1 | // Formatting library for C++ - the core API |
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_CORE_H_ |
9 | #define FMT_CORE_H_ |
10 | |
11 | #include <cstdio> // std::FILE |
12 | #include <cstring> |
13 | #include <iterator> |
14 | #include <string> |
15 | #include <type_traits> |
16 | |
17 | // The fmt library version in the form major * 10000 + minor * 100 + patch. |
18 | #define FMT_VERSION 60102 |
19 | |
20 | #ifdef __has_feature |
21 | # define FMT_HAS_FEATURE(x) __has_feature(x) |
22 | #else |
23 | # define FMT_HAS_FEATURE(x) 0 |
24 | #endif |
25 | |
26 | #if defined(__has_include) && !defined(__INTELLISENSE__) && \ |
27 | !(defined(__INTEL_COMPILER) && __INTEL_COMPILER < 1600) |
28 | # define FMT_HAS_INCLUDE(x) __has_include(x) |
29 | #else |
30 | # define FMT_HAS_INCLUDE(x) 0 |
31 | #endif |
32 | |
33 | #ifdef __has_cpp_attribute |
34 | # define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) |
35 | #else |
36 | # define FMT_HAS_CPP_ATTRIBUTE(x) 0 |
37 | #endif |
38 | |
39 | #if defined(__GNUC__) && !defined(__clang__) |
40 | # define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) |
41 | #else |
42 | # define FMT_GCC_VERSION 0 |
43 | #endif |
44 | |
45 | #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) |
46 | # define FMT_HAS_GXX_CXX11 FMT_GCC_VERSION |
47 | #else |
48 | # define FMT_HAS_GXX_CXX11 0 |
49 | #endif |
50 | |
51 | #ifdef __NVCC__ |
52 | # define FMT_NVCC __NVCC__ |
53 | #else |
54 | # define FMT_NVCC 0 |
55 | #endif |
56 | |
57 | #ifdef _MSC_VER |
58 | # define FMT_MSC_VER _MSC_VER |
59 | #else |
60 | # define FMT_MSC_VER 0 |
61 | #endif |
62 | |
63 | // Check if relaxed C++14 constexpr is supported. |
64 | // GCC doesn't allow throw in constexpr until version 6 (bug 67371). |
65 | #ifndef FMT_USE_CONSTEXPR |
66 | # define FMT_USE_CONSTEXPR \ |
67 | (FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VER >= 1910 || \ |
68 | (FMT_GCC_VERSION >= 600 && __cplusplus >= 201402L)) && \ |
69 | !FMT_NVCC |
70 | #endif |
71 | #if FMT_USE_CONSTEXPR |
72 | # define FMT_CONSTEXPR constexpr |
73 | # define FMT_CONSTEXPR_DECL constexpr |
74 | #else |
75 | # define FMT_CONSTEXPR inline |
76 | # define FMT_CONSTEXPR_DECL |
77 | #endif |
78 | |
79 | #ifndef FMT_OVERRIDE |
80 | # if FMT_HAS_FEATURE(cxx_override) || \ |
81 | (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900 |
82 | # define FMT_OVERRIDE override |
83 | # else |
84 | # define FMT_OVERRIDE |
85 | # endif |
86 | #endif |
87 | |
88 | // Check if exceptions are disabled. |
89 | #ifndef FMT_EXCEPTIONS |
90 | # if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || \ |
91 | FMT_MSC_VER && !_HAS_EXCEPTIONS |
92 | # define FMT_EXCEPTIONS 0 |
93 | # else |
94 | # define FMT_EXCEPTIONS 1 |
95 | # endif |
96 | #endif |
97 | |
98 | // Define FMT_USE_NOEXCEPT to make fmt use noexcept (C++11 feature). |
99 | #ifndef FMT_USE_NOEXCEPT |
100 | # define FMT_USE_NOEXCEPT 0 |
101 | #endif |
102 | |
103 | #if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \ |
104 | (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900 |
105 | # define FMT_DETECTED_NOEXCEPT noexcept |
106 | # define FMT_HAS_CXX11_NOEXCEPT 1 |
107 | #else |
108 | # define FMT_DETECTED_NOEXCEPT throw() |
109 | # define FMT_HAS_CXX11_NOEXCEPT 0 |
110 | #endif |
111 | |
112 | #ifndef FMT_NOEXCEPT |
113 | # if FMT_EXCEPTIONS || FMT_HAS_CXX11_NOEXCEPT |
114 | # define FMT_NOEXCEPT FMT_DETECTED_NOEXCEPT |
115 | # else |
116 | # define FMT_NOEXCEPT |
117 | # endif |
118 | #endif |
119 | |
120 | // [[noreturn]] is disabled on MSVC because of bogus unreachable code warnings. |
121 | #if FMT_EXCEPTIONS && FMT_HAS_CPP_ATTRIBUTE(noreturn) && !FMT_MSC_VER |
122 | # define FMT_NORETURN [[noreturn]] |
123 | #else |
124 | # define FMT_NORETURN |
125 | #endif |
126 | |
127 | #ifndef FMT_DEPRECATED |
128 | # if (FMT_HAS_CPP_ATTRIBUTE(deprecated) && __cplusplus >= 201402L) || \ |
129 | FMT_MSC_VER >= 1900 |
130 | # define FMT_DEPRECATED [[deprecated]] |
131 | # else |
132 | # if defined(__GNUC__) || defined(__clang__) |
133 | # define FMT_DEPRECATED __attribute__((deprecated)) |
134 | # elif FMT_MSC_VER |
135 | # define FMT_DEPRECATED __declspec(deprecated) |
136 | # else |
137 | # define FMT_DEPRECATED /* deprecated */ |
138 | # endif |
139 | # endif |
140 | #endif |
141 | |
142 | // Workaround broken [[deprecated]] in the Intel compiler and NVCC. |
143 | #if defined(__INTEL_COMPILER) || FMT_NVCC |
144 | # define FMT_DEPRECATED_ALIAS |
145 | #else |
146 | # define FMT_DEPRECATED_ALIAS FMT_DEPRECATED |
147 | #endif |
148 | |
149 | #ifndef FMT_BEGIN_NAMESPACE |
150 | # if FMT_HAS_FEATURE(cxx_inline_namespaces) || FMT_GCC_VERSION >= 404 || \ |
151 | FMT_MSC_VER >= 1900 |
152 | # define FMT_INLINE_NAMESPACE inline namespace |
153 | # define FMT_END_NAMESPACE \ |
154 | } \ |
155 | } |
156 | # else |
157 | # define FMT_INLINE_NAMESPACE namespace |
158 | # define FMT_END_NAMESPACE \ |
159 | } \ |
160 | using namespace v6; \ |
161 | } |
162 | # endif |
163 | # define FMT_BEGIN_NAMESPACE \ |
164 | namespace fmt { \ |
165 | FMT_INLINE_NAMESPACE v6 { |
166 | #endif |
167 | |
168 | #if !defined(FMT_HEADER_ONLY) && defined(_WIN32) |
169 | # ifdef FMT_EXPORT |
170 | # define FMT_API __declspec(dllexport) |
171 | # elif defined(FMT_SHARED) |
172 | # define FMT_API __declspec(dllimport) |
173 | # define FMT_EXTERN_TEMPLATE_API FMT_API |
174 | # endif |
175 | #endif |
176 | #ifndef FMT_API |
177 | # define FMT_API |
178 | #endif |
179 | #ifndef FMT_EXTERN_TEMPLATE_API |
180 | # define FMT_EXTERN_TEMPLATE_API |
181 | #endif |
182 | |
183 | #ifndef FMT_HEADER_ONLY |
184 | # define FMT_EXTERN extern |
185 | #else |
186 | # define FMT_EXTERN |
187 | #endif |
188 | |
189 | // libc++ supports string_view in pre-c++17. |
190 | #if (FMT_HAS_INCLUDE(<string_view>) && \ |
191 | (__cplusplus > 201402L || defined(_LIBCPP_VERSION))) || \ |
192 | (defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910) |
193 | # include <string_view> |
194 | # define FMT_USE_STRING_VIEW |
195 | #elif FMT_HAS_INCLUDE("experimental/string_view") && __cplusplus >= 201402L |
196 | # include <experimental/string_view> |
197 | # define FMT_USE_EXPERIMENTAL_STRING_VIEW |
198 | #endif |
199 | |
200 | FMT_BEGIN_NAMESPACE |
201 | |
202 | // Implementations of enable_if_t and other types for pre-C++14 systems. |
203 | template <bool B, class T = void> |
204 | using enable_if_t = typename std::enable_if<B, T>::type; |
205 | template <bool B, class T, class F> |
206 | using conditional_t = typename std::conditional<B, T, F>::type; |
207 | template <bool B> using bool_constant = std::integral_constant<bool, B>; |
208 | template <typename T> |
209 | using remove_reference_t = typename std::remove_reference<T>::type; |
210 | template <typename T> |
211 | using remove_const_t = typename std::remove_const<T>::type; |
212 | template <typename T> |
213 | using remove_cvref_t = typename std::remove_cv<remove_reference_t<T>>::type; |
214 | |
215 | struct monostate {}; |
216 | |
217 | // An enable_if helper to be used in template parameters which results in much |
218 | // shorter symbols: https://godbolt.org/z/sWw4vP. Extra parentheses are needed |
219 | // to workaround a bug in MSVC 2019 (see #1140 and #1186). |
220 | #define FMT_ENABLE_IF(...) enable_if_t<(__VA_ARGS__), int> = 0 |
221 | |
222 | namespace internal { |
223 | |
224 | // A workaround for gcc 4.8 to make void_t work in a SFINAE context. |
225 | template <typename... Ts> struct void_t_impl { using type = void; }; |
226 | |
227 | FMT_API void assert_fail(const char* file, int line, const char* message); |
228 | |
229 | #ifndef FMT_ASSERT |
230 | # ifdef NDEBUG |
231 | # define FMT_ASSERT(condition, message) |
232 | # else |
233 | # define FMT_ASSERT(condition, message) \ |
234 | ((condition) \ |
235 | ? void() \ |
236 | : fmt::internal::assert_fail(__FILE__, __LINE__, (message))) |
237 | # endif |
238 | #endif |
239 | |
240 | #if defined(FMT_USE_STRING_VIEW) |
241 | template <typename Char> using std_string_view = std::basic_string_view<Char>; |
242 | #elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW) |
243 | template <typename Char> |
244 | using std_string_view = std::experimental::basic_string_view<Char>; |
245 | #else |
246 | template <typename T> struct std_string_view {}; |
247 | #endif |
248 | |
249 | #ifdef FMT_USE_INT128 |
250 | // Do nothing. |
251 | #elif defined(__SIZEOF_INT128__) |
252 | # define FMT_USE_INT128 1 |
253 | using int128_t = __int128_t; |
254 | using uint128_t = __uint128_t; |
255 | #else |
256 | # define FMT_USE_INT128 0 |
257 | #endif |
258 | #if !FMT_USE_INT128 |
259 | struct int128_t {}; |
260 | struct uint128_t {}; |
261 | #endif |
262 | |
263 | // Casts a nonnegative integer to unsigned. |
264 | template <typename Int> |
265 | FMT_CONSTEXPR typename std::make_unsigned<Int>::type to_unsigned(Int value) { |
266 | FMT_ASSERT(value >= 0, "negative value" ); |
267 | return static_cast<typename std::make_unsigned<Int>::type>(value); |
268 | } |
269 | } // namespace internal |
270 | |
271 | template <typename... Ts> |
272 | using void_t = typename internal::void_t_impl<Ts...>::type; |
273 | |
274 | /** |
275 | An implementation of ``std::basic_string_view`` for pre-C++17. It provides a |
276 | subset of the API. ``fmt::basic_string_view`` is used for format strings even |
277 | if ``std::string_view`` is available to prevent issues when a library is |
278 | compiled with a different ``-std`` option than the client code (which is not |
279 | recommended). |
280 | */ |
281 | template <typename Char> class basic_string_view { |
282 | private: |
283 | const Char* data_; |
284 | size_t size_; |
285 | |
286 | public: |
287 | using char_type = Char; |
288 | using iterator = const Char*; |
289 | |
290 | FMT_CONSTEXPR basic_string_view() FMT_NOEXCEPT : data_(nullptr), size_(0) {} |
291 | |
292 | /** Constructs a string reference object from a C string and a size. */ |
293 | FMT_CONSTEXPR basic_string_view(const Char* s, size_t count) FMT_NOEXCEPT |
294 | : data_(s), |
295 | size_(count) {} |
296 | |
297 | /** |
298 | \rst |
299 | Constructs a string reference object from a C string computing |
300 | the size with ``std::char_traits<Char>::length``. |
301 | \endrst |
302 | */ |
303 | basic_string_view(const Char* s) |
304 | : data_(s), size_(std::char_traits<Char>::length(s)) {} |
305 | |
306 | /** Constructs a string reference from a ``std::basic_string`` object. */ |
307 | template <typename Traits, typename Alloc> |
308 | FMT_CONSTEXPR basic_string_view( |
309 | const std::basic_string<Char, Traits, Alloc>& s) FMT_NOEXCEPT |
310 | : data_(s.data()), |
311 | size_(s.size()) {} |
312 | |
313 | template < |
314 | typename S, |
315 | FMT_ENABLE_IF(std::is_same<S, internal::std_string_view<Char>>::value)> |
316 | FMT_CONSTEXPR basic_string_view(S s) FMT_NOEXCEPT : data_(s.data()), |
317 | size_(s.size()) {} |
318 | |
319 | /** Returns a pointer to the string data. */ |
320 | FMT_CONSTEXPR const Char* data() const { return data_; } |
321 | |
322 | /** Returns the string size. */ |
323 | FMT_CONSTEXPR size_t size() const { return size_; } |
324 | |
325 | FMT_CONSTEXPR iterator begin() const { return data_; } |
326 | FMT_CONSTEXPR iterator end() const { return data_ + size_; } |
327 | |
328 | FMT_CONSTEXPR const Char& operator[](size_t pos) const { return data_[pos]; } |
329 | |
330 | FMT_CONSTEXPR void remove_prefix(size_t n) { |
331 | data_ += n; |
332 | size_ -= n; |
333 | } |
334 | |
335 | // Lexicographically compare this string reference to other. |
336 | int compare(basic_string_view other) const { |
337 | size_t str_size = size_ < other.size_ ? size_ : other.size_; |
338 | int result = std::char_traits<Char>::compare(data_, other.data_, str_size); |
339 | if (result == 0) |
340 | result = size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1); |
341 | return result; |
342 | } |
343 | |
344 | friend bool operator==(basic_string_view lhs, basic_string_view rhs) { |
345 | return lhs.compare(rhs) == 0; |
346 | } |
347 | friend bool operator!=(basic_string_view lhs, basic_string_view rhs) { |
348 | return lhs.compare(rhs) != 0; |
349 | } |
350 | friend bool operator<(basic_string_view lhs, basic_string_view rhs) { |
351 | return lhs.compare(rhs) < 0; |
352 | } |
353 | friend bool operator<=(basic_string_view lhs, basic_string_view rhs) { |
354 | return lhs.compare(rhs) <= 0; |
355 | } |
356 | friend bool operator>(basic_string_view lhs, basic_string_view rhs) { |
357 | return lhs.compare(rhs) > 0; |
358 | } |
359 | friend bool operator>=(basic_string_view lhs, basic_string_view rhs) { |
360 | return lhs.compare(rhs) >= 0; |
361 | } |
362 | }; |
363 | |
364 | using string_view = basic_string_view<char>; |
365 | using wstring_view = basic_string_view<wchar_t>; |
366 | |
367 | #ifndef __cpp_char8_t |
368 | // A UTF-8 code unit type. |
369 | enum char8_t : unsigned char {}; |
370 | #endif |
371 | |
372 | /** Specifies if ``T`` is a character type. Can be specialized by users. */ |
373 | template <typename T> struct is_char : std::false_type {}; |
374 | template <> struct is_char<char> : std::true_type {}; |
375 | template <> struct is_char<wchar_t> : std::true_type {}; |
376 | template <> struct is_char<char8_t> : std::true_type {}; |
377 | template <> struct is_char<char16_t> : std::true_type {}; |
378 | template <> struct is_char<char32_t> : std::true_type {}; |
379 | |
380 | /** |
381 | \rst |
382 | Returns a string view of `s`. In order to add custom string type support to |
383 | {fmt} provide an overload of `to_string_view` for it in the same namespace as |
384 | the type for the argument-dependent lookup to work. |
385 | |
386 | **Example**:: |
387 | |
388 | namespace my_ns { |
389 | inline string_view to_string_view(const my_string& s) { |
390 | return {s.data(), s.length()}; |
391 | } |
392 | } |
393 | std::string message = fmt::format(my_string("The answer is {}"), 42); |
394 | \endrst |
395 | */ |
396 | template <typename Char, FMT_ENABLE_IF(is_char<Char>::value)> |
397 | inline basic_string_view<Char> to_string_view(const Char* s) { |
398 | return s; |
399 | } |
400 | |
401 | template <typename Char, typename Traits, typename Alloc> |
402 | inline basic_string_view<Char> to_string_view( |
403 | const std::basic_string<Char, Traits, Alloc>& s) { |
404 | return s; |
405 | } |
406 | |
407 | template <typename Char> |
408 | inline basic_string_view<Char> to_string_view(basic_string_view<Char> s) { |
409 | return s; |
410 | } |
411 | |
412 | template <typename Char, |
413 | FMT_ENABLE_IF(!std::is_empty<internal::std_string_view<Char>>::value)> |
414 | inline basic_string_view<Char> to_string_view( |
415 | internal::std_string_view<Char> s) { |
416 | return s; |
417 | } |
418 | |
419 | // A base class for compile-time strings. It is defined in the fmt namespace to |
420 | // make formatting functions visible via ADL, e.g. format(fmt("{}"), 42). |
421 | struct compile_string {}; |
422 | |
423 | template <typename S> |
424 | struct is_compile_string : std::is_base_of<compile_string, S> {}; |
425 | |
426 | template <typename S, FMT_ENABLE_IF(is_compile_string<S>::value)> |
427 | constexpr basic_string_view<typename S::char_type> to_string_view(const S& s) { |
428 | return s; |
429 | } |
430 | |
431 | namespace internal { |
432 | void to_string_view(...); |
433 | using fmt::v6::to_string_view; |
434 | |
435 | // Specifies whether S is a string type convertible to fmt::basic_string_view. |
436 | // It should be a constexpr function but MSVC 2017 fails to compile it in |
437 | // enable_if and MSVC 2015 fails to compile it as an alias template. |
438 | template <typename S> |
439 | struct is_string : std::is_class<decltype(to_string_view(std::declval<S>()))> { |
440 | }; |
441 | |
442 | template <typename S, typename = void> struct char_t_impl {}; |
443 | template <typename S> struct char_t_impl<S, enable_if_t<is_string<S>::value>> { |
444 | using result = decltype(to_string_view(std::declval<S>())); |
445 | using type = typename result::char_type; |
446 | }; |
447 | |
448 | struct error_handler { |
449 | FMT_CONSTEXPR error_handler() = default; |
450 | FMT_CONSTEXPR error_handler(const error_handler&) = default; |
451 | |
452 | // This function is intentionally not constexpr to give a compile-time error. |
453 | FMT_NORETURN FMT_API void on_error(const char* message); |
454 | }; |
455 | } // namespace internal |
456 | |
457 | /** String's character type. */ |
458 | template <typename S> using char_t = typename internal::char_t_impl<S>::type; |
459 | |
460 | /** |
461 | \rst |
462 | Parsing context consisting of a format string range being parsed and an |
463 | argument counter for automatic indexing. |
464 | |
465 | You can use one of the following type aliases for common character types: |
466 | |
467 | +-----------------------+-------------------------------------+ |
468 | | Type | Definition | |
469 | +=======================+=====================================+ |
470 | | format_parse_context | basic_format_parse_context<char> | |
471 | +-----------------------+-------------------------------------+ |
472 | | wformat_parse_context | basic_format_parse_context<wchar_t> | |
473 | +-----------------------+-------------------------------------+ |
474 | \endrst |
475 | */ |
476 | template <typename Char, typename ErrorHandler = internal::error_handler> |
477 | class basic_format_parse_context : private ErrorHandler { |
478 | private: |
479 | basic_string_view<Char> format_str_; |
480 | int next_arg_id_; |
481 | |
482 | public: |
483 | using char_type = Char; |
484 | using iterator = typename basic_string_view<Char>::iterator; |
485 | |
486 | explicit FMT_CONSTEXPR basic_format_parse_context( |
487 | basic_string_view<Char> format_str, ErrorHandler eh = ErrorHandler()) |
488 | : ErrorHandler(eh), format_str_(format_str), next_arg_id_(0) {} |
489 | |
490 | /** |
491 | Returns an iterator to the beginning of the format string range being |
492 | parsed. |
493 | */ |
494 | FMT_CONSTEXPR iterator begin() const FMT_NOEXCEPT { |
495 | return format_str_.begin(); |
496 | } |
497 | |
498 | /** |
499 | Returns an iterator past the end of the format string range being parsed. |
500 | */ |
501 | FMT_CONSTEXPR iterator end() const FMT_NOEXCEPT { return format_str_.end(); } |
502 | |
503 | /** Advances the begin iterator to ``it``. */ |
504 | FMT_CONSTEXPR void advance_to(iterator it) { |
505 | format_str_.remove_prefix(internal::to_unsigned(it - begin())); |
506 | } |
507 | |
508 | /** |
509 | Reports an error if using the manual argument indexing; otherwise returns |
510 | the next argument index and switches to the automatic indexing. |
511 | */ |
512 | FMT_CONSTEXPR int next_arg_id() { |
513 | if (next_arg_id_ >= 0) return next_arg_id_++; |
514 | on_error("cannot switch from manual to automatic argument indexing" ); |
515 | return 0; |
516 | } |
517 | |
518 | /** |
519 | Reports an error if using the automatic argument indexing; otherwise |
520 | switches to the manual indexing. |
521 | */ |
522 | FMT_CONSTEXPR void check_arg_id(int) { |
523 | if (next_arg_id_ > 0) |
524 | on_error("cannot switch from automatic to manual argument indexing" ); |
525 | else |
526 | next_arg_id_ = -1; |
527 | } |
528 | |
529 | FMT_CONSTEXPR void check_arg_id(basic_string_view<Char>) {} |
530 | |
531 | FMT_CONSTEXPR void on_error(const char* message) { |
532 | ErrorHandler::on_error(message); |
533 | } |
534 | |
535 | FMT_CONSTEXPR ErrorHandler error_handler() const { return *this; } |
536 | }; |
537 | |
538 | using format_parse_context = basic_format_parse_context<char>; |
539 | using wformat_parse_context = basic_format_parse_context<wchar_t>; |
540 | |
541 | template <typename Char, typename ErrorHandler = internal::error_handler> |
542 | using basic_parse_context FMT_DEPRECATED_ALIAS = |
543 | basic_format_parse_context<Char, ErrorHandler>; |
544 | using parse_context FMT_DEPRECATED_ALIAS = basic_format_parse_context<char>; |
545 | using wparse_context FMT_DEPRECATED_ALIAS = basic_format_parse_context<wchar_t>; |
546 | |
547 | template <typename Context> class basic_format_arg; |
548 | template <typename Context> class basic_format_args; |
549 | |
550 | // A formatter for objects of type T. |
551 | template <typename T, typename Char = char, typename Enable = void> |
552 | struct formatter { |
553 | // A deleted default constructor indicates a disabled formatter. |
554 | formatter() = delete; |
555 | }; |
556 | |
557 | template <typename T, typename Char, typename Enable = void> |
558 | struct FMT_DEPRECATED convert_to_int |
559 | : bool_constant<!std::is_arithmetic<T>::value && |
560 | std::is_convertible<T, int>::value> {}; |
561 | |
562 | // Specifies if T has an enabled formatter specialization. A type can be |
563 | // formattable even if it doesn't have a formatter e.g. via a conversion. |
564 | template <typename T, typename Context> |
565 | using has_formatter = |
566 | std::is_constructible<typename Context::template formatter_type<T>>; |
567 | |
568 | namespace internal { |
569 | |
570 | /** A contiguous memory buffer with an optional growing ability. */ |
571 | template <typename T> class buffer { |
572 | private: |
573 | T* ptr_; |
574 | std::size_t size_; |
575 | std::size_t capacity_; |
576 | |
577 | protected: |
578 | // Don't initialize ptr_ since it is not accessed to save a few cycles. |
579 | buffer(std::size_t sz) FMT_NOEXCEPT : size_(sz), capacity_(sz) {} |
580 | |
581 | buffer(T* p = nullptr, std::size_t sz = 0, std::size_t cap = 0) FMT_NOEXCEPT |
582 | : ptr_(p), |
583 | size_(sz), |
584 | capacity_(cap) {} |
585 | |
586 | /** Sets the buffer data and capacity. */ |
587 | void set(T* buf_data, std::size_t buf_capacity) FMT_NOEXCEPT { |
588 | ptr_ = buf_data; |
589 | capacity_ = buf_capacity; |
590 | } |
591 | |
592 | /** Increases the buffer capacity to hold at least *capacity* elements. */ |
593 | virtual void grow(std::size_t capacity) = 0; |
594 | |
595 | public: |
596 | using value_type = T; |
597 | using const_reference = const T&; |
598 | |
599 | buffer(const buffer&) = delete; |
600 | void operator=(const buffer&) = delete; |
601 | virtual ~buffer() = default; |
602 | |
603 | T* begin() FMT_NOEXCEPT { return ptr_; } |
604 | T* end() FMT_NOEXCEPT { return ptr_ + size_; } |
605 | |
606 | /** Returns the size of this buffer. */ |
607 | std::size_t size() const FMT_NOEXCEPT { return size_; } |
608 | |
609 | /** Returns the capacity of this buffer. */ |
610 | std::size_t capacity() const FMT_NOEXCEPT { return capacity_; } |
611 | |
612 | /** Returns a pointer to the buffer data. */ |
613 | T* data() FMT_NOEXCEPT { return ptr_; } |
614 | |
615 | /** Returns a pointer to the buffer data. */ |
616 | const T* data() const FMT_NOEXCEPT { return ptr_; } |
617 | |
618 | /** |
619 | Resizes the buffer. If T is a POD type new elements may not be initialized. |
620 | */ |
621 | void resize(std::size_t new_size) { |
622 | reserve(new_size); |
623 | size_ = new_size; |
624 | } |
625 | |
626 | /** Clears this buffer. */ |
627 | void clear() { size_ = 0; } |
628 | |
629 | /** Reserves space to store at least *capacity* elements. */ |
630 | void reserve(std::size_t new_capacity) { |
631 | if (new_capacity > capacity_) grow(new_capacity); |
632 | } |
633 | |
634 | void push_back(const T& value) { |
635 | reserve(size_ + 1); |
636 | ptr_[size_++] = value; |
637 | } |
638 | |
639 | /** Appends data to the end of the buffer. */ |
640 | template <typename U> void append(const U* begin, const U* end); |
641 | |
642 | T& operator[](std::size_t index) { return ptr_[index]; } |
643 | const T& operator[](std::size_t index) const { return ptr_[index]; } |
644 | }; |
645 | |
646 | // A container-backed buffer. |
647 | template <typename Container> |
648 | class container_buffer : public buffer<typename Container::value_type> { |
649 | private: |
650 | Container& container_; |
651 | |
652 | protected: |
653 | void grow(std::size_t capacity) FMT_OVERRIDE { |
654 | container_.resize(capacity); |
655 | this->set(&container_[0], capacity); |
656 | } |
657 | |
658 | public: |
659 | explicit container_buffer(Container& c) |
660 | : buffer<typename Container::value_type>(c.size()), container_(c) {} |
661 | }; |
662 | |
663 | // Extracts a reference to the container from back_insert_iterator. |
664 | template <typename Container> |
665 | inline Container& get_container(std::back_insert_iterator<Container> it) { |
666 | using bi_iterator = std::back_insert_iterator<Container>; |
667 | struct accessor : bi_iterator { |
668 | accessor(bi_iterator iter) : bi_iterator(iter) {} |
669 | using bi_iterator::container; |
670 | }; |
671 | return *accessor(it).container; |
672 | } |
673 | |
674 | template <typename T, typename Char = char, typename Enable = void> |
675 | struct fallback_formatter { |
676 | fallback_formatter() = delete; |
677 | }; |
678 | |
679 | // Specifies if T has an enabled fallback_formatter specialization. |
680 | template <typename T, typename Context> |
681 | using has_fallback_formatter = |
682 | std::is_constructible<fallback_formatter<T, typename Context::char_type>>; |
683 | |
684 | template <typename Char> struct named_arg_base; |
685 | template <typename T, typename Char> struct named_arg; |
686 | |
687 | enum type { |
688 | none_type, |
689 | named_arg_type, |
690 | // Integer types should go first, |
691 | int_type, |
692 | uint_type, |
693 | long_long_type, |
694 | ulong_long_type, |
695 | int128_type, |
696 | uint128_type, |
697 | bool_type, |
698 | char_type, |
699 | last_integer_type = char_type, |
700 | // followed by floating-point types. |
701 | float_type, |
702 | double_type, |
703 | long_double_type, |
704 | last_numeric_type = long_double_type, |
705 | cstring_type, |
706 | string_type, |
707 | pointer_type, |
708 | custom_type |
709 | }; |
710 | |
711 | // Maps core type T to the corresponding type enum constant. |
712 | template <typename T, typename Char> |
713 | struct type_constant : std::integral_constant<type, custom_type> {}; |
714 | |
715 | #define FMT_TYPE_CONSTANT(Type, constant) \ |
716 | template <typename Char> \ |
717 | struct type_constant<Type, Char> : std::integral_constant<type, constant> {} |
718 | |
719 | FMT_TYPE_CONSTANT(const named_arg_base<Char>&, named_arg_type); |
720 | FMT_TYPE_CONSTANT(int, int_type); |
721 | FMT_TYPE_CONSTANT(unsigned, uint_type); |
722 | FMT_TYPE_CONSTANT(long long, long_long_type); |
723 | FMT_TYPE_CONSTANT(unsigned long long, ulong_long_type); |
724 | FMT_TYPE_CONSTANT(int128_t, int128_type); |
725 | FMT_TYPE_CONSTANT(uint128_t, uint128_type); |
726 | FMT_TYPE_CONSTANT(bool, bool_type); |
727 | FMT_TYPE_CONSTANT(Char, char_type); |
728 | FMT_TYPE_CONSTANT(float, float_type); |
729 | FMT_TYPE_CONSTANT(double, double_type); |
730 | FMT_TYPE_CONSTANT(long double, long_double_type); |
731 | FMT_TYPE_CONSTANT(const Char*, cstring_type); |
732 | FMT_TYPE_CONSTANT(basic_string_view<Char>, string_type); |
733 | FMT_TYPE_CONSTANT(const void*, pointer_type); |
734 | |
735 | FMT_CONSTEXPR bool is_integral_type(type t) { |
736 | FMT_ASSERT(t != named_arg_type, "invalid argument type" ); |
737 | return t > none_type && t <= last_integer_type; |
738 | } |
739 | |
740 | FMT_CONSTEXPR bool is_arithmetic_type(type t) { |
741 | FMT_ASSERT(t != named_arg_type, "invalid argument type" ); |
742 | return t > none_type && t <= last_numeric_type; |
743 | } |
744 | |
745 | template <typename Char> struct string_value { |
746 | const Char* data; |
747 | std::size_t size; |
748 | }; |
749 | |
750 | template <typename Context> struct custom_value { |
751 | using parse_context = basic_format_parse_context<typename Context::char_type>; |
752 | const void* value; |
753 | void (*format)(const void* arg, parse_context& parse_ctx, Context& ctx); |
754 | }; |
755 | |
756 | // A formatting argument value. |
757 | template <typename Context> class value { |
758 | public: |
759 | using char_type = typename Context::char_type; |
760 | |
761 | union { |
762 | int int_value; |
763 | unsigned uint_value; |
764 | long long long_long_value; |
765 | unsigned long long ulong_long_value; |
766 | int128_t int128_value; |
767 | uint128_t uint128_value; |
768 | bool bool_value; |
769 | char_type char_value; |
770 | float float_value; |
771 | double double_value; |
772 | long double long_double_value; |
773 | const void* pointer; |
774 | string_value<char_type> string; |
775 | custom_value<Context> custom; |
776 | const named_arg_base<char_type>* named_arg; |
777 | }; |
778 | |
779 | FMT_CONSTEXPR value(int val = 0) : int_value(val) {} |
780 | FMT_CONSTEXPR value(unsigned val) : uint_value(val) {} |
781 | value(long long val) : long_long_value(val) {} |
782 | value(unsigned long long val) : ulong_long_value(val) {} |
783 | value(int128_t val) : int128_value(val) {} |
784 | value(uint128_t val) : uint128_value(val) {} |
785 | value(float val) : float_value(val) {} |
786 | value(double val) : double_value(val) {} |
787 | value(long double val) : long_double_value(val) {} |
788 | value(bool val) : bool_value(val) {} |
789 | value(char_type val) : char_value(val) {} |
790 | value(const char_type* val) { string.data = val; } |
791 | value(basic_string_view<char_type> val) { |
792 | string.data = val.data(); |
793 | string.size = val.size(); |
794 | } |
795 | value(const void* val) : pointer(val) {} |
796 | |
797 | template <typename T> value(const T& val) { |
798 | custom.value = &val; |
799 | // Get the formatter type through the context to allow different contexts |
800 | // have different extension points, e.g. `formatter<T>` for `format` and |
801 | // `printf_formatter<T>` for `printf`. |
802 | custom.format = format_custom_arg< |
803 | T, conditional_t<has_formatter<T, Context>::value, |
804 | typename Context::template formatter_type<T>, |
805 | fallback_formatter<T, char_type>>>; |
806 | } |
807 | |
808 | value(const named_arg_base<char_type>& val) { named_arg = &val; } |
809 | |
810 | private: |
811 | // Formats an argument of a custom type, such as a user-defined class. |
812 | template <typename T, typename Formatter> |
813 | static void format_custom_arg( |
814 | const void* arg, basic_format_parse_context<char_type>& parse_ctx, |
815 | Context& ctx) { |
816 | Formatter f; |
817 | parse_ctx.advance_to(f.parse(parse_ctx)); |
818 | ctx.advance_to(f.format(*static_cast<const T*>(arg), ctx)); |
819 | } |
820 | }; |
821 | |
822 | template <typename Context, typename T> |
823 | FMT_CONSTEXPR basic_format_arg<Context> make_arg(const T& value); |
824 | |
825 | // To minimize the number of types we need to deal with, long is translated |
826 | // either to int or to long long depending on its size. |
827 | enum { long_short = sizeof(long) == sizeof(int) }; |
828 | using long_type = conditional_t<long_short, int, long long>; |
829 | using ulong_type = conditional_t<long_short, unsigned, unsigned long long>; |
830 | |
831 | // Maps formatting arguments to core types. |
832 | template <typename Context> struct arg_mapper { |
833 | using char_type = typename Context::char_type; |
834 | |
835 | FMT_CONSTEXPR int map(signed char val) { return val; } |
836 | FMT_CONSTEXPR unsigned map(unsigned char val) { return val; } |
837 | FMT_CONSTEXPR int map(short val) { return val; } |
838 | FMT_CONSTEXPR unsigned map(unsigned short val) { return val; } |
839 | FMT_CONSTEXPR int map(int val) { return val; } |
840 | FMT_CONSTEXPR unsigned map(unsigned val) { return val; } |
841 | FMT_CONSTEXPR long_type map(long val) { return val; } |
842 | FMT_CONSTEXPR ulong_type map(unsigned long val) { return val; } |
843 | FMT_CONSTEXPR long long map(long long val) { return val; } |
844 | FMT_CONSTEXPR unsigned long long map(unsigned long long val) { return val; } |
845 | FMT_CONSTEXPR int128_t map(int128_t val) { return val; } |
846 | FMT_CONSTEXPR uint128_t map(uint128_t val) { return val; } |
847 | FMT_CONSTEXPR bool map(bool val) { return val; } |
848 | |
849 | template <typename T, FMT_ENABLE_IF(is_char<T>::value)> |
850 | FMT_CONSTEXPR char_type map(T val) { |
851 | static_assert( |
852 | std::is_same<T, char>::value || std::is_same<T, char_type>::value, |
853 | "mixing character types is disallowed" ); |
854 | return val; |
855 | } |
856 | |
857 | FMT_CONSTEXPR float map(float val) { return val; } |
858 | FMT_CONSTEXPR double map(double val) { return val; } |
859 | FMT_CONSTEXPR long double map(long double val) { return val; } |
860 | |
861 | FMT_CONSTEXPR const char_type* map(char_type* val) { return val; } |
862 | FMT_CONSTEXPR const char_type* map(const char_type* val) { return val; } |
863 | template <typename T, FMT_ENABLE_IF(is_string<T>::value)> |
864 | FMT_CONSTEXPR basic_string_view<char_type> map(const T& val) { |
865 | static_assert(std::is_same<char_type, char_t<T>>::value, |
866 | "mixing character types is disallowed" ); |
867 | return to_string_view(val); |
868 | } |
869 | template <typename T, |
870 | FMT_ENABLE_IF( |
871 | std::is_constructible<basic_string_view<char_type>, T>::value && |
872 | !is_string<T>::value)> |
873 | FMT_CONSTEXPR basic_string_view<char_type> map(const T& val) { |
874 | return basic_string_view<char_type>(val); |
875 | } |
876 | template < |
877 | typename T, |
878 | FMT_ENABLE_IF( |
879 | std::is_constructible<std_string_view<char_type>, T>::value && |
880 | !std::is_constructible<basic_string_view<char_type>, T>::value && |
881 | !is_string<T>::value && !has_formatter<T, Context>::value)> |
882 | FMT_CONSTEXPR basic_string_view<char_type> map(const T& val) { |
883 | return std_string_view<char_type>(val); |
884 | } |
885 | FMT_CONSTEXPR const char* map(const signed char* val) { |
886 | static_assert(std::is_same<char_type, char>::value, "invalid string type" ); |
887 | return reinterpret_cast<const char*>(val); |
888 | } |
889 | FMT_CONSTEXPR const char* map(const unsigned char* val) { |
890 | static_assert(std::is_same<char_type, char>::value, "invalid string type" ); |
891 | return reinterpret_cast<const char*>(val); |
892 | } |
893 | |
894 | FMT_CONSTEXPR const void* map(void* val) { return val; } |
895 | FMT_CONSTEXPR const void* map(const void* val) { return val; } |
896 | FMT_CONSTEXPR const void* map(std::nullptr_t val) { return val; } |
897 | template <typename T> FMT_CONSTEXPR int map(const T*) { |
898 | // Formatting of arbitrary pointers is disallowed. If you want to output |
899 | // a pointer cast it to "void *" or "const void *". In particular, this |
900 | // forbids formatting of "[const] volatile char *" which is printed as bool |
901 | // by iostreams. |
902 | static_assert(!sizeof(T), "formatting of non-void pointers is disallowed" ); |
903 | return 0; |
904 | } |
905 | |
906 | template <typename T, |
907 | FMT_ENABLE_IF(std::is_enum<T>::value && |
908 | !has_formatter<T, Context>::value && |
909 | !has_fallback_formatter<T, Context>::value)> |
910 | FMT_CONSTEXPR auto map(const T& val) -> decltype( |
911 | map(static_cast<typename std::underlying_type<T>::type>(val))) { |
912 | return map(static_cast<typename std::underlying_type<T>::type>(val)); |
913 | } |
914 | template < |
915 | typename T, |
916 | FMT_ENABLE_IF( |
917 | !is_string<T>::value && !is_char<T>::value && |
918 | !std::is_constructible<basic_string_view<char_type>, T>::value && |
919 | (has_formatter<T, Context>::value || |
920 | (has_fallback_formatter<T, Context>::value && |
921 | !std::is_constructible<std_string_view<char_type>, T>::value)))> |
922 | FMT_CONSTEXPR const T& map(const T& val) { |
923 | return val; |
924 | } |
925 | |
926 | template <typename T> |
927 | FMT_CONSTEXPR const named_arg_base<char_type>& map( |
928 | const named_arg<T, char_type>& val) { |
929 | auto arg = make_arg<Context>(val.value); |
930 | std::memcpy(val.data, &arg, sizeof(arg)); |
931 | return val; |
932 | } |
933 | }; |
934 | |
935 | // A type constant after applying arg_mapper<Context>. |
936 | template <typename T, typename Context> |
937 | using mapped_type_constant = |
938 | type_constant<decltype(arg_mapper<Context>().map(std::declval<const T&>())), |
939 | typename Context::char_type>; |
940 | |
941 | enum { packed_arg_bits = 5 }; |
942 | // Maximum number of arguments with packed types. |
943 | enum { max_packed_args = 63 / packed_arg_bits }; |
944 | enum : unsigned long long { is_unpacked_bit = 1ULL << 63 }; |
945 | |
946 | template <typename Context> class arg_map; |
947 | } // namespace internal |
948 | |
949 | // A formatting argument. It is a trivially copyable/constructible type to |
950 | // allow storage in basic_memory_buffer. |
951 | template <typename Context> class basic_format_arg { |
952 | private: |
953 | internal::value<Context> value_; |
954 | internal::type type_; |
955 | |
956 | template <typename ContextType, typename T> |
957 | friend FMT_CONSTEXPR basic_format_arg<ContextType> internal::make_arg( |
958 | const T& value); |
959 | |
960 | template <typename Visitor, typename Ctx> |
961 | friend FMT_CONSTEXPR auto visit_format_arg(Visitor&& vis, |
962 | const basic_format_arg<Ctx>& arg) |
963 | -> decltype(vis(0)); |
964 | |
965 | friend class basic_format_args<Context>; |
966 | friend class internal::arg_map<Context>; |
967 | |
968 | using char_type = typename Context::char_type; |
969 | |
970 | public: |
971 | class handle { |
972 | public: |
973 | explicit handle(internal::custom_value<Context> custom) : custom_(custom) {} |
974 | |
975 | void format(basic_format_parse_context<char_type>& parse_ctx, |
976 | Context& ctx) const { |
977 | custom_.format(custom_.value, parse_ctx, ctx); |
978 | } |
979 | |
980 | private: |
981 | internal::custom_value<Context> custom_; |
982 | }; |
983 | |
984 | FMT_CONSTEXPR basic_format_arg() : type_(internal::none_type) {} |
985 | |
986 | FMT_CONSTEXPR explicit operator bool() const FMT_NOEXCEPT { |
987 | return type_ != internal::none_type; |
988 | } |
989 | |
990 | internal::type type() const { return type_; } |
991 | |
992 | bool is_integral() const { return internal::is_integral_type(type_); } |
993 | bool is_arithmetic() const { return internal::is_arithmetic_type(type_); } |
994 | }; |
995 | |
996 | /** |
997 | \rst |
998 | Visits an argument dispatching to the appropriate visit method based on |
999 | the argument type. For example, if the argument type is ``double`` then |
1000 | ``vis(value)`` will be called with the value of type ``double``. |
1001 | \endrst |
1002 | */ |
1003 | template <typename Visitor, typename Context> |
1004 | FMT_CONSTEXPR auto visit_format_arg(Visitor&& vis, |
1005 | const basic_format_arg<Context>& arg) |
1006 | -> decltype(vis(0)) { |
1007 | using char_type = typename Context::char_type; |
1008 | switch (arg.type_) { |
1009 | case internal::none_type: |
1010 | break; |
1011 | case internal::named_arg_type: |
1012 | FMT_ASSERT(false, "invalid argument type" ); |
1013 | break; |
1014 | case internal::int_type: |
1015 | return vis(arg.value_.int_value); |
1016 | case internal::uint_type: |
1017 | return vis(arg.value_.uint_value); |
1018 | case internal::long_long_type: |
1019 | return vis(arg.value_.long_long_value); |
1020 | case internal::ulong_long_type: |
1021 | return vis(arg.value_.ulong_long_value); |
1022 | #if FMT_USE_INT128 |
1023 | case internal::int128_type: |
1024 | return vis(arg.value_.int128_value); |
1025 | case internal::uint128_type: |
1026 | return vis(arg.value_.uint128_value); |
1027 | #else |
1028 | case internal::int128_type: |
1029 | case internal::uint128_type: |
1030 | break; |
1031 | #endif |
1032 | case internal::bool_type: |
1033 | return vis(arg.value_.bool_value); |
1034 | case internal::char_type: |
1035 | return vis(arg.value_.char_value); |
1036 | case internal::float_type: |
1037 | return vis(arg.value_.float_value); |
1038 | case internal::double_type: |
1039 | return vis(arg.value_.double_value); |
1040 | case internal::long_double_type: |
1041 | return vis(arg.value_.long_double_value); |
1042 | case internal::cstring_type: |
1043 | return vis(arg.value_.string.data); |
1044 | case internal::string_type: |
1045 | return vis(basic_string_view<char_type>(arg.value_.string.data, |
1046 | arg.value_.string.size)); |
1047 | case internal::pointer_type: |
1048 | return vis(arg.value_.pointer); |
1049 | case internal::custom_type: |
1050 | return vis(typename basic_format_arg<Context>::handle(arg.value_.custom)); |
1051 | } |
1052 | return vis(monostate()); |
1053 | } |
1054 | |
1055 | namespace internal { |
1056 | // A map from argument names to their values for named arguments. |
1057 | template <typename Context> class arg_map { |
1058 | private: |
1059 | using char_type = typename Context::char_type; |
1060 | |
1061 | struct entry { |
1062 | basic_string_view<char_type> name; |
1063 | basic_format_arg<Context> arg; |
1064 | }; |
1065 | |
1066 | entry* map_; |
1067 | unsigned size_; |
1068 | |
1069 | void push_back(value<Context> val) { |
1070 | const auto& named = *val.named_arg; |
1071 | map_[size_] = {named.name, named.template deserialize<Context>()}; |
1072 | ++size_; |
1073 | } |
1074 | |
1075 | public: |
1076 | arg_map(const arg_map&) = delete; |
1077 | void operator=(const arg_map&) = delete; |
1078 | arg_map() : map_(nullptr), size_(0) {} |
1079 | void init(const basic_format_args<Context>& args); |
1080 | ~arg_map() { delete[] map_; } |
1081 | |
1082 | basic_format_arg<Context> find(basic_string_view<char_type> name) const { |
1083 | // The list is unsorted, so just return the first matching name. |
1084 | for (entry *it = map_, *end = map_ + size_; it != end; ++it) { |
1085 | if (it->name == name) return it->arg; |
1086 | } |
1087 | return {}; |
1088 | } |
1089 | }; |
1090 | |
1091 | // A type-erased reference to an std::locale to avoid heavy <locale> include. |
1092 | class locale_ref { |
1093 | private: |
1094 | const void* locale_; // A type-erased pointer to std::locale. |
1095 | |
1096 | public: |
1097 | locale_ref() : locale_(nullptr) {} |
1098 | template <typename Locale> explicit locale_ref(const Locale& loc); |
1099 | |
1100 | explicit operator bool() const FMT_NOEXCEPT { return locale_ != nullptr; } |
1101 | |
1102 | template <typename Locale> Locale get() const; |
1103 | }; |
1104 | |
1105 | template <typename> constexpr unsigned long long encode_types() { return 0; } |
1106 | |
1107 | template <typename Context, typename Arg, typename... Args> |
1108 | constexpr unsigned long long encode_types() { |
1109 | return mapped_type_constant<Arg, Context>::value | |
1110 | (encode_types<Context, Args...>() << packed_arg_bits); |
1111 | } |
1112 | |
1113 | template <typename Context, typename T> |
1114 | FMT_CONSTEXPR basic_format_arg<Context> make_arg(const T& value) { |
1115 | basic_format_arg<Context> arg; |
1116 | arg.type_ = mapped_type_constant<T, Context>::value; |
1117 | arg.value_ = arg_mapper<Context>().map(value); |
1118 | return arg; |
1119 | } |
1120 | |
1121 | template <bool IS_PACKED, typename Context, typename T, |
1122 | FMT_ENABLE_IF(IS_PACKED)> |
1123 | inline value<Context> make_arg(const T& val) { |
1124 | return arg_mapper<Context>().map(val); |
1125 | } |
1126 | |
1127 | template <bool IS_PACKED, typename Context, typename T, |
1128 | FMT_ENABLE_IF(!IS_PACKED)> |
1129 | inline basic_format_arg<Context> make_arg(const T& value) { |
1130 | return make_arg<Context>(value); |
1131 | } |
1132 | } // namespace internal |
1133 | |
1134 | // Formatting context. |
1135 | template <typename OutputIt, typename Char> class basic_format_context { |
1136 | public: |
1137 | /** The character type for the output. */ |
1138 | using char_type = Char; |
1139 | |
1140 | private: |
1141 | OutputIt out_; |
1142 | basic_format_args<basic_format_context> args_; |
1143 | internal::arg_map<basic_format_context> map_; |
1144 | internal::locale_ref loc_; |
1145 | |
1146 | public: |
1147 | using iterator = OutputIt; |
1148 | using format_arg = basic_format_arg<basic_format_context>; |
1149 | template <typename T> using formatter_type = formatter<T, char_type>; |
1150 | |
1151 | basic_format_context(const basic_format_context&) = delete; |
1152 | void operator=(const basic_format_context&) = delete; |
1153 | /** |
1154 | Constructs a ``basic_format_context`` object. References to the arguments are |
1155 | stored in the object so make sure they have appropriate lifetimes. |
1156 | */ |
1157 | basic_format_context(OutputIt out, |
1158 | basic_format_args<basic_format_context> ctx_args, |
1159 | internal::locale_ref loc = internal::locale_ref()) |
1160 | : out_(out), args_(ctx_args), loc_(loc) {} |
1161 | |
1162 | format_arg arg(int id) const { return args_.get(id); } |
1163 | |
1164 | // Checks if manual indexing is used and returns the argument with the |
1165 | // specified name. |
1166 | format_arg arg(basic_string_view<char_type> name); |
1167 | |
1168 | internal::error_handler error_handler() { return {}; } |
1169 | void on_error(const char* message) { error_handler().on_error(message); } |
1170 | |
1171 | // Returns an iterator to the beginning of the output range. |
1172 | iterator out() { return out_; } |
1173 | |
1174 | // Advances the begin iterator to ``it``. |
1175 | void advance_to(iterator it) { out_ = it; } |
1176 | |
1177 | internal::locale_ref locale() { return loc_; } |
1178 | }; |
1179 | |
1180 | template <typename Char> |
1181 | using buffer_context = |
1182 | basic_format_context<std::back_insert_iterator<internal::buffer<Char>>, |
1183 | Char>; |
1184 | using format_context = buffer_context<char>; |
1185 | using wformat_context = buffer_context<wchar_t>; |
1186 | |
1187 | /** |
1188 | \rst |
1189 | An array of references to arguments. It can be implicitly converted into |
1190 | `~fmt::basic_format_args` for passing into type-erased formatting functions |
1191 | such as `~fmt::vformat`. |
1192 | \endrst |
1193 | */ |
1194 | template <typename Context, typename... Args> class format_arg_store { |
1195 | private: |
1196 | static const size_t num_args = sizeof...(Args); |
1197 | static const bool is_packed = num_args < internal::max_packed_args; |
1198 | |
1199 | using value_type = conditional_t<is_packed, internal::value<Context>, |
1200 | basic_format_arg<Context>>; |
1201 | |
1202 | // If the arguments are not packed, add one more element to mark the end. |
1203 | value_type data_[num_args + (num_args == 0 ? 1 : 0)]; |
1204 | |
1205 | friend class basic_format_args<Context>; |
1206 | |
1207 | public: |
1208 | static constexpr unsigned long long types = |
1209 | is_packed ? internal::encode_types<Context, Args...>() |
1210 | : internal::is_unpacked_bit | num_args; |
1211 | |
1212 | format_arg_store(const Args&... args) |
1213 | : data_{internal::make_arg<is_packed, Context>(args)...} {} |
1214 | }; |
1215 | |
1216 | /** |
1217 | \rst |
1218 | Constructs an `~fmt::format_arg_store` object that contains references to |
1219 | arguments and can be implicitly converted to `~fmt::format_args`. `Context` |
1220 | can be omitted in which case it defaults to `~fmt::context`. |
1221 | See `~fmt::arg` for lifetime considerations. |
1222 | \endrst |
1223 | */ |
1224 | template <typename Context = format_context, typename... Args> |
1225 | inline format_arg_store<Context, Args...> make_format_args( |
1226 | const Args&... args) { |
1227 | return {args...}; |
1228 | } |
1229 | |
1230 | /** Formatting arguments. */ |
1231 | template <typename Context> class basic_format_args { |
1232 | public: |
1233 | using size_type = int; |
1234 | using format_arg = basic_format_arg<Context>; |
1235 | |
1236 | private: |
1237 | // To reduce compiled code size per formatting function call, types of first |
1238 | // max_packed_args arguments are passed in the types_ field. |
1239 | unsigned long long types_; |
1240 | union { |
1241 | // If the number of arguments is less than max_packed_args, the argument |
1242 | // values are stored in values_, otherwise they are stored in args_. |
1243 | // This is done to reduce compiled code size as storing larger objects |
1244 | // may require more code (at least on x86-64) even if the same amount of |
1245 | // data is actually copied to stack. It saves ~10% on the bloat test. |
1246 | const internal::value<Context>* values_; |
1247 | const format_arg* args_; |
1248 | }; |
1249 | |
1250 | bool is_packed() const { return (types_ & internal::is_unpacked_bit) == 0; } |
1251 | |
1252 | internal::type type(int index) const { |
1253 | int shift = index * internal::packed_arg_bits; |
1254 | unsigned int mask = (1 << internal::packed_arg_bits) - 1; |
1255 | return static_cast<internal::type>((types_ >> shift) & mask); |
1256 | } |
1257 | |
1258 | friend class internal::arg_map<Context>; |
1259 | |
1260 | void set_data(const internal::value<Context>* values) { values_ = values; } |
1261 | void set_data(const format_arg* args) { args_ = args; } |
1262 | |
1263 | format_arg do_get(int index) const { |
1264 | format_arg arg; |
1265 | if (!is_packed()) { |
1266 | auto num_args = max_size(); |
1267 | if (index < num_args) arg = args_[index]; |
1268 | return arg; |
1269 | } |
1270 | if (index > internal::max_packed_args) return arg; |
1271 | arg.type_ = type(index); |
1272 | if (arg.type_ == internal::none_type) return arg; |
1273 | internal::value<Context>& val = arg.value_; |
1274 | val = values_[index]; |
1275 | return arg; |
1276 | } |
1277 | |
1278 | public: |
1279 | basic_format_args() : types_(0) {} |
1280 | |
1281 | /** |
1282 | \rst |
1283 | Constructs a `basic_format_args` object from `~fmt::format_arg_store`. |
1284 | \endrst |
1285 | */ |
1286 | template <typename... Args> |
1287 | basic_format_args(const format_arg_store<Context, Args...>& store) |
1288 | : types_(store.types) { |
1289 | set_data(store.data_); |
1290 | } |
1291 | |
1292 | /** |
1293 | \rst |
1294 | Constructs a `basic_format_args` object from a dynamic set of arguments. |
1295 | \endrst |
1296 | */ |
1297 | basic_format_args(const format_arg* args, int count) |
1298 | : types_(internal::is_unpacked_bit | internal::to_unsigned(count)) { |
1299 | set_data(args); |
1300 | } |
1301 | |
1302 | /** Returns the argument at specified index. */ |
1303 | format_arg get(int index) const { |
1304 | format_arg arg = do_get(index); |
1305 | if (arg.type_ == internal::named_arg_type) |
1306 | arg = arg.value_.named_arg->template deserialize<Context>(); |
1307 | return arg; |
1308 | } |
1309 | |
1310 | int max_size() const { |
1311 | unsigned long long max_packed = internal::max_packed_args; |
1312 | return static_cast<int>(is_packed() ? max_packed |
1313 | : types_ & ~internal::is_unpacked_bit); |
1314 | } |
1315 | }; |
1316 | |
1317 | /** An alias to ``basic_format_args<context>``. */ |
1318 | // It is a separate type rather than an alias to make symbols readable. |
1319 | struct format_args : basic_format_args<format_context> { |
1320 | template <typename... Args> |
1321 | format_args(Args&&... args) |
1322 | : basic_format_args<format_context>(std::forward<Args>(args)...) {} |
1323 | }; |
1324 | struct wformat_args : basic_format_args<wformat_context> { |
1325 | template <typename... Args> |
1326 | wformat_args(Args&&... args) |
1327 | : basic_format_args<wformat_context>(std::forward<Args>(args)...) {} |
1328 | }; |
1329 | |
1330 | template <typename Container> struct is_contiguous : std::false_type {}; |
1331 | |
1332 | template <typename Char> |
1333 | struct is_contiguous<std::basic_string<Char>> : std::true_type {}; |
1334 | |
1335 | template <typename Char> |
1336 | struct is_contiguous<internal::buffer<Char>> : std::true_type {}; |
1337 | |
1338 | namespace internal { |
1339 | |
1340 | template <typename OutputIt> |
1341 | struct is_contiguous_back_insert_iterator : std::false_type {}; |
1342 | template <typename Container> |
1343 | struct is_contiguous_back_insert_iterator<std::back_insert_iterator<Container>> |
1344 | : is_contiguous<Container> {}; |
1345 | |
1346 | template <typename Char> struct named_arg_base { |
1347 | basic_string_view<Char> name; |
1348 | |
1349 | // Serialized value<context>. |
1350 | mutable char data[sizeof(basic_format_arg<buffer_context<Char>>)]; |
1351 | |
1352 | named_arg_base(basic_string_view<Char> nm) : name(nm) {} |
1353 | |
1354 | template <typename Context> basic_format_arg<Context> deserialize() const { |
1355 | basic_format_arg<Context> arg; |
1356 | std::memcpy(&arg, data, sizeof(basic_format_arg<Context>)); |
1357 | return arg; |
1358 | } |
1359 | }; |
1360 | |
1361 | template <typename T, typename Char> struct named_arg : named_arg_base<Char> { |
1362 | const T& value; |
1363 | |
1364 | named_arg(basic_string_view<Char> name, const T& val) |
1365 | : named_arg_base<Char>(name), value(val) {} |
1366 | }; |
1367 | |
1368 | template <typename..., typename S, FMT_ENABLE_IF(!is_compile_string<S>::value)> |
1369 | inline void check_format_string(const S&) { |
1370 | #if defined(FMT_ENFORCE_COMPILE_STRING) |
1371 | static_assert(is_compile_string<S>::value, |
1372 | "FMT_ENFORCE_COMPILE_STRING requires all format strings to " |
1373 | "utilize FMT_STRING() or fmt()." ); |
1374 | #endif |
1375 | } |
1376 | template <typename..., typename S, FMT_ENABLE_IF(is_compile_string<S>::value)> |
1377 | void check_format_string(S); |
1378 | |
1379 | struct view {}; |
1380 | template <bool...> struct bool_pack; |
1381 | template <bool... Args> |
1382 | using all_true = |
1383 | std::is_same<bool_pack<Args..., true>, bool_pack<true, Args...>>; |
1384 | |
1385 | template <typename... Args, typename S, typename Char = char_t<S>> |
1386 | inline format_arg_store<buffer_context<Char>, remove_reference_t<Args>...> |
1387 | make_args_checked(const S& format_str, |
1388 | const remove_reference_t<Args>&... args) { |
1389 | static_assert(all_true<(!std::is_base_of<view, remove_reference_t<Args>>() || |
1390 | !std::is_reference<Args>())...>::value, |
1391 | "passing views as lvalues is disallowed" ); |
1392 | check_format_string<remove_const_t<remove_reference_t<Args>>...>(format_str); |
1393 | return {args...}; |
1394 | } |
1395 | |
1396 | template <typename Char> |
1397 | std::basic_string<Char> vformat(basic_string_view<Char> format_str, |
1398 | basic_format_args<buffer_context<Char>> args); |
1399 | |
1400 | template <typename Char> |
1401 | typename buffer_context<Char>::iterator vformat_to( |
1402 | buffer<Char>& buf, basic_string_view<Char> format_str, |
1403 | basic_format_args<buffer_context<Char>> args); |
1404 | } // namespace internal |
1405 | |
1406 | /** |
1407 | \rst |
1408 | Returns a named argument to be used in a formatting function. |
1409 | |
1410 | The named argument holds a reference and does not extend the lifetime |
1411 | of its arguments. |
1412 | Consequently, a dangling reference can accidentally be created. |
1413 | The user should take care to only pass this function temporaries when |
1414 | the named argument is itself a temporary, as per the following example. |
1415 | |
1416 | **Example**:: |
1417 | |
1418 | fmt::print("Elapsed time: {s:.2f} seconds", fmt::arg("s", 1.23)); |
1419 | \endrst |
1420 | */ |
1421 | template <typename S, typename T, typename Char = char_t<S>> |
1422 | inline internal::named_arg<T, Char> arg(const S& name, const T& arg) { |
1423 | static_assert(internal::is_string<S>::value, "" ); |
1424 | return {name, arg}; |
1425 | } |
1426 | |
1427 | // Disable nested named arguments, e.g. ``arg("a", arg("b", 42))``. |
1428 | template <typename S, typename T, typename Char> |
1429 | void arg(S, internal::named_arg<T, Char>) = delete; |
1430 | |
1431 | /** Formats a string and writes the output to ``out``. */ |
1432 | // GCC 8 and earlier cannot handle std::back_insert_iterator<Container> with |
1433 | // vformat_to<ArgFormatter>(...) overload, so SFINAE on iterator type instead. |
1434 | template <typename OutputIt, typename S, typename Char = char_t<S>, |
1435 | FMT_ENABLE_IF( |
1436 | internal::is_contiguous_back_insert_iterator<OutputIt>::value)> |
1437 | OutputIt vformat_to(OutputIt out, const S& format_str, |
1438 | basic_format_args<buffer_context<Char>> args) { |
1439 | using container = remove_reference_t<decltype(internal::get_container(out))>; |
1440 | internal::container_buffer<container> buf((internal::get_container(out))); |
1441 | internal::vformat_to(buf, to_string_view(format_str), args); |
1442 | return out; |
1443 | } |
1444 | |
1445 | template <typename Container, typename S, typename... Args, |
1446 | FMT_ENABLE_IF( |
1447 | is_contiguous<Container>::value&& internal::is_string<S>::value)> |
1448 | inline std::back_insert_iterator<Container> format_to( |
1449 | std::back_insert_iterator<Container> out, const S& format_str, |
1450 | Args&&... args) { |
1451 | return vformat_to( |
1452 | out, to_string_view(format_str), |
1453 | {internal::make_args_checked<Args...>(format_str, args...)}); |
1454 | } |
1455 | |
1456 | template <typename S, typename Char = char_t<S>> |
1457 | inline std::basic_string<Char> vformat( |
1458 | const S& format_str, basic_format_args<buffer_context<Char>> args) { |
1459 | return internal::vformat(to_string_view(format_str), args); |
1460 | } |
1461 | |
1462 | /** |
1463 | \rst |
1464 | Formats arguments and returns the result as a string. |
1465 | |
1466 | **Example**:: |
1467 | |
1468 | #include <fmt/core.h> |
1469 | std::string message = fmt::format("The answer is {}", 42); |
1470 | \endrst |
1471 | */ |
1472 | // Pass char_t as a default template parameter instead of using |
1473 | // std::basic_string<char_t<S>> to reduce the symbol size. |
1474 | template <typename S, typename... Args, typename Char = char_t<S>> |
1475 | inline std::basic_string<Char> format(const S& format_str, Args&&... args) { |
1476 | return internal::vformat( |
1477 | to_string_view(format_str), |
1478 | {internal::make_args_checked<Args...>(format_str, args...)}); |
1479 | } |
1480 | |
1481 | FMT_API void vprint(std::FILE* f, string_view format_str, format_args args); |
1482 | FMT_API void vprint(string_view format_str, format_args args); |
1483 | |
1484 | /** |
1485 | \rst |
1486 | Prints formatted data to the file *f*. For wide format strings, |
1487 | *f* should be in wide-oriented mode set via ``fwide(f, 1)`` or |
1488 | ``_setmode(_fileno(f), _O_U8TEXT)`` on Windows. |
1489 | |
1490 | **Example**:: |
1491 | |
1492 | fmt::print(stderr, "Don't {}!", "panic"); |
1493 | \endrst |
1494 | */ |
1495 | template <typename S, typename... Args, |
1496 | FMT_ENABLE_IF(internal::is_string<S>::value)> |
1497 | inline void print(std::FILE* f, const S& format_str, Args&&... args) { |
1498 | vprint(f, to_string_view(format_str), |
1499 | internal::make_args_checked<Args...>(format_str, args...)); |
1500 | } |
1501 | |
1502 | /** |
1503 | \rst |
1504 | Prints formatted data to ``stdout``. |
1505 | |
1506 | **Example**:: |
1507 | |
1508 | fmt::print("Elapsed time: {0:.2f} seconds", 1.23); |
1509 | \endrst |
1510 | */ |
1511 | template <typename S, typename... Args, |
1512 | FMT_ENABLE_IF(internal::is_string<S>::value)> |
1513 | inline void print(const S& format_str, Args&&... args) { |
1514 | vprint(to_string_view(format_str), |
1515 | internal::make_args_checked<Args...>(format_str, args...)); |
1516 | } |
1517 | FMT_END_NAMESPACE |
1518 | |
1519 | #endif // FMT_CORE_H_ |
1520 | |