xchar.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  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 "color.h"
  10. #include "format.h"
  11. #include "ranges.h"
  12. #ifndef FMT_MODULE
  13. # include <cwchar>
  14. # if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
  15. # include <locale>
  16. # endif
  17. #endif
  18. FMT_BEGIN_NAMESPACE
  19. namespace detail {
  20. template <typename T>
  21. using is_exotic_char = bool_constant<!std::is_same<T, char>::value>;
  22. template <typename S, typename = void> struct format_string_char {};
  23. template <typename S>
  24. struct format_string_char<
  25. S, void_t<decltype(sizeof(detail::to_string_view(std::declval<S>())))>> {
  26. using type = char_t<S>;
  27. };
  28. template <typename S>
  29. struct format_string_char<S, enable_if_t<is_compile_string<S>::value>> {
  30. using type = typename S::char_type;
  31. };
  32. template <typename S>
  33. using format_string_char_t = typename format_string_char<S>::type;
  34. inline auto write_loc(basic_appender<wchar_t> out, loc_value value,
  35. const format_specs& specs, locale_ref loc) -> bool {
  36. #ifndef FMT_STATIC_THOUSANDS_SEPARATOR
  37. auto& numpunct =
  38. std::use_facet<std::numpunct<wchar_t>>(loc.get<std::locale>());
  39. auto separator = std::wstring();
  40. auto grouping = numpunct.grouping();
  41. if (!grouping.empty()) separator = std::wstring(1, numpunct.thousands_sep());
  42. return value.visit(loc_writer<wchar_t>{out, specs, separator, grouping, {}});
  43. #endif
  44. return false;
  45. }
  46. } // namespace detail
  47. FMT_BEGIN_EXPORT
  48. using wstring_view = basic_string_view<wchar_t>;
  49. using wformat_parse_context = basic_format_parse_context<wchar_t>;
  50. using wformat_context = buffered_context<wchar_t>;
  51. using wformat_args = basic_format_args<wformat_context>;
  52. using wmemory_buffer = basic_memory_buffer<wchar_t>;
  53. #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
  54. // Workaround broken conversion on older gcc.
  55. template <typename... Args> using wformat_string = wstring_view;
  56. inline auto runtime(wstring_view s) -> wstring_view { return s; }
  57. #else
  58. template <typename... Args>
  59. using wformat_string = basic_format_string<wchar_t, type_identity_t<Args>...>;
  60. inline auto runtime(wstring_view s) -> runtime_format_string<wchar_t> {
  61. return {{s}};
  62. }
  63. #endif
  64. template <> struct is_char<wchar_t> : std::true_type {};
  65. template <> struct is_char<char16_t> : std::true_type {};
  66. template <> struct is_char<char32_t> : std::true_type {};
  67. #ifdef __cpp_char8_t
  68. template <>
  69. struct is_char<char8_t> : bool_constant<detail::is_utf8_enabled()> {};
  70. #endif
  71. template <typename... T>
  72. constexpr auto make_wformat_args(T&... args)
  73. -> decltype(fmt::make_format_args<wformat_context>(args...)) {
  74. return fmt::make_format_args<wformat_context>(args...);
  75. }
  76. inline namespace literals {
  77. #if FMT_USE_USER_DEFINED_LITERALS && !FMT_USE_NONTYPE_TEMPLATE_ARGS
  78. constexpr auto operator""_a(const wchar_t* s, size_t)
  79. -> detail::udl_arg<wchar_t> {
  80. return {s};
  81. }
  82. #endif
  83. } // namespace literals
  84. template <typename It, typename Sentinel>
  85. auto join(It begin, Sentinel end, wstring_view sep)
  86. -> join_view<It, Sentinel, wchar_t> {
  87. return {begin, end, sep};
  88. }
  89. template <typename Range>
  90. auto join(Range&& range, wstring_view sep)
  91. -> join_view<detail::iterator_t<Range>, detail::sentinel_t<Range>,
  92. wchar_t> {
  93. return join(std::begin(range), std::end(range), sep);
  94. }
  95. template <typename T>
  96. auto join(std::initializer_list<T> list, wstring_view sep)
  97. -> join_view<const T*, const T*, wchar_t> {
  98. return join(std::begin(list), std::end(list), sep);
  99. }
  100. template <typename... T>
  101. auto join(const std::tuple<T...>& tuple, basic_string_view<wchar_t> sep)
  102. -> tuple_join_view<wchar_t, T...> {
  103. return {tuple, sep};
  104. }
  105. template <typename Char, FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
  106. auto vformat(basic_string_view<Char> format_str,
  107. typename detail::vformat_args<Char>::type args)
  108. -> std::basic_string<Char> {
  109. auto buf = basic_memory_buffer<Char>();
  110. detail::vformat_to(buf, format_str, args);
  111. return to_string(buf);
  112. }
  113. template <typename... T>
  114. auto format(wformat_string<T...> fmt, T&&... args) -> std::wstring {
  115. return vformat(fmt::wstring_view(fmt), fmt::make_wformat_args(args...));
  116. }
  117. template <typename OutputIt, typename... T>
  118. auto format_to(OutputIt out, wformat_string<T...> fmt, T&&... args)
  119. -> OutputIt {
  120. return vformat_to(out, fmt::wstring_view(fmt),
  121. fmt::make_wformat_args(args...));
  122. }
  123. // Pass char_t as a default template parameter instead of using
  124. // std::basic_string<char_t<S>> to reduce the symbol size.
  125. template <typename S, typename... T,
  126. typename Char = detail::format_string_char_t<S>,
  127. FMT_ENABLE_IF(!std::is_same<Char, char>::value &&
  128. !std::is_same<Char, wchar_t>::value)>
  129. auto format(const S& format_str, T&&... args) -> std::basic_string<Char> {
  130. return vformat(detail::to_string_view(format_str),
  131. fmt::make_format_args<buffered_context<Char>>(args...));
  132. }
  133. template <typename Locale, typename S,
  134. typename Char = detail::format_string_char_t<S>,
  135. FMT_ENABLE_IF(detail::is_locale<Locale>::value&&
  136. detail::is_exotic_char<Char>::value)>
  137. inline auto vformat(const Locale& loc, const S& format_str,
  138. typename detail::vformat_args<Char>::type args)
  139. -> std::basic_string<Char> {
  140. return detail::vformat(loc, detail::to_string_view(format_str), args);
  141. }
  142. template <typename Locale, typename S, typename... T,
  143. typename Char = detail::format_string_char_t<S>,
  144. FMT_ENABLE_IF(detail::is_locale<Locale>::value&&
  145. detail::is_exotic_char<Char>::value)>
  146. inline auto format(const Locale& loc, const S& format_str, T&&... args)
  147. -> std::basic_string<Char> {
  148. return detail::vformat(
  149. loc, detail::to_string_view(format_str),
  150. fmt::make_format_args<buffered_context<Char>>(args...));
  151. }
  152. template <typename OutputIt, typename S,
  153. typename Char = detail::format_string_char_t<S>,
  154. FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
  155. detail::is_exotic_char<Char>::value)>
  156. auto vformat_to(OutputIt out, const S& format_str,
  157. typename detail::vformat_args<Char>::type args) -> OutputIt {
  158. auto&& buf = detail::get_buffer<Char>(out);
  159. detail::vformat_to(buf, detail::to_string_view(format_str), args);
  160. return detail::get_iterator(buf, out);
  161. }
  162. template <typename OutputIt, typename S, typename... T,
  163. typename Char = detail::format_string_char_t<S>,
  164. FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value &&
  165. !std::is_same<Char, char>::value &&
  166. !std::is_same<Char, wchar_t>::value)>
  167. inline auto format_to(OutputIt out, const S& fmt, T&&... args) -> OutputIt {
  168. return vformat_to(out, detail::to_string_view(fmt),
  169. fmt::make_format_args<buffered_context<Char>>(args...));
  170. }
  171. template <typename Locale, typename S, typename OutputIt, typename... Args,
  172. typename Char = detail::format_string_char_t<S>,
  173. FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
  174. detail::is_locale<Locale>::value&&
  175. detail::is_exotic_char<Char>::value)>
  176. inline auto vformat_to(OutputIt out, const Locale& loc, const S& format_str,
  177. typename detail::vformat_args<Char>::type args)
  178. -> OutputIt {
  179. auto&& buf = detail::get_buffer<Char>(out);
  180. vformat_to(buf, detail::to_string_view(format_str), args,
  181. detail::locale_ref(loc));
  182. return detail::get_iterator(buf, out);
  183. }
  184. template <typename OutputIt, typename Locale, typename S, typename... T,
  185. typename Char = detail::format_string_char_t<S>,
  186. bool enable = detail::is_output_iterator<OutputIt, Char>::value &&
  187. detail::is_locale<Locale>::value &&
  188. detail::is_exotic_char<Char>::value>
  189. inline auto format_to(OutputIt out, const Locale& loc, const S& format_str,
  190. T&&... args) ->
  191. typename std::enable_if<enable, OutputIt>::type {
  192. return vformat_to(out, loc, detail::to_string_view(format_str),
  193. fmt::make_format_args<buffered_context<Char>>(args...));
  194. }
  195. template <typename OutputIt, typename Char, typename... Args,
  196. FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
  197. detail::is_exotic_char<Char>::value)>
  198. inline auto vformat_to_n(OutputIt out, size_t n,
  199. basic_string_view<Char> format_str,
  200. typename detail::vformat_args<Char>::type args)
  201. -> format_to_n_result<OutputIt> {
  202. using traits = detail::fixed_buffer_traits;
  203. auto buf = detail::iterator_buffer<OutputIt, Char, traits>(out, n);
  204. detail::vformat_to(buf, format_str, args);
  205. return {buf.out(), buf.count()};
  206. }
  207. template <typename OutputIt, typename S, typename... T,
  208. typename Char = detail::format_string_char_t<S>,
  209. FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
  210. detail::is_exotic_char<Char>::value)>
  211. inline auto format_to_n(OutputIt out, size_t n, const S& fmt, T&&... args)
  212. -> format_to_n_result<OutputIt> {
  213. return vformat_to_n(out, n, fmt::basic_string_view<Char>(fmt),
  214. fmt::make_format_args<buffered_context<Char>>(args...));
  215. }
  216. template <typename S, typename... T,
  217. typename Char = detail::format_string_char_t<S>,
  218. FMT_ENABLE_IF(detail::is_exotic_char<Char>::value)>
  219. inline auto formatted_size(const S& fmt, T&&... args) -> size_t {
  220. auto buf = detail::counting_buffer<Char>();
  221. detail::vformat_to(buf, detail::to_string_view(fmt),
  222. fmt::make_format_args<buffered_context<Char>>(args...));
  223. return buf.count();
  224. }
  225. inline void vprint(std::FILE* f, wstring_view fmt, wformat_args args) {
  226. auto buf = wmemory_buffer();
  227. detail::vformat_to(buf, fmt, args);
  228. buf.push_back(L'\0');
  229. if (std::fputws(buf.data(), f) == -1)
  230. FMT_THROW(system_error(errno, FMT_STRING("cannot write to file")));
  231. }
  232. inline void vprint(wstring_view fmt, wformat_args args) {
  233. vprint(stdout, fmt, args);
  234. }
  235. template <typename... T>
  236. void print(std::FILE* f, wformat_string<T...> fmt, T&&... args) {
  237. return vprint(f, wstring_view(fmt), fmt::make_wformat_args(args...));
  238. }
  239. template <typename... T> void print(wformat_string<T...> fmt, T&&... args) {
  240. return vprint(wstring_view(fmt), fmt::make_wformat_args(args...));
  241. }
  242. template <typename... T>
  243. void println(std::FILE* f, wformat_string<T...> fmt, T&&... args) {
  244. return print(f, L"{}\n", fmt::format(fmt, std::forward<T>(args)...));
  245. }
  246. template <typename... T> void println(wformat_string<T...> fmt, T&&... args) {
  247. return print(L"{}\n", fmt::format(fmt, std::forward<T>(args)...));
  248. }
  249. inline auto vformat(const text_style& ts, wstring_view fmt, wformat_args args)
  250. -> std::wstring {
  251. auto buf = wmemory_buffer();
  252. detail::vformat_to(buf, ts, fmt, args);
  253. return fmt::to_string(buf);
  254. }
  255. template <typename... T>
  256. inline auto format(const text_style& ts, wformat_string<T...> fmt, T&&... args)
  257. -> std::wstring {
  258. return fmt::vformat(ts, fmt, fmt::make_wformat_args(args...));
  259. }
  260. template <typename... T>
  261. FMT_DEPRECATED void print(std::FILE* f, const text_style& ts,
  262. wformat_string<T...> fmt, const T&... args) {
  263. vprint(f, ts, fmt, fmt::make_wformat_args(args...));
  264. }
  265. template <typename... T>
  266. FMT_DEPRECATED void print(const text_style& ts, wformat_string<T...> fmt,
  267. const T&... args) {
  268. return print(stdout, ts, fmt, args...);
  269. }
  270. /// Converts `value` to `std::wstring` using the default format for type `T`.
  271. template <typename T> inline auto to_wstring(const T& value) -> std::wstring {
  272. return format(FMT_STRING(L"{}"), value);
  273. }
  274. FMT_END_EXPORT
  275. FMT_END_NAMESPACE
  276. #endif // FMT_XCHAR_H_