STIR  6.3.0
xchar.h
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 
8 #ifndef FMT_XCHAR_H_
9 #define FMT_XCHAR_H_
10 
11 #include "color.h"
12 #include "format.h"
13 #include "ostream.h"
14 #include "ranges.h"
15 
16 #ifndef FMT_MODULE
17 # include <cwchar>
18 # if FMT_USE_LOCALE
19 # include <locale>
20 # endif
21 #endif
22 
23 FMT_BEGIN_NAMESPACE
24 namespace detail {
25 
26 template <typename T>
27 using is_exotic_char = bool_constant<!std::is_same<T, char>::value>;
28 
29 template <typename S, typename = void> struct format_string_char {};
30 
31 template <typename S>
32 struct format_string_char<
33  S, void_t<decltype(sizeof(detail::to_string_view(std::declval<S>())))>> {
34  using type = char_t<S>;
35 };
36 
37 template <typename S>
38 struct format_string_char<
39  S, enable_if_t<std::is_base_of<detail::compile_string, S>::value>> {
40  using type = typename S::char_type;
41 };
42 
43 template <typename S>
44 using format_string_char_t = typename format_string_char<S>::type;
45 
46 inline auto write_loc(basic_appender<wchar_t> out, loc_value value,
47  const format_specs& specs, locale_ref loc) -> bool {
48 #if FMT_USE_LOCALE
49  auto& numpunct =
50  std::use_facet<std::numpunct<wchar_t>>(loc.get<std::locale>());
51  auto separator = std::wstring();
52  auto grouping = numpunct.grouping();
53  if (!grouping.empty()) separator = std::wstring(1, numpunct.thousands_sep());
54  return value.visit(loc_writer<wchar_t>{out, specs, separator, grouping, {}});
55 #endif
56  return false;
57 }
58 
59 template <typename Char>
60 void vformat_to(buffer<Char>& buf, basic_string_view<Char> fmt,
61  basic_format_args<buffered_context<Char>> args,
62  locale_ref loc = {}) {
63  static_assert(!std::is_same<Char, char>::value, "");
64  auto out = basic_appender<Char>(buf);
65  parse_format_string(
66  fmt, format_handler<Char>{parse_context<Char>(fmt), {out, args, loc}});
67 }
68 } // namespace detail
69 
70 FMT_BEGIN_EXPORT
71 
74 using wformat_context = buffered_context<wchar_t>;
77 
78 template <typename Char, typename... T> struct basic_fstring {
79  private:
81 
82  static constexpr int num_static_named_args =
83  detail::count_static_named_args<T...>();
84 
85  using checker = detail::format_string_checker<
86  Char, static_cast<int>(sizeof...(T)), num_static_named_args,
87  num_static_named_args != detail::count_named_args<T...>()>;
88 
89  using arg_pack = detail::arg_pack<T...>;
90 
91  public:
92  using t = basic_fstring;
93 
94  template <typename S,
95  FMT_ENABLE_IF(
96  std::is_convertible<const S&, basic_string_view<Char>>::value)>
97  FMT_CONSTEVAL FMT_ALWAYS_INLINE basic_fstring(const S& s) : str_(s) {
98  if (FMT_USE_CONSTEVAL)
99  detail::parse_format_string<Char>(s, checker(s, arg_pack()));
100  }
101  template <typename S,
102  FMT_ENABLE_IF(std::is_base_of<detail::compile_string, S>::value&&
103  std::is_same<typename S::char_type, Char>::value)>
104  FMT_ALWAYS_INLINE basic_fstring(const S&) : str_(S()) {
105  FMT_CONSTEXPR auto sv = basic_string_view<Char>(S());
106  FMT_CONSTEXPR int ignore =
107  (parse_format_string(sv, checker(sv, arg_pack())), 0);
108  detail::ignore_unused(ignore);
109  }
110  basic_fstring(runtime_format_string<Char> fmt) : str_(fmt.str) {}
111 
112  operator basic_string_view<Char>() const { return str_; }
113  auto get() const -> basic_string_view<Char> { return str_; }
114 };
115 
116 template <typename Char, typename... T>
117 using basic_format_string = basic_fstring<Char, T...>;
118 
119 template <typename... T>
120 using wformat_string = typename basic_format_string<wchar_t, T...>::t;
121 inline auto runtime(wstring_view s) -> runtime_format_string<wchar_t> {
122  return {{s}};
123 }
124 
125 template <typename... T>
126 constexpr auto make_wformat_args(T&... args)
127  -> decltype(fmt::make_format_args<wformat_context>(args...)) {
128  return fmt::make_format_args<wformat_context>(args...);
129 }
130 
131 #if !FMT_USE_NONTYPE_TEMPLATE_ARGS
132 inline namespace literals {
133 inline auto operator""_a(const wchar_t* s, size_t) -> detail::udl_arg<wchar_t> {
134  return {s};
135 }
136 } // namespace literals
137 #endif
138 
139 template <typename It, typename Sentinel>
140 auto join(It begin, Sentinel end, wstring_view sep)
141  -> join_view<It, Sentinel, wchar_t> {
142  return {begin, end, sep};
143 }
144 
145 template <typename Range, FMT_ENABLE_IF(!is_tuple_like<Range>::value)>
146 auto join(Range&& range, wstring_view sep)
147  -> join_view<decltype(std::begin(range)), decltype(std::end(range)),
148  wchar_t> {
149  return join(std::begin(range), std::end(range), sep);
150 }
151 
152 template <typename T>
153 auto join(std::initializer_list<T> list, wstring_view sep)
154  -> join_view<const T*, const T*, wchar_t> {
155  return join(std::begin(list), std::end(list), sep);
156 }
157 
158 template <typename Tuple, FMT_ENABLE_IF(is_tuple_like<Tuple>::value)>
159 auto join(const Tuple& tuple, basic_string_view<wchar_t> sep)
160  -> tuple_join_view<Tuple, wchar_t> {
161  return {tuple, sep};
162 }
163 
164 template <typename Char, FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
165 auto vformat(basic_string_view<Char> fmt,
166  basic_format_args<buffered_context<Char>> args)
167  -> std::basic_string<Char> {
168  auto buf = basic_memory_buffer<Char>();
169  detail::vformat_to(buf, fmt, args);
170  return {buf.data(), buf.size()};
171 }
172 
173 template <typename... T>
174 auto format(wformat_string<T...> fmt, T&&... args) -> std::wstring {
175  return vformat(fmt::wstring_view(fmt), fmt::make_wformat_args(args...));
176 }
177 
178 template <typename OutputIt, typename... T>
179 auto format_to(OutputIt out, wformat_string<T...> fmt, T&&... args)
180  -> OutputIt {
181  return vformat_to(out, fmt::wstring_view(fmt),
182  fmt::make_wformat_args(args...));
183 }
184 
185 // Pass char_t as a default template parameter instead of using
186 // std::basic_string<char_t<S>> to reduce the symbol size.
187 template <typename S, typename... T,
188  typename Char = detail::format_string_char_t<S>,
189  FMT_ENABLE_IF(!std::is_same<Char, char>::value &&
190  !std::is_same<Char, wchar_t>::value)>
191 auto format(const S& fmt, T&&... args) -> std::basic_string<Char> {
192  return vformat(detail::to_string_view(fmt),
193  fmt::make_format_args<buffered_context<Char>>(args...));
194 }
195 
196 template <typename S, typename Char = detail::format_string_char_t<S>,
197  FMT_ENABLE_IF(detail::is_exotic_char<Char>::value)>
198 inline auto vformat(locale_ref loc, const S& fmt,
199  basic_format_args<buffered_context<Char>> args)
200  -> std::basic_string<Char> {
201  auto buf = basic_memory_buffer<Char>();
202  detail::vformat_to(buf, detail::to_string_view(fmt), args, loc);
203  return {buf.data(), buf.size()};
204 }
205 
206 template <typename S, typename... T,
207  typename Char = detail::format_string_char_t<S>,
208  FMT_ENABLE_IF(detail::is_exotic_char<Char>::value)>
209 inline auto format(locale_ref loc, const S& fmt, T&&... args)
210  -> std::basic_string<Char> {
211  return vformat(loc, detail::to_string_view(fmt),
212  fmt::make_format_args<buffered_context<Char>>(args...));
213 }
214 
215 template <typename OutputIt, typename S,
216  typename Char = detail::format_string_char_t<S>,
217  FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
218  detail::is_exotic_char<Char>::value)>
219 auto vformat_to(OutputIt out, const S& fmt,
220  basic_format_args<buffered_context<Char>> args) -> OutputIt {
221  auto&& buf = detail::get_buffer<Char>(out);
222  detail::vformat_to(buf, detail::to_string_view(fmt), args);
223  return detail::get_iterator(buf, out);
224 }
225 
226 template <typename OutputIt, typename S, typename... T,
227  typename Char = detail::format_string_char_t<S>,
228  FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value &&
229  !std::is_same<Char, char>::value &&
230  !std::is_same<Char, wchar_t>::value)>
231 inline auto format_to(OutputIt out, const S& fmt, T&&... args) -> OutputIt {
232  return vformat_to(out, detail::to_string_view(fmt),
233  fmt::make_format_args<buffered_context<Char>>(args...));
234 }
235 
236 template <typename S, typename OutputIt, typename... Args,
237  typename Char = detail::format_string_char_t<S>,
238  FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
239  detail::is_exotic_char<Char>::value)>
240 inline auto vformat_to(OutputIt out, locale_ref loc, const S& fmt,
241  basic_format_args<buffered_context<Char>> args)
242  -> OutputIt {
243  auto&& buf = detail::get_buffer<Char>(out);
244  vformat_to(buf, detail::to_string_view(fmt), args, loc);
245  return detail::get_iterator(buf, out);
246 }
247 
248 template <typename OutputIt, typename S, typename... T,
249  typename Char = detail::format_string_char_t<S>,
250  bool enable = detail::is_output_iterator<OutputIt, Char>::value &&
251  detail::is_exotic_char<Char>::value>
252 inline auto format_to(OutputIt out, locale_ref loc, const S& fmt, T&&... args)
253  -> typename std::enable_if<enable, OutputIt>::type {
254  return vformat_to(out, loc, detail::to_string_view(fmt),
255  fmt::make_format_args<buffered_context<Char>>(args...));
256 }
257 
258 template <typename OutputIt, typename Char, typename... Args,
259  FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
260  detail::is_exotic_char<Char>::value)>
261 inline auto vformat_to_n(OutputIt out, size_t n, basic_string_view<Char> fmt,
262  basic_format_args<buffered_context<Char>> args)
263  -> format_to_n_result<OutputIt> {
264  using traits = detail::fixed_buffer_traits;
265  auto buf = detail::iterator_buffer<OutputIt, Char, traits>(out, n);
266  detail::vformat_to(buf, fmt, args);
267  return {buf.out(), buf.count()};
268 }
269 
270 template <typename OutputIt, typename S, typename... T,
271  typename Char = detail::format_string_char_t<S>,
272  FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
273  detail::is_exotic_char<Char>::value)>
274 inline auto format_to_n(OutputIt out, size_t n, const S& fmt, T&&... args)
275  -> format_to_n_result<OutputIt> {
276  return vformat_to_n(out, n, fmt::basic_string_view<Char>(fmt),
277  fmt::make_format_args<buffered_context<Char>>(args...));
278 }
279 
280 template <typename S, typename... T,
281  typename Char = detail::format_string_char_t<S>,
282  FMT_ENABLE_IF(detail::is_exotic_char<Char>::value)>
283 inline auto formatted_size(const S& fmt, T&&... args) -> size_t {
284  auto buf = detail::counting_buffer<Char>();
285  detail::vformat_to(buf, detail::to_string_view(fmt),
286  fmt::make_format_args<buffered_context<Char>>(args...));
287  return buf.count();
288 }
289 
290 inline void vprint(std::FILE* f, wstring_view fmt, wformat_args args) {
291  auto buf = wmemory_buffer();
292  detail::vformat_to(buf, fmt, args);
293  buf.push_back(L'\0');
294  if (std::fputws(buf.data(), f) == -1)
295  FMT_THROW(system_error(errno, FMT_STRING("cannot write to file")));
296 }
297 
298 inline void vprint(wstring_view fmt, wformat_args args) {
299  vprint(stdout, fmt, args);
300 }
301 
302 template <typename... T>
303 void print(std::FILE* f, wformat_string<T...> fmt, T&&... args) {
304  return vprint(f, wstring_view(fmt), fmt::make_wformat_args(args...));
305 }
306 
307 template <typename... T> void print(wformat_string<T...> fmt, T&&... args) {
308  return vprint(wstring_view(fmt), fmt::make_wformat_args(args...));
309 }
310 
311 template <typename... T>
312 void println(std::FILE* f, wformat_string<T...> fmt, T&&... args) {
313  return print(f, L"{}\n", fmt::format(fmt, std::forward<T>(args)...));
314 }
315 
316 template <typename... T> void println(wformat_string<T...> fmt, T&&... args) {
317  return print(L"{}\n", fmt::format(fmt, std::forward<T>(args)...));
318 }
319 
320 inline auto vformat(text_style ts, wstring_view fmt, wformat_args args)
321  -> std::wstring {
322  auto buf = wmemory_buffer();
323  detail::vformat_to(buf, ts, fmt, args);
324  return {buf.data(), buf.size()};
325 }
326 
327 template <typename... T>
328 inline auto format(text_style ts, wformat_string<T...> fmt, T&&... args)
329  -> std::wstring {
330  return fmt::vformat(ts, fmt, fmt::make_wformat_args(args...));
331 }
332 
333 inline void vprint(std::wostream& os, wstring_view fmt, wformat_args args) {
334  auto buffer = basic_memory_buffer<wchar_t>();
335  detail::vformat_to(buffer, fmt, args);
336  detail::write_buffer(os, buffer);
337 }
338 
339 template <typename... T>
340 void print(std::wostream& os, wformat_string<T...> fmt, T&&... args) {
341  vprint(os, fmt, fmt::make_format_args<buffered_context<wchar_t>>(args...));
342 }
343 
344 template <typename... T>
345 void println(std::wostream& os, wformat_string<T...> fmt, T&&... args) {
346  print(os, L"{}\n", fmt::format(fmt, std::forward<T>(args)...));
347 }
348 
350 template <typename T> inline auto to_wstring(const T& value) -> std::wstring {
351  return format(FMT_STRING(L"{}"), value);
352 }
353 FMT_END_EXPORT
354 FMT_END_NAMESPACE
355 
356 #endif // FMT_XCHAR_H_
BasicCoordinate< num_dimensions+1, coordT > join(const coordT &a, const BasicCoordinate< num_dimensions, coordT > &c)
make a longer BasicCoordinate, by prepending c with the single coordT
Definition: BasicCoordinate.inl:447
Parsing context consisting of a format string range being parsed and an argument counter for automati...
Definition: base.h:623
STL namespace.
Converts a string literal into a format string that will be parsed at compile time and converted into...
Definition: args.h:20
An implementation of std::basic_string_view for pre-C++17.
Definition: base.h:515
A view of a collection of formatting arguments.
Definition: base.h:640
A text style consisting of foreground and background colors and emphasis.
Definition: color.h:236
Definition: format.h:4131