You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

229 lines
8.8 KiB

  1. // Formatting library for C++ - optional wchar_t and exotic character support
  2. //
  3. // Copyright (c) 2012 - present, Victor Zverovich
  4. // All rights reserved.
  5. //
  6. // For the license information refer to format.h.
  7. #ifndef FMT_XCHAR_H_
  8. #define FMT_XCHAR_H_
  9. #include <cwchar>
  10. #include "format.h"
  11. FMT_BEGIN_NAMESPACE
  12. namespace detail {
  13. template <typename T>
  14. using is_exotic_char = bool_constant<!std::is_same<T, char>::value>;
  15. }
  16. FMT_MODULE_EXPORT_BEGIN
  17. using wstring_view = basic_string_view<wchar_t>;
  18. using wformat_parse_context = basic_format_parse_context<wchar_t>;
  19. using wformat_context = buffer_context<wchar_t>;
  20. using wformat_args = basic_format_args<wformat_context>;
  21. using wmemory_buffer = basic_memory_buffer<wchar_t>;
  22. #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
  23. // Workaround broken conversion on older gcc.
  24. template <typename... Args> using wformat_string = wstring_view;
  25. inline auto runtime(wstring_view s) -> wstring_view { return s; }
  26. #else
  27. template <typename... Args>
  28. using wformat_string = basic_format_string<wchar_t, type_identity_t<Args>...>;
  29. inline auto runtime(wstring_view s) -> basic_runtime<wchar_t> { return {{s}}; }
  30. #endif
  31. template <> struct is_char<wchar_t> : std::true_type {};
  32. template <> struct is_char<detail::char8_type> : std::true_type {};
  33. template <> struct is_char<char16_t> : std::true_type {};
  34. template <> struct is_char<char32_t> : std::true_type {};
  35. template <typename... Args>
  36. constexpr format_arg_store<wformat_context, Args...> make_wformat_args(
  37. const Args&... args) {
  38. return {args...};
  39. }
  40. inline namespace literals {
  41. #if FMT_USE_USER_DEFINED_LITERALS && !FMT_USE_NONTYPE_TEMPLATE_ARGS
  42. constexpr detail::udl_arg<wchar_t> operator"" _a(const wchar_t* s, size_t) {
  43. return {s};
  44. }
  45. #endif
  46. } // namespace literals
  47. template <typename It, typename Sentinel>
  48. auto join(It begin, Sentinel end, wstring_view sep)
  49. -> join_view<It, Sentinel, wchar_t> {
  50. return {begin, end, sep};
  51. }
  52. template <typename Range>
  53. auto join(Range&& range, wstring_view sep)
  54. -> join_view<detail::iterator_t<Range>, detail::sentinel_t<Range>,
  55. wchar_t> {
  56. return join(std::begin(range), std::end(range), sep);
  57. }
  58. template <typename T>
  59. auto join(std::initializer_list<T> list, wstring_view sep)
  60. -> join_view<const T*, const T*, wchar_t> {
  61. return join(std::begin(list), std::end(list), sep);
  62. }
  63. template <typename Char, FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
  64. auto vformat(basic_string_view<Char> format_str,
  65. basic_format_args<buffer_context<type_identity_t<Char>>> args)
  66. -> std::basic_string<Char> {
  67. basic_memory_buffer<Char> buffer;
  68. detail::vformat_to(buffer, format_str, args);
  69. return to_string(buffer);
  70. }
  71. template <typename... T>
  72. auto format(wformat_string<T...> fmt, T&&... args) -> std::wstring {
  73. return vformat(fmt::wstring_view(fmt), fmt::make_wformat_args(args...));
  74. }
  75. // Pass char_t as a default template parameter instead of using
  76. // std::basic_string<char_t<S>> to reduce the symbol size.
  77. template <typename S, typename... Args, typename Char = char_t<S>,
  78. FMT_ENABLE_IF(!std::is_same<Char, char>::value &&
  79. !std::is_same<Char, wchar_t>::value)>
  80. auto format(const S& format_str, Args&&... args) -> std::basic_string<Char> {
  81. return vformat(detail::to_string_view(format_str),
  82. fmt::make_format_args<buffer_context<Char>>(args...));
  83. }
  84. template <typename Locale, typename S, typename Char = char_t<S>,
  85. FMT_ENABLE_IF(detail::is_locale<Locale>::value&&
  86. detail::is_exotic_char<Char>::value)>
  87. inline auto vformat(
  88. const Locale& loc, const S& format_str,
  89. basic_format_args<buffer_context<type_identity_t<Char>>> args)
  90. -> std::basic_string<Char> {
  91. return detail::vformat(loc, detail::to_string_view(format_str), args);
  92. }
  93. template <typename Locale, typename S, typename... Args,
  94. typename Char = char_t<S>,
  95. FMT_ENABLE_IF(detail::is_locale<Locale>::value&&
  96. detail::is_exotic_char<Char>::value)>
  97. inline auto format(const Locale& loc, const S& format_str, Args&&... args)
  98. -> std::basic_string<Char> {
  99. return detail::vformat(loc, detail::to_string_view(format_str),
  100. fmt::make_format_args<buffer_context<Char>>(args...));
  101. }
  102. template <typename OutputIt, typename S, typename Char = char_t<S>,
  103. FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
  104. detail::is_exotic_char<Char>::value)>
  105. auto vformat_to(OutputIt out, const S& format_str,
  106. basic_format_args<buffer_context<type_identity_t<Char>>> args)
  107. -> OutputIt {
  108. auto&& buf = detail::get_buffer<Char>(out);
  109. detail::vformat_to(buf, detail::to_string_view(format_str), args);
  110. return detail::get_iterator(buf);
  111. }
  112. template <typename OutputIt, typename S, typename... Args,
  113. typename Char = char_t<S>,
  114. FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
  115. detail::is_exotic_char<Char>::value)>
  116. inline auto format_to(OutputIt out, const S& fmt, Args&&... args) -> OutputIt {
  117. return vformat_to(out, detail::to_string_view(fmt),
  118. fmt::make_format_args<buffer_context<Char>>(args...));
  119. }
  120. template <typename Locale, typename S, typename OutputIt, typename... Args,
  121. typename Char = char_t<S>,
  122. FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
  123. detail::is_locale<Locale>::value&&
  124. detail::is_exotic_char<Char>::value)>
  125. inline auto vformat_to(
  126. OutputIt out, const Locale& loc, const S& format_str,
  127. basic_format_args<buffer_context<type_identity_t<Char>>> args) -> OutputIt {
  128. auto&& buf = detail::get_buffer<Char>(out);
  129. vformat_to(buf, detail::to_string_view(format_str), args,
  130. detail::locale_ref(loc));
  131. return detail::get_iterator(buf);
  132. }
  133. template <
  134. typename OutputIt, typename Locale, typename S, typename... Args,
  135. typename Char = char_t<S>,
  136. bool enable = detail::is_output_iterator<OutputIt, Char>::value&&
  137. detail::is_locale<Locale>::value&& detail::is_exotic_char<Char>::value>
  138. inline auto format_to(OutputIt out, const Locale& loc, const S& format_str,
  139. Args&&... args) ->
  140. typename std::enable_if<enable, OutputIt>::type {
  141. return vformat_to(out, loc, to_string_view(format_str),
  142. fmt::make_format_args<buffer_context<Char>>(args...));
  143. }
  144. template <typename OutputIt, typename Char, typename... Args,
  145. FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
  146. detail::is_exotic_char<Char>::value)>
  147. inline auto vformat_to_n(
  148. OutputIt out, size_t n, basic_string_view<Char> format_str,
  149. basic_format_args<buffer_context<type_identity_t<Char>>> args)
  150. -> format_to_n_result<OutputIt> {
  151. detail::iterator_buffer<OutputIt, Char, detail::fixed_buffer_traits> buf(out,
  152. n);
  153. detail::vformat_to(buf, format_str, args);
  154. return {buf.out(), buf.count()};
  155. }
  156. template <typename OutputIt, typename S, typename... Args,
  157. typename Char = char_t<S>,
  158. FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
  159. detail::is_exotic_char<Char>::value)>
  160. inline auto format_to_n(OutputIt out, size_t n, const S& fmt,
  161. const Args&... args) -> format_to_n_result<OutputIt> {
  162. return vformat_to_n(out, n, detail::to_string_view(fmt),
  163. fmt::make_format_args<buffer_context<Char>>(args...));
  164. }
  165. template <typename S, typename... Args, typename Char = char_t<S>,
  166. FMT_ENABLE_IF(detail::is_exotic_char<Char>::value)>
  167. inline auto formatted_size(const S& fmt, Args&&... args) -> size_t {
  168. detail::counting_buffer<Char> buf;
  169. detail::vformat_to(buf, detail::to_string_view(fmt),
  170. fmt::make_format_args<buffer_context<Char>>(args...));
  171. return buf.count();
  172. }
  173. inline void vprint(std::FILE* f, wstring_view fmt, wformat_args args) {
  174. wmemory_buffer buffer;
  175. detail::vformat_to(buffer, fmt, args);
  176. buffer.push_back(L'\0');
  177. if (std::fputws(buffer.data(), f) == -1)
  178. FMT_THROW(system_error(errno, FMT_STRING("cannot write to file")));
  179. }
  180. inline void vprint(wstring_view fmt, wformat_args args) {
  181. vprint(stdout, fmt, args);
  182. }
  183. template <typename... T>
  184. void print(std::FILE* f, wformat_string<T...> fmt, T&&... args) {
  185. return vprint(f, wstring_view(fmt), fmt::make_wformat_args(args...));
  186. }
  187. template <typename... T> void print(wformat_string<T...> fmt, T&&... args) {
  188. return vprint(wstring_view(fmt), fmt::make_wformat_args(args...));
  189. }
  190. /**
  191. Converts *value* to ``std::wstring`` using the default format for type *T*.
  192. */
  193. template <typename T> inline auto to_wstring(const T& value) -> std::wstring {
  194. return format(FMT_STRING(L"{}"), value);
  195. }
  196. FMT_MODULE_EXPORT_END
  197. FMT_END_NAMESPACE
  198. #endif // FMT_XCHAR_H_