1 // Formatting library for C++ - the core API for char/UTF-8 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 <cstddef> // std::byte 12 #include <cstdio> // std::FILE 13 #include <cstring> // std::strlen 14 #include <iterator> 15 #include <limits> 16 #include <memory> // std::addressof 17 #include <string> 18 #include <type_traits> 19 20 // The fmt library version in the form major * 10000 + minor * 100 + patch. 21 #define FMT_VERSION 100200 22 23 #if defined(__clang__) && !defined(__ibmxl__) 24 # define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__) 25 #else 26 # define FMT_CLANG_VERSION 0 27 #endif 28 29 #if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) && \ 30 !defined(__NVCOMPILER) 31 # define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) 32 #else 33 # define FMT_GCC_VERSION 0 34 #endif 35 36 #ifndef FMT_GCC_PRAGMA 37 // Workaround _Pragma bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59884. 38 # if FMT_GCC_VERSION >= 504 39 # define FMT_GCC_PRAGMA(arg) _Pragma(arg) 40 # else 41 # define FMT_GCC_PRAGMA(arg) 42 # endif 43 #endif 44 45 #ifdef __ICL 46 # define FMT_ICC_VERSION __ICL 47 #elif defined(__INTEL_COMPILER) 48 # define FMT_ICC_VERSION __INTEL_COMPILER 49 #else 50 # define FMT_ICC_VERSION 0 51 #endif 52 53 #ifdef _MSC_VER 54 # define FMT_MSC_VERSION _MSC_VER 55 # define FMT_MSC_WARNING(...) __pragma(warning(__VA_ARGS__)) 56 #else 57 # define FMT_MSC_VERSION 0 58 # define FMT_MSC_WARNING(...) 59 #endif 60 61 #ifdef _MSVC_LANG 62 # define FMT_CPLUSPLUS _MSVC_LANG 63 #else 64 # define FMT_CPLUSPLUS __cplusplus 65 #endif 66 67 #ifdef __has_feature 68 # define FMT_HAS_FEATURE(x) __has_feature(x) 69 #else 70 # define FMT_HAS_FEATURE(x) 0 71 #endif 72 73 #if defined(__has_include) || FMT_ICC_VERSION >= 1600 || FMT_MSC_VERSION > 1900 74 # define FMT_HAS_INCLUDE(x) __has_include(x) 75 #else 76 # define FMT_HAS_INCLUDE(x) 0 77 #endif 78 79 #ifdef __has_cpp_attribute 80 # define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) 81 #else 82 # define FMT_HAS_CPP_ATTRIBUTE(x) 0 83 #endif 84 85 #define FMT_HAS_CPP14_ATTRIBUTE(attribute) \ 86 (FMT_CPLUSPLUS >= 201402L && FMT_HAS_CPP_ATTRIBUTE(attribute)) 87 88 #define FMT_HAS_CPP17_ATTRIBUTE(attribute) \ 89 (FMT_CPLUSPLUS >= 201703L && FMT_HAS_CPP_ATTRIBUTE(attribute)) 90 91 // Check if relaxed C++14 constexpr is supported. 92 // GCC doesn't allow throw in constexpr until version 6 (bug 67371). 93 #ifndef FMT_USE_CONSTEXPR 94 # if (FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VERSION >= 1912 || \ 95 (FMT_GCC_VERSION >= 600 && FMT_CPLUSPLUS >= 201402L)) && \ 96 !FMT_ICC_VERSION && (!defined(__NVCC__) || FMT_CPLUSPLUS >= 202002L) 97 # define FMT_USE_CONSTEXPR 1 98 # else 99 # define FMT_USE_CONSTEXPR 0 100 # endif 101 #endif 102 #if FMT_USE_CONSTEXPR 103 # define FMT_CONSTEXPR constexpr 104 #else 105 # define FMT_CONSTEXPR 106 #endif 107 108 #if (FMT_CPLUSPLUS >= 202002L || \ 109 (FMT_CPLUSPLUS >= 201709L && FMT_GCC_VERSION >= 1002)) && \ 110 ((!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE >= 10) && \ 111 (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION >= 10000) && \ 112 (!FMT_MSC_VERSION || FMT_MSC_VERSION >= 1928)) && \ 113 defined(__cpp_lib_is_constant_evaluated) 114 # define FMT_CONSTEXPR20 constexpr 115 #else 116 # define FMT_CONSTEXPR20 117 #endif 118 119 // Check if constexpr std::char_traits<>::{compare,length} are supported. 120 #if defined(__GLIBCXX__) 121 # if FMT_CPLUSPLUS >= 201703L && defined(_GLIBCXX_RELEASE) && \ 122 _GLIBCXX_RELEASE >= 7 // GCC 7+ libstdc++ has _GLIBCXX_RELEASE. 123 # define FMT_CONSTEXPR_CHAR_TRAITS constexpr 124 # endif 125 #elif defined(_LIBCPP_VERSION) && FMT_CPLUSPLUS >= 201703L && \ 126 _LIBCPP_VERSION >= 4000 127 # define FMT_CONSTEXPR_CHAR_TRAITS constexpr 128 #elif FMT_MSC_VERSION >= 1914 && FMT_CPLUSPLUS >= 201703L 129 # define FMT_CONSTEXPR_CHAR_TRAITS constexpr 130 #endif 131 #ifndef FMT_CONSTEXPR_CHAR_TRAITS 132 # define FMT_CONSTEXPR_CHAR_TRAITS 133 #endif 134 135 // Check if exceptions are disabled. 136 #ifndef FMT_EXCEPTIONS 137 # if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || \ 138 (FMT_MSC_VERSION && !_HAS_EXCEPTIONS) 139 # define FMT_EXCEPTIONS 0 140 # else 141 # define FMT_EXCEPTIONS 1 142 # endif 143 #endif 144 145 // Disable [[noreturn]] on MSVC/NVCC because of bogus unreachable code warnings. 146 #if FMT_EXCEPTIONS && FMT_HAS_CPP_ATTRIBUTE(noreturn) && !FMT_MSC_VERSION && \ 147 !defined(__NVCC__) 148 # define FMT_NORETURN [[noreturn]] 149 #else 150 # define FMT_NORETURN 151 #endif 152 153 #ifndef FMT_NODISCARD 154 # if FMT_HAS_CPP17_ATTRIBUTE(nodiscard) 155 # define FMT_NODISCARD [[nodiscard]] 156 # else 157 # define FMT_NODISCARD 158 # endif 159 #endif 160 161 #ifndef FMT_INLINE 162 # if FMT_GCC_VERSION || FMT_CLANG_VERSION 163 # define FMT_INLINE inline __attribute__((always_inline)) 164 # else 165 # define FMT_INLINE inline 166 # endif 167 #endif 168 169 #ifdef _MSC_VER 170 # define FMT_UNCHECKED_ITERATOR(It) \ 171 using _Unchecked_type = It // Mark iterator as checked. 172 #else 173 # define FMT_UNCHECKED_ITERATOR(It) using unchecked_type = It 174 #endif 175 176 #ifndef FMT_BEGIN_NAMESPACE 177 # define FMT_BEGIN_NAMESPACE \ 178 namespace fmt { \ 179 inline namespace v10 { 180 # define FMT_END_NAMESPACE \ 181 } \ 182 } 183 #endif 184 185 #ifndef FMT_EXPORT 186 # define FMT_EXPORT 187 # define FMT_BEGIN_EXPORT 188 # define FMT_END_EXPORT 189 #endif 190 191 #if FMT_GCC_VERSION || FMT_CLANG_VERSION 192 # define FMT_VISIBILITY(value) __attribute__((visibility(value))) 193 #else 194 # define FMT_VISIBILITY(value) 195 #endif 196 197 #if !defined(FMT_HEADER_ONLY) && defined(_WIN32) 198 # if defined(FMT_LIB_EXPORT) 199 # define FMT_API __declspec(dllexport) 200 # elif defined(FMT_SHARED) 201 # define FMT_API __declspec(dllimport) 202 # endif 203 #elif defined(FMT_LIB_EXPORT) || defined(FMT_SHARED) 204 # define FMT_API FMT_VISIBILITY("default") 205 #endif 206 #ifndef FMT_API 207 # define FMT_API 208 #endif 209 210 // libc++ supports string_view in pre-c++17. 211 #if FMT_HAS_INCLUDE(<string_view>) && \ 212 (FMT_CPLUSPLUS >= 201703L || defined(_LIBCPP_VERSION)) 213 # include <string_view> 214 # define FMT_USE_STRING_VIEW 215 #elif FMT_HAS_INCLUDE("experimental/string_view") && FMT_CPLUSPLUS >= 201402L 216 # include <experimental/string_view> 217 # define FMT_USE_EXPERIMENTAL_STRING_VIEW 218 #endif 219 220 #ifndef FMT_UNICODE 221 # define FMT_UNICODE !FMT_MSC_VERSION 222 #endif 223 224 #ifndef FMT_CONSTEVAL 225 # if ((FMT_GCC_VERSION >= 1000 || FMT_CLANG_VERSION >= 1101) && \ 226 (!defined(__apple_build_version__) || \ 227 __apple_build_version__ >= 14000029L) && \ 228 FMT_CPLUSPLUS >= 202002L) || \ 229 (defined(__cpp_consteval) && \ 230 (!FMT_MSC_VERSION || FMT_MSC_VERSION >= 1929)) 231 // consteval is broken in MSVC before VS2019 version 16.10 and Apple clang 232 // before 14. 233 # define FMT_CONSTEVAL consteval 234 # define FMT_HAS_CONSTEVAL 235 # else 236 # define FMT_CONSTEVAL 237 # endif 238 #endif 239 240 #ifndef FMT_USE_NONTYPE_TEMPLATE_ARGS 241 # if defined(__cpp_nontype_template_args) && \ 242 ((FMT_GCC_VERSION >= 903 && FMT_CPLUSPLUS >= 201709L) || \ 243 __cpp_nontype_template_args >= 201911L) && \ 244 !defined(__NVCOMPILER) && !defined(__LCC__) 245 # define FMT_USE_NONTYPE_TEMPLATE_ARGS 1 246 # else 247 # define FMT_USE_NONTYPE_TEMPLATE_ARGS 0 248 # endif 249 #endif 250 251 // GCC < 5 requires this-> in decltype 252 #ifndef FMT_DECLTYPE_THIS 253 # if FMT_GCC_VERSION && FMT_GCC_VERSION < 500 254 # define FMT_DECLTYPE_THIS this-> 255 # else 256 # define FMT_DECLTYPE_THIS 257 # endif 258 #endif 259 260 // Enable minimal optimizations for more compact code in debug mode. 261 FMT_GCC_PRAGMA("GCC push_options") 262 #if !defined(__OPTIMIZE__) && !defined(__NVCOMPILER) && !defined(__LCC__) && \ 263 !defined(__CUDACC__) 264 FMT_GCC_PRAGMA("GCC optimize(\"Og\")") 265 #endif 266 267 FMT_BEGIN_NAMESPACE 268 269 // Implementations of enable_if_t and other metafunctions for older systems. 270 template <bool B, typename T = void> 271 using enable_if_t = typename std::enable_if<B, T>::type; 272 template <bool B, typename T, typename F> 273 using conditional_t = typename std::conditional<B, T, F>::type; 274 template <bool B> using bool_constant = std::integral_constant<bool, B>; 275 template <typename T> 276 using remove_reference_t = typename std::remove_reference<T>::type; 277 template <typename T> 278 using remove_const_t = typename std::remove_const<T>::type; 279 template <typename T> 280 using remove_cvref_t = typename std::remove_cv<remove_reference_t<T>>::type; 281 template <typename T> struct type_identity { 282 using type = T; 283 }; 284 template <typename T> using type_identity_t = typename type_identity<T>::type; 285 template <typename T> 286 using underlying_t = typename std::underlying_type<T>::type; 287 288 // Checks whether T is a container with contiguous storage. 289 template <typename T> struct is_contiguous : std::false_type {}; 290 template <typename Char> 291 struct is_contiguous<std::basic_string<Char>> : std::true_type {}; 292 293 struct monostate { 294 constexpr monostate() {} 295 }; 296 297 // An enable_if helper to be used in template parameters which results in much 298 // shorter symbols: https://godbolt.org/z/sWw4vP. Extra parentheses are needed 299 // to workaround a bug in MSVC 2019 (see #1140 and #1186). 300 #ifdef FMT_DOC 301 # define FMT_ENABLE_IF(...) 302 #else 303 # define FMT_ENABLE_IF(...) fmt::enable_if_t<(__VA_ARGS__), int> = 0 304 #endif 305 306 // This is defined in core.h instead of format.h to avoid injecting in std. 307 // It is a template to avoid undesirable implicit conversions to std::byte. 308 #ifdef __cpp_lib_byte 309 template <typename T, FMT_ENABLE_IF(std::is_same<T, std::byte>::value)> 310 inline auto format_as(T b) -> unsigned char { 311 return static_cast<unsigned char>(b); 312 } 313 #endif 314 315 namespace detail { 316 // Suppresses "unused variable" warnings with the method described in 317 // https://herbsutter.com/2009/10/18/mailbag-shutting-up-compiler-warnings/. 318 // (void)var does not work on many Intel compilers. 319 template <typename... T> FMT_CONSTEXPR void ignore_unused(const T&...) {} 320 321 constexpr FMT_INLINE auto is_constant_evaluated( 322 bool default_value = false) noexcept -> bool { 323 // Workaround for incompatibility between libstdc++ consteval-based 324 // std::is_constant_evaluated() implementation and clang-14. 325 // https://github.com/fmtlib/fmt/issues/3247 326 #if FMT_CPLUSPLUS >= 202002L && defined(_GLIBCXX_RELEASE) && \ 327 _GLIBCXX_RELEASE >= 12 && \ 328 (FMT_CLANG_VERSION >= 1400 && FMT_CLANG_VERSION < 1500) 329 ignore_unused(default_value); 330 return __builtin_is_constant_evaluated(); 331 #elif defined(__cpp_lib_is_constant_evaluated) 332 ignore_unused(default_value); 333 return std::is_constant_evaluated(); 334 #else 335 return default_value; 336 #endif 337 } 338 339 // Suppresses "conditional expression is constant" warnings. 340 template <typename T> constexpr FMT_INLINE auto const_check(T value) -> T { 341 return value; 342 } 343 344 FMT_NORETURN FMT_API void assert_fail(const char* file, int line, 345 const char* message); 346 347 #ifndef FMT_ASSERT 348 # ifdef NDEBUG 349 // FMT_ASSERT is not empty to avoid -Wempty-body. 350 # define FMT_ASSERT(condition, message) \ 351 fmt::detail::ignore_unused((condition), (message)) 352 # else 353 # define FMT_ASSERT(condition, message) \ 354 ((condition) /* void() fails with -Winvalid-constexpr on clang 4.0.1 */ \ 355 ? (void)0 \ 356 : fmt::detail::assert_fail(__FILE__, __LINE__, (message))) 357 # endif 358 #endif 359 360 #if defined(FMT_USE_STRING_VIEW) 361 template <typename Char> using std_string_view = std::basic_string_view<Char>; 362 #elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW) 363 template <typename Char> 364 using std_string_view = std::experimental::basic_string_view<Char>; 365 #else 366 template <typename T> struct std_string_view {}; 367 #endif 368 369 #ifdef FMT_USE_INT128 370 // Do nothing. 371 #elif defined(__SIZEOF_INT128__) && !defined(__NVCC__) && \ 372 !(FMT_CLANG_VERSION && FMT_MSC_VERSION) 373 # define FMT_USE_INT128 1 374 using int128_opt = __int128_t; // An optional native 128-bit integer. 375 using uint128_opt = __uint128_t; 376 template <typename T> inline auto convert_for_visit(T value) -> T { 377 return value; 378 } 379 #else 380 # define FMT_USE_INT128 0 381 #endif 382 #if !FMT_USE_INT128 383 enum class int128_opt {}; 384 enum class uint128_opt {}; 385 // Reduce template instantiations. 386 template <typename T> auto convert_for_visit(T) -> monostate { return {}; } 387 #endif 388 389 // Casts a nonnegative integer to unsigned. 390 template <typename Int> 391 FMT_CONSTEXPR auto to_unsigned(Int value) -> 392 typename std::make_unsigned<Int>::type { 393 FMT_ASSERT(std::is_unsigned<Int>::value || value >= 0, "negative value"); 394 return static_cast<typename std::make_unsigned<Int>::type>(value); 395 } 396 397 FMT_CONSTEXPR inline auto is_utf8() -> bool { 398 FMT_MSC_WARNING(suppress : 4566) constexpr unsigned char section[] = "\u00A7"; 399 400 // Avoid buggy sign extensions in MSVC's constant evaluation mode (#2297). 401 using uchar = unsigned char; 402 return FMT_UNICODE || (sizeof(section) == 3 && uchar(section[0]) == 0xC2 && 403 uchar(section[1]) == 0xA7); 404 } 405 } // namespace detail 406 407 /** 408 An implementation of ``std::basic_string_view`` for pre-C++17. It provides a 409 subset of the API. ``fmt::basic_string_view`` is used for format strings even 410 if ``std::string_view`` is available to prevent issues when a library is 411 compiled with a different ``-std`` option than the client code (which is not 412 recommended). 413 */ 414 FMT_EXPORT 415 template <typename Char> class basic_string_view { 416 private: 417 const Char* data_; 418 size_t size_; 419 420 public: 421 using value_type = Char; 422 using iterator = const Char*; 423 424 constexpr basic_string_view() noexcept : data_(nullptr), size_(0) {} 425 426 /** Constructs a string reference object from a C string and a size. */ 427 constexpr basic_string_view(const Char* s, size_t count) noexcept 428 : data_(s), size_(count) {} 429 430 /** 431 \rst 432 Constructs a string reference object from a C string computing 433 the size with ``std::char_traits<Char>::length``. 434 \endrst 435 */ 436 FMT_CONSTEXPR_CHAR_TRAITS 437 FMT_INLINE 438 basic_string_view(const Char* s) 439 : data_(s), 440 size_(detail::const_check(std::is_same<Char, char>::value && 441 !detail::is_constant_evaluated(true)) 442 ? std::strlen(reinterpret_cast<const char*>(s)) 443 : std::char_traits<Char>::length(s)) {} 444 445 /** Constructs a string reference from a ``std::basic_string`` object. */ 446 template <typename Traits, typename Alloc> 447 FMT_CONSTEXPR basic_string_view( 448 const std::basic_string<Char, Traits, Alloc>& s) noexcept 449 : data_(s.data()), size_(s.size()) {} 450 451 template <typename S, FMT_ENABLE_IF(std::is_same< 452 S, detail::std_string_view<Char>>::value)> 453 FMT_CONSTEXPR basic_string_view(S s) noexcept 454 : data_(s.data()), size_(s.size()) {} 455 456 /** Returns a pointer to the string data. */ 457 constexpr auto data() const noexcept -> const Char* { return data_; } 458 459 /** Returns the string size. */ 460 constexpr auto size() const noexcept -> size_t { return size_; } 461 462 constexpr auto begin() const noexcept -> iterator { return data_; } 463 constexpr auto end() const noexcept -> iterator { return data_ + size_; } 464 465 constexpr auto operator[](size_t pos) const noexcept -> const Char& { 466 return data_[pos]; 467 } 468 469 FMT_CONSTEXPR void remove_prefix(size_t n) noexcept { 470 data_ += n; 471 size_ -= n; 472 } 473 474 FMT_CONSTEXPR_CHAR_TRAITS auto starts_with( 475 basic_string_view<Char> sv) const noexcept -> bool { 476 return size_ >= sv.size_ && 477 std::char_traits<Char>::compare(data_, sv.data_, sv.size_) == 0; 478 } 479 FMT_CONSTEXPR_CHAR_TRAITS auto starts_with(Char c) const noexcept -> bool { 480 return size_ >= 1 && std::char_traits<Char>::eq(*data_, c); 481 } 482 FMT_CONSTEXPR_CHAR_TRAITS auto starts_with(const Char* s) const -> bool { 483 return starts_with(basic_string_view<Char>(s)); 484 } 485 486 // Lexicographically compare this string reference to other. 487 FMT_CONSTEXPR_CHAR_TRAITS auto compare(basic_string_view other) const -> int { 488 size_t str_size = size_ < other.size_ ? size_ : other.size_; 489 int result = std::char_traits<Char>::compare(data_, other.data_, str_size); 490 if (result == 0) 491 result = size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1); 492 return result; 493 } 494 495 FMT_CONSTEXPR_CHAR_TRAITS friend auto operator==(basic_string_view lhs, 496 basic_string_view rhs) 497 -> bool { 498 return lhs.compare(rhs) == 0; 499 } 500 friend auto operator!=(basic_string_view lhs, basic_string_view rhs) -> bool { 501 return lhs.compare(rhs) != 0; 502 } 503 friend auto operator<(basic_string_view lhs, basic_string_view rhs) -> bool { 504 return lhs.compare(rhs) < 0; 505 } 506 friend auto operator<=(basic_string_view lhs, basic_string_view rhs) -> bool { 507 return lhs.compare(rhs) <= 0; 508 } 509 friend auto operator>(basic_string_view lhs, basic_string_view rhs) -> bool { 510 return lhs.compare(rhs) > 0; 511 } 512 friend auto operator>=(basic_string_view lhs, basic_string_view rhs) -> bool { 513 return lhs.compare(rhs) >= 0; 514 } 515 }; 516 517 FMT_EXPORT 518 using string_view = basic_string_view<char>; 519 520 /** Specifies if ``T`` is a character type. Can be specialized by users. */ 521 FMT_EXPORT 522 template <typename T> struct is_char : std::false_type {}; 523 template <> struct is_char<char> : std::true_type {}; 524 525 namespace detail { 526 527 // A base class for compile-time strings. 528 struct compile_string {}; 529 530 template <typename S> 531 struct is_compile_string : std::is_base_of<compile_string, S> {}; 532 533 template <typename Char, FMT_ENABLE_IF(is_char<Char>::value)> 534 FMT_INLINE auto to_string_view(const Char* s) -> basic_string_view<Char> { 535 return s; 536 } 537 template <typename Char, typename Traits, typename Alloc> 538 inline auto to_string_view(const std::basic_string<Char, Traits, Alloc>& s) 539 -> basic_string_view<Char> { 540 return s; 541 } 542 template <typename Char> 543 constexpr auto to_string_view(basic_string_view<Char> s) 544 -> basic_string_view<Char> { 545 return s; 546 } 547 template <typename Char, 548 FMT_ENABLE_IF(!std::is_empty<std_string_view<Char>>::value)> 549 inline auto to_string_view(std_string_view<Char> s) -> basic_string_view<Char> { 550 return s; 551 } 552 template <typename S, FMT_ENABLE_IF(is_compile_string<S>::value)> 553 constexpr auto to_string_view(const S& s) 554 -> basic_string_view<typename S::char_type> { 555 return basic_string_view<typename S::char_type>(s); 556 } 557 void to_string_view(...); 558 559 // Specifies whether S is a string type convertible to fmt::basic_string_view. 560 // It should be a constexpr function but MSVC 2017 fails to compile it in 561 // enable_if and MSVC 2015 fails to compile it as an alias template. 562 // ADL is intentionally disabled as to_string_view is not an extension point. 563 template <typename S> 564 struct is_string 565 : std::is_class<decltype(detail::to_string_view(std::declval<S>()))> {}; 566 567 template <typename S, typename = void> struct char_t_impl {}; 568 template <typename S> struct char_t_impl<S, enable_if_t<is_string<S>::value>> { 569 using result = decltype(to_string_view(std::declval<S>())); 570 using type = typename result::value_type; 571 }; 572 573 enum class type { 574 none_type, 575 // Integer types should go first, 576 int_type, 577 uint_type, 578 long_long_type, 579 ulong_long_type, 580 int128_type, 581 uint128_type, 582 bool_type, 583 char_type, 584 last_integer_type = char_type, 585 // followed by floating-point types. 586 float_type, 587 double_type, 588 long_double_type, 589 last_numeric_type = long_double_type, 590 cstring_type, 591 string_type, 592 pointer_type, 593 custom_type 594 }; 595 596 // Maps core type T to the corresponding type enum constant. 597 template <typename T, typename Char> 598 struct type_constant : std::integral_constant<type, type::custom_type> {}; 599 600 #define FMT_TYPE_CONSTANT(Type, constant) \ 601 template <typename Char> \ 602 struct type_constant<Type, Char> \ 603 : std::integral_constant<type, type::constant> {} 604 605 FMT_TYPE_CONSTANT(int, int_type); 606 FMT_TYPE_CONSTANT(unsigned, uint_type); 607 FMT_TYPE_CONSTANT(long long, long_long_type); 608 FMT_TYPE_CONSTANT(unsigned long long, ulong_long_type); 609 FMT_TYPE_CONSTANT(int128_opt, int128_type); 610 FMT_TYPE_CONSTANT(uint128_opt, uint128_type); 611 FMT_TYPE_CONSTANT(bool, bool_type); 612 FMT_TYPE_CONSTANT(Char, char_type); 613 FMT_TYPE_CONSTANT(float, float_type); 614 FMT_TYPE_CONSTANT(double, double_type); 615 FMT_TYPE_CONSTANT(long double, long_double_type); 616 FMT_TYPE_CONSTANT(const Char*, cstring_type); 617 FMT_TYPE_CONSTANT(basic_string_view<Char>, string_type); 618 FMT_TYPE_CONSTANT(const void*, pointer_type); 619 620 constexpr auto is_integral_type(type t) -> bool { 621 return t > type::none_type && t <= type::last_integer_type; 622 } 623 constexpr auto is_arithmetic_type(type t) -> bool { 624 return t > type::none_type && t <= type::last_numeric_type; 625 } 626 627 constexpr auto set(type rhs) -> int { return 1 << static_cast<int>(rhs); } 628 constexpr auto in(type t, int set) -> bool { 629 return ((set >> static_cast<int>(t)) & 1) != 0; 630 } 631 632 // Bitsets of types. 633 enum { 634 sint_set = 635 set(type::int_type) | set(type::long_long_type) | set(type::int128_type), 636 uint_set = set(type::uint_type) | set(type::ulong_long_type) | 637 set(type::uint128_type), 638 bool_set = set(type::bool_type), 639 char_set = set(type::char_type), 640 float_set = set(type::float_type) | set(type::double_type) | 641 set(type::long_double_type), 642 string_set = set(type::string_type), 643 cstring_set = set(type::cstring_type), 644 pointer_set = set(type::pointer_type) 645 }; 646 647 // DEPRECATED! 648 FMT_NORETURN FMT_API void throw_format_error(const char* message); 649 650 struct error_handler { 651 constexpr error_handler() = default; 652 653 // This function is intentionally not constexpr to give a compile-time error. 654 FMT_NORETURN void on_error(const char* message) { 655 throw_format_error(message); 656 } 657 }; 658 } // namespace detail 659 660 /** Throws ``format_error`` with a given message. */ 661 using detail::throw_format_error; 662 663 /** String's character type. */ 664 template <typename S> using char_t = typename detail::char_t_impl<S>::type; 665 666 /** 667 \rst 668 Parsing context consisting of a format string range being parsed and an 669 argument counter for automatic indexing. 670 You can use the ``format_parse_context`` type alias for ``char`` instead. 671 \endrst 672 */ 673 FMT_EXPORT 674 template <typename Char> class basic_format_parse_context { 675 private: 676 basic_string_view<Char> format_str_; 677 int next_arg_id_; 678 679 FMT_CONSTEXPR void do_check_arg_id(int id); 680 681 public: 682 using char_type = Char; 683 using iterator = const Char*; 684 685 explicit constexpr basic_format_parse_context( 686 basic_string_view<Char> format_str, int next_arg_id = 0) 687 : format_str_(format_str), next_arg_id_(next_arg_id) {} 688 689 /** 690 Returns an iterator to the beginning of the format string range being 691 parsed. 692 */ 693 constexpr auto begin() const noexcept -> iterator { 694 return format_str_.begin(); 695 } 696 697 /** 698 Returns an iterator past the end of the format string range being parsed. 699 */ 700 constexpr auto end() const noexcept -> iterator { return format_str_.end(); } 701 702 /** Advances the begin iterator to ``it``. */ 703 FMT_CONSTEXPR void advance_to(iterator it) { 704 format_str_.remove_prefix(detail::to_unsigned(it - begin())); 705 } 706 707 /** 708 Reports an error if using the manual argument indexing; otherwise returns 709 the next argument index and switches to the automatic indexing. 710 */ 711 FMT_CONSTEXPR auto next_arg_id() -> int { 712 if (next_arg_id_ < 0) { 713 detail::throw_format_error( 714 "cannot switch from manual to automatic argument indexing"); 715 return 0; 716 } 717 int id = next_arg_id_++; 718 do_check_arg_id(id); 719 return id; 720 } 721 722 /** 723 Reports an error if using the automatic argument indexing; otherwise 724 switches to the manual indexing. 725 */ 726 FMT_CONSTEXPR void check_arg_id(int id) { 727 if (next_arg_id_ > 0) { 728 detail::throw_format_error( 729 "cannot switch from automatic to manual argument indexing"); 730 return; 731 } 732 next_arg_id_ = -1; 733 do_check_arg_id(id); 734 } 735 FMT_CONSTEXPR void check_arg_id(basic_string_view<Char>) {} 736 FMT_CONSTEXPR void check_dynamic_spec(int arg_id); 737 }; 738 739 FMT_EXPORT 740 using format_parse_context = basic_format_parse_context<char>; 741 742 namespace detail { 743 // A parse context with extra data used only in compile-time checks. 744 template <typename Char> 745 class compile_parse_context : public basic_format_parse_context<Char> { 746 private: 747 int num_args_; 748 const type* types_; 749 using base = basic_format_parse_context<Char>; 750 751 public: 752 explicit FMT_CONSTEXPR compile_parse_context( 753 basic_string_view<Char> format_str, int num_args, const type* types, 754 int next_arg_id = 0) 755 : base(format_str, next_arg_id), num_args_(num_args), types_(types) {} 756 757 constexpr auto num_args() const -> int { return num_args_; } 758 constexpr auto arg_type(int id) const -> type { return types_[id]; } 759 760 FMT_CONSTEXPR auto next_arg_id() -> int { 761 int id = base::next_arg_id(); 762 if (id >= num_args_) throw_format_error("argument not found"); 763 return id; 764 } 765 766 FMT_CONSTEXPR void check_arg_id(int id) { 767 base::check_arg_id(id); 768 if (id >= num_args_) throw_format_error("argument not found"); 769 } 770 using base::check_arg_id; 771 772 FMT_CONSTEXPR void check_dynamic_spec(int arg_id) { 773 detail::ignore_unused(arg_id); 774 #if !defined(__LCC__) 775 if (arg_id < num_args_ && types_ && !is_integral_type(types_[arg_id])) 776 throw_format_error("width/precision is not integer"); 777 #endif 778 } 779 }; 780 781 // Extracts a reference to the container from back_insert_iterator. 782 template <typename Container> 783 inline auto get_container(std::back_insert_iterator<Container> it) 784 -> Container& { 785 using base = std::back_insert_iterator<Container>; 786 struct accessor : base { 787 accessor(base b) : base(b) {} 788 using base::container; 789 }; 790 return *accessor(it).container; 791 } 792 793 template <typename Char, typename InputIt, typename OutputIt> 794 FMT_CONSTEXPR auto copy_str(InputIt begin, InputIt end, OutputIt out) 795 -> OutputIt { 796 while (begin != end) *out++ = static_cast<Char>(*begin++); 797 return out; 798 } 799 800 template <typename Char, typename T, typename U, 801 FMT_ENABLE_IF( 802 std::is_same<remove_const_t<T>, U>::value&& is_char<U>::value)> 803 FMT_CONSTEXPR auto copy_str(T* begin, T* end, U* out) -> U* { 804 if (is_constant_evaluated()) return copy_str<Char, T*, U*>(begin, end, out); 805 auto size = to_unsigned(end - begin); 806 if (size > 0) memcpy(out, begin, size * sizeof(U)); 807 return out + size; 808 } 809 810 /** 811 \rst 812 A contiguous memory buffer with an optional growing ability. It is an internal 813 class and shouldn't be used directly, only via `~fmt::basic_memory_buffer`. 814 \endrst 815 */ 816 template <typename T> class buffer { 817 private: 818 T* ptr_; 819 size_t size_; 820 size_t capacity_; 821 822 protected: 823 // Don't initialize ptr_ since it is not accessed to save a few cycles. 824 FMT_MSC_WARNING(suppress : 26495) 825 FMT_CONSTEXPR buffer(size_t sz) noexcept : size_(sz), capacity_(sz) {} 826 827 FMT_CONSTEXPR20 buffer(T* p = nullptr, size_t sz = 0, size_t cap = 0) noexcept 828 : ptr_(p), size_(sz), capacity_(cap) {} 829 830 FMT_CONSTEXPR20 ~buffer() = default; 831 buffer(buffer&&) = default; 832 833 /** Sets the buffer data and capacity. */ 834 FMT_CONSTEXPR void set(T* buf_data, size_t buf_capacity) noexcept { 835 ptr_ = buf_data; 836 capacity_ = buf_capacity; 837 } 838 839 /** Increases the buffer capacity to hold at least *capacity* elements. */ 840 // DEPRECATED! 841 virtual FMT_CONSTEXPR20 void grow(size_t capacity) = 0; 842 843 public: 844 using value_type = T; 845 using const_reference = const T&; 846 847 buffer(const buffer&) = delete; 848 void operator=(const buffer&) = delete; 849 850 FMT_INLINE auto begin() noexcept -> T* { return ptr_; } 851 FMT_INLINE auto end() noexcept -> T* { return ptr_ + size_; } 852 853 FMT_INLINE auto begin() const noexcept -> const T* { return ptr_; } 854 FMT_INLINE auto end() const noexcept -> const T* { return ptr_ + size_; } 855 856 /** Returns the size of this buffer. */ 857 constexpr auto size() const noexcept -> size_t { return size_; } 858 859 /** Returns the capacity of this buffer. */ 860 constexpr auto capacity() const noexcept -> size_t { return capacity_; } 861 862 /** Returns a pointer to the buffer data (not null-terminated). */ 863 FMT_CONSTEXPR auto data() noexcept -> T* { return ptr_; } 864 FMT_CONSTEXPR auto data() const noexcept -> const T* { return ptr_; } 865 866 /** Clears this buffer. */ 867 void clear() { size_ = 0; } 868 869 // Tries resizing the buffer to contain *count* elements. If T is a POD type 870 // the new elements may not be initialized. 871 FMT_CONSTEXPR20 void try_resize(size_t count) { 872 try_reserve(count); 873 size_ = count <= capacity_ ? count : capacity_; 874 } 875 876 // Tries increasing the buffer capacity to *new_capacity*. It can increase the 877 // capacity by a smaller amount than requested but guarantees there is space 878 // for at least one additional element either by increasing the capacity or by 879 // flushing the buffer if it is full. 880 FMT_CONSTEXPR20 void try_reserve(size_t new_capacity) { 881 if (new_capacity > capacity_) grow(new_capacity); 882 } 883 884 FMT_CONSTEXPR20 void push_back(const T& value) { 885 try_reserve(size_ + 1); 886 ptr_[size_++] = value; 887 } 888 889 /** Appends data to the end of the buffer. */ 890 template <typename U> void append(const U* begin, const U* end); 891 892 template <typename Idx> FMT_CONSTEXPR auto operator[](Idx index) -> T& { 893 return ptr_[index]; 894 } 895 template <typename Idx> 896 FMT_CONSTEXPR auto operator[](Idx index) const -> const T& { 897 return ptr_[index]; 898 } 899 }; 900 901 struct buffer_traits { 902 explicit buffer_traits(size_t) {} 903 auto count() const -> size_t { return 0; } 904 auto limit(size_t size) -> size_t { return size; } 905 }; 906 907 class fixed_buffer_traits { 908 private: 909 size_t count_ = 0; 910 size_t limit_; 911 912 public: 913 explicit fixed_buffer_traits(size_t limit) : limit_(limit) {} 914 auto count() const -> size_t { return count_; } 915 auto limit(size_t size) -> size_t { 916 size_t n = limit_ > count_ ? limit_ - count_ : 0; 917 count_ += size; 918 return size < n ? size : n; 919 } 920 }; 921 922 // A buffer that writes to an output iterator when flushed. 923 template <typename OutputIt, typename T, typename Traits = buffer_traits> 924 class iterator_buffer final : public Traits, public buffer<T> { 925 private: 926 OutputIt out_; 927 enum { buffer_size = 256 }; 928 T data_[buffer_size]; 929 930 protected: 931 FMT_CONSTEXPR20 void grow(size_t) override { 932 if (this->size() == buffer_size) flush(); 933 } 934 935 void flush() { 936 auto size = this->size(); 937 this->clear(); 938 out_ = copy_str<T>(data_, data_ + this->limit(size), out_); 939 } 940 941 public: 942 explicit iterator_buffer(OutputIt out, size_t n = buffer_size) 943 : Traits(n), buffer<T>(data_, 0, buffer_size), out_(out) {} 944 iterator_buffer(iterator_buffer&& other) 945 : Traits(other), buffer<T>(data_, 0, buffer_size), out_(other.out_) {} 946 ~iterator_buffer() { flush(); } 947 948 auto out() -> OutputIt { 949 flush(); 950 return out_; 951 } 952 auto count() const -> size_t { return Traits::count() + this->size(); } 953 }; 954 955 template <typename T> 956 class iterator_buffer<T*, T, fixed_buffer_traits> final 957 : public fixed_buffer_traits, 958 public buffer<T> { 959 private: 960 T* out_; 961 enum { buffer_size = 256 }; 962 T data_[buffer_size]; 963 964 protected: 965 FMT_CONSTEXPR20 void grow(size_t) override { 966 if (this->size() == this->capacity()) flush(); 967 } 968 969 void flush() { 970 size_t n = this->limit(this->size()); 971 if (this->data() == out_) { 972 out_ += n; 973 this->set(data_, buffer_size); 974 } 975 this->clear(); 976 } 977 978 public: 979 explicit iterator_buffer(T* out, size_t n = buffer_size) 980 : fixed_buffer_traits(n), buffer<T>(out, 0, n), out_(out) {} 981 iterator_buffer(iterator_buffer&& other) 982 : fixed_buffer_traits(other), 983 buffer<T>(std::move(other)), 984 out_(other.out_) { 985 if (this->data() != out_) { 986 this->set(data_, buffer_size); 987 this->clear(); 988 } 989 } 990 ~iterator_buffer() { flush(); } 991 992 auto out() -> T* { 993 flush(); 994 return out_; 995 } 996 auto count() const -> size_t { 997 return fixed_buffer_traits::count() + this->size(); 998 } 999 }; 1000 1001 template <typename T> class iterator_buffer<T*, T> final : public buffer<T> { 1002 protected: 1003 FMT_CONSTEXPR20 void grow(size_t) override {} 1004 1005 public: 1006 explicit iterator_buffer(T* out, size_t = 0) : buffer<T>(out, 0, ~size_t()) {} 1007 1008 auto out() -> T* { return &*this->end(); } 1009 }; 1010 1011 // A buffer that writes to a container with the contiguous storage. 1012 template <typename Container> 1013 class iterator_buffer<std::back_insert_iterator<Container>, 1014 enable_if_t<is_contiguous<Container>::value, 1015 typename Container::value_type>> 1016 final : public buffer<typename Container::value_type> { 1017 private: 1018 Container& container_; 1019 1020 protected: 1021 FMT_CONSTEXPR20 void grow(size_t capacity) override { 1022 container_.resize(capacity); 1023 this->set(&container_[0], capacity); 1024 } 1025 1026 public: 1027 explicit iterator_buffer(Container& c) 1028 : buffer<typename Container::value_type>(c.size()), container_(c) {} 1029 explicit iterator_buffer(std::back_insert_iterator<Container> out, size_t = 0) 1030 : iterator_buffer(get_container(out)) {} 1031 1032 auto out() -> std::back_insert_iterator<Container> { 1033 return std::back_inserter(container_); 1034 } 1035 }; 1036 1037 // A buffer that counts the number of code units written discarding the output. 1038 template <typename T = char> class counting_buffer final : public buffer<T> { 1039 private: 1040 enum { buffer_size = 256 }; 1041 T data_[buffer_size]; 1042 size_t count_ = 0; 1043 1044 protected: 1045 FMT_CONSTEXPR20 void grow(size_t) override { 1046 if (this->size() != buffer_size) return; 1047 count_ += this->size(); 1048 this->clear(); 1049 } 1050 1051 public: 1052 counting_buffer() : buffer<T>(data_, 0, buffer_size) {} 1053 1054 auto count() -> size_t { return count_ + this->size(); } 1055 }; 1056 } // namespace detail 1057 1058 template <typename Char> 1059 FMT_CONSTEXPR void basic_format_parse_context<Char>::do_check_arg_id(int id) { 1060 // Argument id is only checked at compile-time during parsing because 1061 // formatting has its own validation. 1062 if (detail::is_constant_evaluated() && 1063 (!FMT_GCC_VERSION || FMT_GCC_VERSION >= 1200)) { 1064 using context = detail::compile_parse_context<Char>; 1065 if (id >= static_cast<context*>(this)->num_args()) 1066 detail::throw_format_error("argument not found"); 1067 } 1068 } 1069 1070 template <typename Char> 1071 FMT_CONSTEXPR void basic_format_parse_context<Char>::check_dynamic_spec( 1072 int arg_id) { 1073 if (detail::is_constant_evaluated() && 1074 (!FMT_GCC_VERSION || FMT_GCC_VERSION >= 1200)) { 1075 using context = detail::compile_parse_context<Char>; 1076 static_cast<context*>(this)->check_dynamic_spec(arg_id); 1077 } 1078 } 1079 1080 FMT_EXPORT template <typename Context> class basic_format_arg; 1081 FMT_EXPORT template <typename Context> class basic_format_args; 1082 FMT_EXPORT template <typename Context> class dynamic_format_arg_store; 1083 1084 // A formatter for objects of type T. 1085 FMT_EXPORT 1086 template <typename T, typename Char = char, typename Enable = void> 1087 struct formatter { 1088 // A deleted default constructor indicates a disabled formatter. 1089 formatter() = delete; 1090 }; 1091 1092 // Specifies if T has an enabled formatter specialization. A type can be 1093 // formattable even if it doesn't have a formatter e.g. via a conversion. 1094 template <typename T, typename Context> 1095 using has_formatter = 1096 std::is_constructible<typename Context::template formatter_type<T>>; 1097 1098 // An output iterator that appends to a buffer. 1099 // It is used to reduce symbol sizes for the common case. 1100 class appender : public std::back_insert_iterator<detail::buffer<char>> { 1101 using base = std::back_insert_iterator<detail::buffer<char>>; 1102 1103 public: 1104 using std::back_insert_iterator<detail::buffer<char>>::back_insert_iterator; 1105 appender(base it) noexcept : base(it) {} 1106 FMT_UNCHECKED_ITERATOR(appender); 1107 1108 auto operator++() noexcept -> appender& { return *this; } 1109 auto operator++(int) noexcept -> appender { return *this; } 1110 }; 1111 1112 namespace detail { 1113 1114 template <typename Context, typename T> 1115 constexpr auto has_const_formatter_impl(T*) 1116 -> decltype(typename Context::template formatter_type<T>().format( 1117 std::declval<const T&>(), std::declval<Context&>()), 1118 true) { 1119 return true; 1120 } 1121 template <typename Context> 1122 constexpr auto has_const_formatter_impl(...) -> bool { 1123 return false; 1124 } 1125 template <typename T, typename Context> 1126 constexpr auto has_const_formatter() -> bool { 1127 return has_const_formatter_impl<Context>(static_cast<T*>(nullptr)); 1128 } 1129 1130 template <typename T> 1131 using buffer_appender = conditional_t<std::is_same<T, char>::value, appender, 1132 std::back_insert_iterator<buffer<T>>>; 1133 1134 // Maps an output iterator to a buffer. 1135 template <typename T, typename OutputIt> 1136 auto get_buffer(OutputIt out) -> iterator_buffer<OutputIt, T> { 1137 return iterator_buffer<OutputIt, T>(out); 1138 } 1139 template <typename T, typename Buf, 1140 FMT_ENABLE_IF(std::is_base_of<buffer<char>, Buf>::value)> 1141 auto get_buffer(std::back_insert_iterator<Buf> out) -> buffer<char>& { 1142 return get_container(out); 1143 } 1144 1145 template <typename Buf, typename OutputIt> 1146 FMT_INLINE auto get_iterator(Buf& buf, OutputIt) -> decltype(buf.out()) { 1147 return buf.out(); 1148 } 1149 template <typename T, typename OutputIt> 1150 auto get_iterator(buffer<T>&, OutputIt out) -> OutputIt { 1151 return out; 1152 } 1153 1154 struct view {}; 1155 1156 template <typename Char, typename T> struct named_arg : view { 1157 const Char* name; 1158 const T& value; 1159 named_arg(const Char* n, const T& v) : name(n), value(v) {} 1160 }; 1161 1162 template <typename Char> struct named_arg_info { 1163 const Char* name; 1164 int id; 1165 }; 1166 1167 template <typename T, typename Char, size_t NUM_ARGS, size_t NUM_NAMED_ARGS> 1168 struct arg_data { 1169 // args_[0].named_args points to named_args_ to avoid bloating format_args. 1170 // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning. 1171 T args_[1 + (NUM_ARGS != 0 ? NUM_ARGS : +1)]; 1172 named_arg_info<Char> named_args_[NUM_NAMED_ARGS]; 1173 1174 template <typename... U> 1175 arg_data(const U&... init) : args_{T(named_args_, NUM_NAMED_ARGS), init...} {} 1176 arg_data(const arg_data& other) = delete; 1177 auto args() const -> const T* { return args_ + 1; } 1178 auto named_args() -> named_arg_info<Char>* { return named_args_; } 1179 }; 1180 1181 template <typename T, typename Char, size_t NUM_ARGS> 1182 struct arg_data<T, Char, NUM_ARGS, 0> { 1183 // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning. 1184 T args_[NUM_ARGS != 0 ? NUM_ARGS : +1]; 1185 1186 template <typename... U> 1187 FMT_CONSTEXPR FMT_INLINE arg_data(const U&... init) : args_{init...} {} 1188 FMT_CONSTEXPR FMT_INLINE auto args() const -> const T* { return args_; } 1189 FMT_CONSTEXPR FMT_INLINE auto named_args() -> std::nullptr_t { 1190 return nullptr; 1191 } 1192 }; 1193 1194 template <typename Char> 1195 inline void init_named_args(named_arg_info<Char>*, int, int) {} 1196 1197 template <typename T> struct is_named_arg : std::false_type {}; 1198 template <typename T> struct is_statically_named_arg : std::false_type {}; 1199 1200 template <typename T, typename Char> 1201 struct is_named_arg<named_arg<Char, T>> : std::true_type {}; 1202 1203 template <typename Char, typename T, typename... Tail, 1204 FMT_ENABLE_IF(!is_named_arg<T>::value)> 1205 void init_named_args(named_arg_info<Char>* named_args, int arg_count, 1206 int named_arg_count, const T&, const Tail&... args) { 1207 init_named_args(named_args, arg_count + 1, named_arg_count, args...); 1208 } 1209 1210 template <typename Char, typename T, typename... Tail, 1211 FMT_ENABLE_IF(is_named_arg<T>::value)> 1212 void init_named_args(named_arg_info<Char>* named_args, int arg_count, 1213 int named_arg_count, const T& arg, const Tail&... args) { 1214 named_args[named_arg_count++] = {arg.name, arg_count}; 1215 init_named_args(named_args, arg_count + 1, named_arg_count, args...); 1216 } 1217 1218 template <typename... Args> 1219 FMT_CONSTEXPR FMT_INLINE void init_named_args(std::nullptr_t, int, int, 1220 const Args&...) {} 1221 1222 template <bool B = false> constexpr auto count() -> size_t { return B ? 1 : 0; } 1223 template <bool B1, bool B2, bool... Tail> constexpr auto count() -> size_t { 1224 return (B1 ? 1 : 0) + count<B2, Tail...>(); 1225 } 1226 1227 template <typename... Args> constexpr auto count_named_args() -> size_t { 1228 return count<is_named_arg<Args>::value...>(); 1229 } 1230 1231 template <typename... Args> 1232 constexpr auto count_statically_named_args() -> size_t { 1233 return count<is_statically_named_arg<Args>::value...>(); 1234 } 1235 1236 struct unformattable {}; 1237 struct unformattable_char : unformattable {}; 1238 struct unformattable_pointer : unformattable {}; 1239 1240 template <typename Char> struct string_value { 1241 const Char* data; 1242 size_t size; 1243 }; 1244 1245 template <typename Char> struct named_arg_value { 1246 const named_arg_info<Char>* data; 1247 size_t size; 1248 }; 1249 1250 template <typename Context> struct custom_value { 1251 using parse_context = typename Context::parse_context_type; 1252 void* value; 1253 void (*format)(void* arg, parse_context& parse_ctx, Context& ctx); 1254 }; 1255 1256 // A formatting argument value. 1257 template <typename Context> class value { 1258 public: 1259 using char_type = typename Context::char_type; 1260 1261 union { 1262 monostate no_value; 1263 int int_value; 1264 unsigned uint_value; 1265 long long long_long_value; 1266 unsigned long long ulong_long_value; 1267 int128_opt int128_value; 1268 uint128_opt uint128_value; 1269 bool bool_value; 1270 char_type char_value; 1271 float float_value; 1272 double double_value; 1273 long double long_double_value; 1274 const void* pointer; 1275 string_value<char_type> string; 1276 custom_value<Context> custom; 1277 named_arg_value<char_type> named_args; 1278 }; 1279 1280 constexpr FMT_INLINE value() : no_value() {} 1281 constexpr FMT_INLINE value(int val) : int_value(val) {} 1282 constexpr FMT_INLINE value(unsigned val) : uint_value(val) {} 1283 constexpr FMT_INLINE value(long long val) : long_long_value(val) {} 1284 constexpr FMT_INLINE value(unsigned long long val) : ulong_long_value(val) {} 1285 FMT_INLINE value(int128_opt val) : int128_value(val) {} 1286 FMT_INLINE value(uint128_opt val) : uint128_value(val) {} 1287 constexpr FMT_INLINE value(float val) : float_value(val) {} 1288 constexpr FMT_INLINE value(double val) : double_value(val) {} 1289 FMT_INLINE value(long double val) : long_double_value(val) {} 1290 constexpr FMT_INLINE value(bool val) : bool_value(val) {} 1291 constexpr FMT_INLINE value(char_type val) : char_value(val) {} 1292 FMT_CONSTEXPR FMT_INLINE value(const char_type* val) { 1293 string.data = val; 1294 if (is_constant_evaluated()) string.size = {}; 1295 } 1296 FMT_CONSTEXPR FMT_INLINE value(basic_string_view<char_type> val) { 1297 string.data = val.data(); 1298 string.size = val.size(); 1299 } 1300 FMT_INLINE value(const void* val) : pointer(val) {} 1301 FMT_INLINE value(const named_arg_info<char_type>* args, size_t size) 1302 : named_args{args, size} {} 1303 1304 template <typename T> FMT_CONSTEXPR20 FMT_INLINE value(T& val) { 1305 using value_type = remove_const_t<T>; 1306 custom.value = const_cast<value_type*>(std::addressof(val)); 1307 // Get the formatter type through the context to allow different contexts 1308 // have different extension points, e.g. `formatter<T>` for `format` and 1309 // `printf_formatter<T>` for `printf`. 1310 custom.format = format_custom_arg< 1311 value_type, typename Context::template formatter_type<value_type>>; 1312 } 1313 value(unformattable); 1314 value(unformattable_char); 1315 value(unformattable_pointer); 1316 1317 private: 1318 // Formats an argument of a custom type, such as a user-defined class. 1319 template <typename T, typename Formatter> 1320 static void format_custom_arg(void* arg, 1321 typename Context::parse_context_type& parse_ctx, 1322 Context& ctx) { 1323 auto f = Formatter(); 1324 parse_ctx.advance_to(f.parse(parse_ctx)); 1325 using qualified_type = 1326 conditional_t<has_const_formatter<T, Context>(), const T, T>; 1327 // Calling format through a mutable reference is deprecated. 1328 ctx.advance_to(f.format(*static_cast<qualified_type*>(arg), ctx)); 1329 } 1330 }; 1331 1332 // To minimize the number of types we need to deal with, long is translated 1333 // either to int or to long long depending on its size. 1334 enum { long_short = sizeof(long) == sizeof(int) }; 1335 using long_type = conditional_t<long_short, int, long long>; 1336 using ulong_type = conditional_t<long_short, unsigned, unsigned long long>; 1337 1338 template <typename T> struct format_as_result { 1339 template <typename U, 1340 FMT_ENABLE_IF(std::is_enum<U>::value || std::is_class<U>::value)> 1341 static auto map(U*) -> remove_cvref_t<decltype(format_as(std::declval<U>()))>; 1342 static auto map(...) -> void; 1343 1344 using type = decltype(map(static_cast<T*>(nullptr))); 1345 }; 1346 template <typename T> using format_as_t = typename format_as_result<T>::type; 1347 1348 template <typename T> 1349 struct has_format_as 1350 : bool_constant<!std::is_same<format_as_t<T>, void>::value> {}; 1351 1352 // Maps formatting arguments to core types. 1353 // arg_mapper reports errors by returning unformattable instead of using 1354 // static_assert because it's used in the is_formattable trait. 1355 template <typename Context> struct arg_mapper { 1356 using char_type = typename Context::char_type; 1357 1358 FMT_CONSTEXPR FMT_INLINE auto map(signed char val) -> int { return val; } 1359 FMT_CONSTEXPR FMT_INLINE auto map(unsigned char val) -> unsigned { 1360 return val; 1361 } 1362 FMT_CONSTEXPR FMT_INLINE auto map(short val) -> int { return val; } 1363 FMT_CONSTEXPR FMT_INLINE auto map(unsigned short val) -> unsigned { 1364 return val; 1365 } 1366 FMT_CONSTEXPR FMT_INLINE auto map(int val) -> int { return val; } 1367 FMT_CONSTEXPR FMT_INLINE auto map(unsigned val) -> unsigned { return val; } 1368 FMT_CONSTEXPR FMT_INLINE auto map(long val) -> long_type { return val; } 1369 FMT_CONSTEXPR FMT_INLINE auto map(unsigned long val) -> ulong_type { 1370 return val; 1371 } 1372 FMT_CONSTEXPR FMT_INLINE auto map(long long val) -> long long { return val; } 1373 FMT_CONSTEXPR FMT_INLINE auto map(unsigned long long val) 1374 -> unsigned long long { 1375 return val; 1376 } 1377 FMT_CONSTEXPR FMT_INLINE auto map(int128_opt val) -> int128_opt { 1378 return val; 1379 } 1380 FMT_CONSTEXPR FMT_INLINE auto map(uint128_opt val) -> uint128_opt { 1381 return val; 1382 } 1383 FMT_CONSTEXPR FMT_INLINE auto map(bool val) -> bool { return val; } 1384 1385 template <typename T, FMT_ENABLE_IF(std::is_same<T, char>::value || 1386 std::is_same<T, char_type>::value)> 1387 FMT_CONSTEXPR FMT_INLINE auto map(T val) -> char_type { 1388 return val; 1389 } 1390 template <typename T, enable_if_t<(std::is_same<T, wchar_t>::value || 1391 #ifdef __cpp_char8_t 1392 std::is_same<T, char8_t>::value || 1393 #endif 1394 std::is_same<T, char16_t>::value || 1395 std::is_same<T, char32_t>::value) && 1396 !std::is_same<T, char_type>::value, 1397 int> = 0> 1398 FMT_CONSTEXPR FMT_INLINE auto map(T) -> unformattable_char { 1399 return {}; 1400 } 1401 1402 FMT_CONSTEXPR FMT_INLINE auto map(float val) -> float { return val; } 1403 FMT_CONSTEXPR FMT_INLINE auto map(double val) -> double { return val; } 1404 FMT_CONSTEXPR FMT_INLINE auto map(long double val) -> long double { 1405 return val; 1406 } 1407 1408 FMT_CONSTEXPR FMT_INLINE auto map(char_type* val) -> const char_type* { 1409 return val; 1410 } 1411 FMT_CONSTEXPR FMT_INLINE auto map(const char_type* val) -> const char_type* { 1412 return val; 1413 } 1414 template <typename T, 1415 FMT_ENABLE_IF(is_string<T>::value && !std::is_pointer<T>::value && 1416 std::is_same<char_type, char_t<T>>::value)> 1417 FMT_CONSTEXPR FMT_INLINE auto map(const T& val) 1418 -> basic_string_view<char_type> { 1419 return to_string_view(val); 1420 } 1421 template <typename T, 1422 FMT_ENABLE_IF(is_string<T>::value && !std::is_pointer<T>::value && 1423 !std::is_same<char_type, char_t<T>>::value)> 1424 FMT_CONSTEXPR FMT_INLINE auto map(const T&) -> unformattable_char { 1425 return {}; 1426 } 1427 1428 FMT_CONSTEXPR FMT_INLINE auto map(void* val) -> const void* { return val; } 1429 FMT_CONSTEXPR FMT_INLINE auto map(const void* val) -> const void* { 1430 return val; 1431 } 1432 FMT_CONSTEXPR FMT_INLINE auto map(std::nullptr_t val) -> const void* { 1433 return val; 1434 } 1435 1436 // Use SFINAE instead of a const T* parameter to avoid a conflict with the 1437 // array overload. 1438 template < 1439 typename T, 1440 FMT_ENABLE_IF( 1441 std::is_pointer<T>::value || std::is_member_pointer<T>::value || 1442 std::is_function<typename std::remove_pointer<T>::type>::value || 1443 (std::is_array<T>::value && 1444 !std::is_convertible<T, const char_type*>::value))> 1445 FMT_CONSTEXPR auto map(const T&) -> unformattable_pointer { 1446 return {}; 1447 } 1448 1449 template <typename T, std::size_t N, 1450 FMT_ENABLE_IF(!std::is_same<T, wchar_t>::value)> 1451 FMT_CONSTEXPR FMT_INLINE auto map(const T (&values)[N]) -> const T (&)[N] { 1452 return values; 1453 } 1454 1455 // Only map owning types because mapping views can be unsafe. 1456 template <typename T, typename U = format_as_t<T>, 1457 FMT_ENABLE_IF(std::is_arithmetic<U>::value)> 1458 FMT_CONSTEXPR FMT_INLINE auto map(const T& val) 1459 -> decltype(FMT_DECLTYPE_THIS map(U())) { 1460 return map(format_as(val)); 1461 } 1462 1463 template <typename T, typename U = remove_const_t<T>> 1464 struct formattable : bool_constant<has_const_formatter<U, Context>() || 1465 (has_formatter<U, Context>::value && 1466 !std::is_const<T>::value)> {}; 1467 1468 template <typename T, FMT_ENABLE_IF(formattable<T>::value)> 1469 FMT_CONSTEXPR FMT_INLINE auto do_map(T& val) -> T& { 1470 return val; 1471 } 1472 template <typename T, FMT_ENABLE_IF(!formattable<T>::value)> 1473 FMT_CONSTEXPR FMT_INLINE auto do_map(T&) -> unformattable { 1474 return {}; 1475 } 1476 1477 template <typename T, typename U = remove_const_t<T>, 1478 FMT_ENABLE_IF((std::is_class<U>::value || std::is_enum<U>::value || 1479 std::is_union<U>::value) && 1480 !is_string<U>::value && !is_char<U>::value && 1481 !is_named_arg<U>::value && 1482 !std::is_arithmetic<format_as_t<U>>::value)> 1483 FMT_CONSTEXPR FMT_INLINE auto map(T& val) 1484 -> decltype(FMT_DECLTYPE_THIS do_map(val)) { 1485 return do_map(val); 1486 } 1487 1488 template <typename T, FMT_ENABLE_IF(is_named_arg<T>::value)> 1489 FMT_CONSTEXPR FMT_INLINE auto map(const T& named_arg) 1490 -> decltype(FMT_DECLTYPE_THIS map(named_arg.value)) { 1491 return map(named_arg.value); 1492 } 1493 1494 auto map(...) -> unformattable { return {}; } 1495 }; 1496 1497 // A type constant after applying arg_mapper<Context>. 1498 template <typename T, typename Context> 1499 using mapped_type_constant = 1500 type_constant<decltype(arg_mapper<Context>().map(std::declval<const T&>())), 1501 typename Context::char_type>; 1502 1503 enum { packed_arg_bits = 4 }; 1504 // Maximum number of arguments with packed types. 1505 enum { max_packed_args = 62 / packed_arg_bits }; 1506 enum : unsigned long long { is_unpacked_bit = 1ULL << 63 }; 1507 enum : unsigned long long { has_named_args_bit = 1ULL << 62 }; 1508 1509 template <typename Char, typename InputIt> 1510 auto copy_str(InputIt begin, InputIt end, appender out) -> appender { 1511 get_container(out).append(begin, end); 1512 return out; 1513 } 1514 template <typename Char, typename InputIt> 1515 auto copy_str(InputIt begin, InputIt end, 1516 std::back_insert_iterator<std::string> out) 1517 -> std::back_insert_iterator<std::string> { 1518 get_container(out).append(begin, end); 1519 return out; 1520 } 1521 1522 template <typename Char, typename R, typename OutputIt> 1523 FMT_CONSTEXPR auto copy_str(R&& rng, OutputIt out) -> OutputIt { 1524 return detail::copy_str<Char>(rng.begin(), rng.end(), out); 1525 } 1526 1527 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 500 1528 // A workaround for gcc 4.8 to make void_t work in a SFINAE context. 1529 template <typename...> struct void_t_impl { 1530 using type = void; 1531 }; 1532 template <typename... T> using void_t = typename void_t_impl<T...>::type; 1533 #else 1534 template <typename...> using void_t = void; 1535 #endif 1536 1537 template <typename It, typename T, typename Enable = void> 1538 struct is_output_iterator : std::false_type {}; 1539 1540 template <typename It, typename T> 1541 struct is_output_iterator< 1542 It, T, 1543 void_t<typename std::iterator_traits<It>::iterator_category, 1544 decltype(*std::declval<It>() = std::declval<T>())>> 1545 : std::true_type {}; 1546 1547 template <typename It> struct is_back_insert_iterator : std::false_type {}; 1548 template <typename Container> 1549 struct is_back_insert_iterator<std::back_insert_iterator<Container>> 1550 : std::true_type {}; 1551 1552 // A type-erased reference to an std::locale to avoid a heavy <locale> include. 1553 class locale_ref { 1554 private: 1555 const void* locale_; // A type-erased pointer to std::locale. 1556 1557 public: 1558 constexpr FMT_INLINE locale_ref() : locale_(nullptr) {} 1559 template <typename Locale> explicit locale_ref(const Locale& loc); 1560 1561 explicit operator bool() const noexcept { return locale_ != nullptr; } 1562 1563 template <typename Locale> auto get() const -> Locale; 1564 }; 1565 1566 template <typename> constexpr auto encode_types() -> unsigned long long { 1567 return 0; 1568 } 1569 1570 template <typename Context, typename Arg, typename... Args> 1571 constexpr auto encode_types() -> unsigned long long { 1572 return static_cast<unsigned>(mapped_type_constant<Arg, Context>::value) | 1573 (encode_types<Context, Args...>() << packed_arg_bits); 1574 } 1575 1576 #if defined(__cpp_if_constexpr) 1577 // This type is intentionally undefined, only used for errors 1578 template <typename T, typename Char> struct type_is_unformattable_for; 1579 #endif 1580 1581 template <bool PACKED, typename Context, typename T, FMT_ENABLE_IF(PACKED)> 1582 FMT_CONSTEXPR FMT_INLINE auto make_arg(T& val) -> value<Context> { 1583 using arg_type = remove_cvref_t<decltype(arg_mapper<Context>().map(val))>; 1584 1585 constexpr bool formattable_char = 1586 !std::is_same<arg_type, unformattable_char>::value; 1587 static_assert(formattable_char, "Mixing character types is disallowed."); 1588 1589 // Formatting of arbitrary pointers is disallowed. If you want to format a 1590 // pointer cast it to `void*` or `const void*`. In particular, this forbids 1591 // formatting of `[const] volatile char*` printed as bool by iostreams. 1592 constexpr bool formattable_pointer = 1593 !std::is_same<arg_type, unformattable_pointer>::value; 1594 static_assert(formattable_pointer, 1595 "Formatting of non-void pointers is disallowed."); 1596 1597 constexpr bool formattable = !std::is_same<arg_type, unformattable>::value; 1598 #if defined(__cpp_if_constexpr) 1599 if constexpr (!formattable) { 1600 type_is_unformattable_for<T, typename Context::char_type> _; 1601 } 1602 #endif 1603 static_assert( 1604 formattable, 1605 "Cannot format an argument. To make type T formattable provide a " 1606 "formatter<T> specialization: https://fmt.dev/latest/api.html#udt"); 1607 return {arg_mapper<Context>().map(val)}; 1608 } 1609 1610 template <typename Context, typename T> 1611 FMT_CONSTEXPR auto make_arg(T& val) -> basic_format_arg<Context> { 1612 auto arg = basic_format_arg<Context>(); 1613 arg.type_ = mapped_type_constant<T, Context>::value; 1614 arg.value_ = make_arg<true, Context>(val); 1615 return arg; 1616 } 1617 1618 template <bool PACKED, typename Context, typename T, FMT_ENABLE_IF(!PACKED)> 1619 FMT_CONSTEXPR inline auto make_arg(T& val) -> basic_format_arg<Context> { 1620 return make_arg<Context>(val); 1621 } 1622 } // namespace detail 1623 FMT_BEGIN_EXPORT 1624 1625 // A formatting argument. Context is a template parameter for the compiled API 1626 // where output can be unbuffered. 1627 template <typename Context> class basic_format_arg { 1628 private: 1629 detail::value<Context> value_; 1630 detail::type type_; 1631 1632 template <typename ContextType, typename T> 1633 friend FMT_CONSTEXPR auto detail::make_arg(T& value) 1634 -> basic_format_arg<ContextType>; 1635 1636 template <typename Visitor, typename Ctx> 1637 friend FMT_CONSTEXPR auto visit_format_arg(Visitor&& vis, 1638 const basic_format_arg<Ctx>& arg) 1639 -> decltype(vis(0)); 1640 1641 friend class basic_format_args<Context>; 1642 friend class dynamic_format_arg_store<Context>; 1643 1644 using char_type = typename Context::char_type; 1645 1646 template <typename T, typename Char, size_t NUM_ARGS, size_t NUM_NAMED_ARGS> 1647 friend struct detail::arg_data; 1648 1649 basic_format_arg(const detail::named_arg_info<char_type>* args, size_t size) 1650 : value_(args, size) {} 1651 1652 public: 1653 class handle { 1654 public: 1655 explicit handle(detail::custom_value<Context> custom) : custom_(custom) {} 1656 1657 void format(typename Context::parse_context_type& parse_ctx, 1658 Context& ctx) const { 1659 custom_.format(custom_.value, parse_ctx, ctx); 1660 } 1661 1662 private: 1663 detail::custom_value<Context> custom_; 1664 }; 1665 1666 constexpr basic_format_arg() : type_(detail::type::none_type) {} 1667 1668 constexpr explicit operator bool() const noexcept { 1669 return type_ != detail::type::none_type; 1670 } 1671 1672 auto type() const -> detail::type { return type_; } 1673 1674 auto is_integral() const -> bool { return detail::is_integral_type(type_); } 1675 auto is_arithmetic() const -> bool { 1676 return detail::is_arithmetic_type(type_); 1677 } 1678 1679 FMT_INLINE auto format_custom(const char_type* parse_begin, 1680 typename Context::parse_context_type& parse_ctx, 1681 Context& ctx) -> bool { 1682 if (type_ != detail::type::custom_type) return false; 1683 parse_ctx.advance_to(parse_begin); 1684 value_.custom.format(value_.custom.value, parse_ctx, ctx); 1685 return true; 1686 } 1687 }; 1688 1689 /** 1690 \rst 1691 Visits an argument dispatching to the appropriate visit method based on 1692 the argument type. For example, if the argument type is ``double`` then 1693 ``vis(value)`` will be called with the value of type ``double``. 1694 \endrst 1695 */ 1696 // DEPRECATED! 1697 template <typename Visitor, typename Context> 1698 FMT_CONSTEXPR FMT_INLINE auto visit_format_arg( 1699 Visitor&& vis, const basic_format_arg<Context>& arg) -> decltype(vis(0)) { 1700 switch (arg.type_) { 1701 case detail::type::none_type: 1702 break; 1703 case detail::type::int_type: 1704 return vis(arg.value_.int_value); 1705 case detail::type::uint_type: 1706 return vis(arg.value_.uint_value); 1707 case detail::type::long_long_type: 1708 return vis(arg.value_.long_long_value); 1709 case detail::type::ulong_long_type: 1710 return vis(arg.value_.ulong_long_value); 1711 case detail::type::int128_type: 1712 return vis(detail::convert_for_visit(arg.value_.int128_value)); 1713 case detail::type::uint128_type: 1714 return vis(detail::convert_for_visit(arg.value_.uint128_value)); 1715 case detail::type::bool_type: 1716 return vis(arg.value_.bool_value); 1717 case detail::type::char_type: 1718 return vis(arg.value_.char_value); 1719 case detail::type::float_type: 1720 return vis(arg.value_.float_value); 1721 case detail::type::double_type: 1722 return vis(arg.value_.double_value); 1723 case detail::type::long_double_type: 1724 return vis(arg.value_.long_double_value); 1725 case detail::type::cstring_type: 1726 return vis(arg.value_.string.data); 1727 case detail::type::string_type: 1728 using sv = basic_string_view<typename Context::char_type>; 1729 return vis(sv(arg.value_.string.data, arg.value_.string.size)); 1730 case detail::type::pointer_type: 1731 return vis(arg.value_.pointer); 1732 case detail::type::custom_type: 1733 return vis(typename basic_format_arg<Context>::handle(arg.value_.custom)); 1734 } 1735 return vis(monostate()); 1736 } 1737 1738 // Formatting context. 1739 template <typename OutputIt, typename Char> class basic_format_context { 1740 private: 1741 OutputIt out_; 1742 basic_format_args<basic_format_context> args_; 1743 detail::locale_ref loc_; 1744 1745 public: 1746 using iterator = OutputIt; 1747 using format_arg = basic_format_arg<basic_format_context>; 1748 using format_args = basic_format_args<basic_format_context>; 1749 using parse_context_type = basic_format_parse_context<Char>; 1750 template <typename T> using formatter_type = formatter<T, Char>; 1751 1752 /** The character type for the output. */ 1753 using char_type = Char; 1754 1755 basic_format_context(basic_format_context&&) = default; 1756 basic_format_context(const basic_format_context&) = delete; 1757 void operator=(const basic_format_context&) = delete; 1758 /** 1759 Constructs a ``basic_format_context`` object. References to the arguments 1760 are stored in the object so make sure they have appropriate lifetimes. 1761 */ 1762 constexpr basic_format_context(OutputIt out, format_args ctx_args, 1763 detail::locale_ref loc = {}) 1764 : out_(out), args_(ctx_args), loc_(loc) {} 1765 1766 constexpr auto arg(int id) const -> format_arg { return args_.get(id); } 1767 FMT_CONSTEXPR auto arg(basic_string_view<Char> name) -> format_arg { 1768 return args_.get(name); 1769 } 1770 FMT_CONSTEXPR auto arg_id(basic_string_view<Char> name) -> int { 1771 return args_.get_id(name); 1772 } 1773 auto args() const -> const format_args& { return args_; } 1774 1775 // DEPRECATED! 1776 FMT_CONSTEXPR auto error_handler() -> detail::error_handler { return {}; } 1777 void on_error(const char* message) { error_handler().on_error(message); } 1778 1779 // Returns an iterator to the beginning of the output range. 1780 FMT_CONSTEXPR auto out() -> iterator { return out_; } 1781 1782 // Advances the begin iterator to ``it``. 1783 void advance_to(iterator it) { 1784 if (!detail::is_back_insert_iterator<iterator>()) out_ = it; 1785 } 1786 1787 FMT_CONSTEXPR auto locale() -> detail::locale_ref { return loc_; } 1788 }; 1789 1790 template <typename Char> 1791 using buffer_context = 1792 basic_format_context<detail::buffer_appender<Char>, Char>; 1793 using format_context = buffer_context<char>; 1794 1795 template <typename T, typename Char = char> 1796 using is_formattable = bool_constant<!std::is_base_of< 1797 detail::unformattable, decltype(detail::arg_mapper<buffer_context<Char>>() 1798 .map(std::declval<T&>()))>::value>; 1799 1800 /** 1801 \rst 1802 An array of references to arguments. It can be implicitly converted into 1803 `~fmt::basic_format_args` for passing into type-erased formatting functions 1804 such as `~fmt::vformat`. 1805 \endrst 1806 */ 1807 template <typename Context, typename... Args> 1808 class format_arg_store 1809 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 1810 // Workaround a GCC template argument substitution bug. 1811 : public basic_format_args<Context> 1812 #endif 1813 { 1814 private: 1815 static const size_t num_args = sizeof...(Args); 1816 static constexpr size_t num_named_args = detail::count_named_args<Args...>(); 1817 static const bool is_packed = num_args <= detail::max_packed_args; 1818 1819 using value_type = conditional_t<is_packed, detail::value<Context>, 1820 basic_format_arg<Context>>; 1821 1822 detail::arg_data<value_type, typename Context::char_type, num_args, 1823 num_named_args> 1824 data_; 1825 1826 friend class basic_format_args<Context>; 1827 1828 static constexpr unsigned long long desc = 1829 (is_packed ? detail::encode_types<Context, Args...>() 1830 : detail::is_unpacked_bit | num_args) | 1831 (num_named_args != 0 1832 ? static_cast<unsigned long long>(detail::has_named_args_bit) 1833 : 0); 1834 1835 public: 1836 template <typename... T> 1837 FMT_CONSTEXPR FMT_INLINE format_arg_store(T&... args) 1838 : 1839 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 1840 basic_format_args<Context>(*this), 1841 #endif 1842 data_{detail::make_arg<is_packed, Context>(args)...} { 1843 if (detail::const_check(num_named_args != 0)) 1844 detail::init_named_args(data_.named_args(), 0, 0, args...); 1845 } 1846 }; 1847 1848 /** 1849 \rst 1850 Constructs a `~fmt::format_arg_store` object that contains references to 1851 arguments and can be implicitly converted to `~fmt::format_args`. `Context` 1852 can be omitted in which case it defaults to `~fmt::format_context`. 1853 See `~fmt::arg` for lifetime considerations. 1854 \endrst 1855 */ 1856 // Arguments are taken by lvalue references to avoid some lifetime issues. 1857 template <typename Context = format_context, typename... T> 1858 constexpr auto make_format_args(T&... args) 1859 -> format_arg_store<Context, remove_cvref_t<T>...> { 1860 return {args...}; 1861 } 1862 1863 /** 1864 \rst 1865 Returns a named argument to be used in a formatting function. 1866 It should only be used in a call to a formatting function or 1867 `dynamic_format_arg_store::push_back`. 1868 1869 **Example**:: 1870 1871 fmt::print("Elapsed time: {s:.2f} seconds", fmt::arg("s", 1.23)); 1872 \endrst 1873 */ 1874 template <typename Char, typename T> 1875 inline auto arg(const Char* name, const T& arg) -> detail::named_arg<Char, T> { 1876 static_assert(!detail::is_named_arg<T>(), "nested named arguments"); 1877 return {name, arg}; 1878 } 1879 FMT_END_EXPORT 1880 1881 /** 1882 \rst 1883 A view of a collection of formatting arguments. To avoid lifetime issues it 1884 should only be used as a parameter type in type-erased functions such as 1885 ``vformat``:: 1886 1887 void vlog(string_view format_str, format_args args); // OK 1888 format_args args = make_format_args(); // Error: dangling reference 1889 \endrst 1890 */ 1891 template <typename Context> class basic_format_args { 1892 public: 1893 using size_type = int; 1894 using format_arg = basic_format_arg<Context>; 1895 1896 private: 1897 // A descriptor that contains information about formatting arguments. 1898 // If the number of arguments is less or equal to max_packed_args then 1899 // argument types are passed in the descriptor. This reduces binary code size 1900 // per formatting function call. 1901 unsigned long long desc_; 1902 union { 1903 // If is_packed() returns true then argument values are stored in values_; 1904 // otherwise they are stored in args_. This is done to improve cache 1905 // locality and reduce compiled code size since storing larger objects 1906 // may require more code (at least on x86-64) even if the same amount of 1907 // data is actually copied to stack. It saves ~10% on the bloat test. 1908 const detail::value<Context>* values_; 1909 const format_arg* args_; 1910 }; 1911 1912 constexpr auto is_packed() const -> bool { 1913 return (desc_ & detail::is_unpacked_bit) == 0; 1914 } 1915 auto has_named_args() const -> bool { 1916 return (desc_ & detail::has_named_args_bit) != 0; 1917 } 1918 1919 FMT_CONSTEXPR auto type(int index) const -> detail::type { 1920 int shift = index * detail::packed_arg_bits; 1921 unsigned int mask = (1 << detail::packed_arg_bits) - 1; 1922 return static_cast<detail::type>((desc_ >> shift) & mask); 1923 } 1924 1925 constexpr FMT_INLINE basic_format_args(unsigned long long desc, 1926 const detail::value<Context>* values) 1927 : desc_(desc), values_(values) {} 1928 constexpr basic_format_args(unsigned long long desc, const format_arg* args) 1929 : desc_(desc), args_(args) {} 1930 1931 public: 1932 constexpr basic_format_args() : desc_(0), args_(nullptr) {} 1933 1934 /** 1935 \rst 1936 Constructs a `basic_format_args` object from `~fmt::format_arg_store`. 1937 \endrst 1938 */ 1939 template <typename... Args> 1940 constexpr FMT_INLINE basic_format_args( 1941 const format_arg_store<Context, Args...>& store) 1942 : basic_format_args(format_arg_store<Context, Args...>::desc, 1943 store.data_.args()) {} 1944 1945 /** 1946 \rst 1947 Constructs a `basic_format_args` object from 1948 `~fmt::dynamic_format_arg_store`. 1949 \endrst 1950 */ 1951 constexpr FMT_INLINE basic_format_args( 1952 const dynamic_format_arg_store<Context>& store) 1953 : basic_format_args(store.get_types(), store.data()) {} 1954 1955 /** 1956 \rst 1957 Constructs a `basic_format_args` object from a dynamic set of arguments. 1958 \endrst 1959 */ 1960 constexpr basic_format_args(const format_arg* args, int count) 1961 : basic_format_args(detail::is_unpacked_bit | detail::to_unsigned(count), 1962 args) {} 1963 1964 /** Returns the argument with the specified id. */ 1965 FMT_CONSTEXPR auto get(int id) const -> format_arg { 1966 format_arg arg; 1967 if (!is_packed()) { 1968 if (id < max_size()) arg = args_[id]; 1969 return arg; 1970 } 1971 if (id >= detail::max_packed_args) return arg; 1972 arg.type_ = type(id); 1973 if (arg.type_ == detail::type::none_type) return arg; 1974 arg.value_ = values_[id]; 1975 return arg; 1976 } 1977 1978 template <typename Char> 1979 auto get(basic_string_view<Char> name) const -> format_arg { 1980 int id = get_id(name); 1981 return id >= 0 ? get(id) : format_arg(); 1982 } 1983 1984 template <typename Char> 1985 auto get_id(basic_string_view<Char> name) const -> int { 1986 if (!has_named_args()) return -1; 1987 const auto& named_args = 1988 (is_packed() ? values_[-1] : args_[-1].value_).named_args; 1989 for (size_t i = 0; i < named_args.size; ++i) { 1990 if (named_args.data[i].name == name) return named_args.data[i].id; 1991 } 1992 return -1; 1993 } 1994 1995 auto max_size() const -> int { 1996 unsigned long long max_packed = detail::max_packed_args; 1997 return static_cast<int>(is_packed() ? max_packed 1998 : desc_ & ~detail::is_unpacked_bit); 1999 } 2000 }; 2001 2002 /** An alias to ``basic_format_args<format_context>``. */ 2003 // A separate type would result in shorter symbols but break ABI compatibility 2004 // between clang and gcc on ARM (#1919). 2005 FMT_EXPORT using format_args = basic_format_args<format_context>; 2006 2007 // We cannot use enum classes as bit fields because of a gcc bug, so we put them 2008 // in namespaces instead (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414). 2009 // Additionally, if an underlying type is specified, older gcc incorrectly warns 2010 // that the type is too small. Both bugs are fixed in gcc 9.3. 2011 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 903 2012 # define FMT_ENUM_UNDERLYING_TYPE(type) 2013 #else 2014 # define FMT_ENUM_UNDERLYING_TYPE(type) : type 2015 #endif 2016 namespace align { 2017 enum type FMT_ENUM_UNDERLYING_TYPE(unsigned char){none, left, right, center, 2018 numeric}; 2019 } 2020 using align_t = align::type; 2021 namespace sign { 2022 enum type FMT_ENUM_UNDERLYING_TYPE(unsigned char){none, minus, plus, space}; 2023 } 2024 using sign_t = sign::type; 2025 2026 namespace detail { 2027 2028 // Workaround an array initialization issue in gcc 4.8. 2029 template <typename Char> struct fill_t { 2030 private: 2031 enum { max_size = 4 }; 2032 Char data_[max_size] = {Char(' '), Char(0), Char(0), Char(0)}; 2033 unsigned char size_ = 1; 2034 2035 public: 2036 FMT_CONSTEXPR void operator=(basic_string_view<Char> s) { 2037 auto size = s.size(); 2038 FMT_ASSERT(size <= max_size, "invalid fill"); 2039 for (size_t i = 0; i < size; ++i) data_[i] = s[i]; 2040 size_ = static_cast<unsigned char>(size); 2041 } 2042 2043 constexpr auto size() const -> size_t { return size_; } 2044 constexpr auto data() const -> const Char* { return data_; } 2045 2046 FMT_CONSTEXPR auto operator[](size_t index) -> Char& { return data_[index]; } 2047 FMT_CONSTEXPR auto operator[](size_t index) const -> const Char& { 2048 return data_[index]; 2049 } 2050 }; 2051 } // namespace detail 2052 2053 enum class presentation_type : unsigned char { 2054 none, 2055 dec, // 'd' 2056 oct, // 'o' 2057 hex_lower, // 'x' 2058 hex_upper, // 'X' 2059 bin_lower, // 'b' 2060 bin_upper, // 'B' 2061 hexfloat_lower, // 'a' 2062 hexfloat_upper, // 'A' 2063 exp_lower, // 'e' 2064 exp_upper, // 'E' 2065 fixed_lower, // 'f' 2066 fixed_upper, // 'F' 2067 general_lower, // 'g' 2068 general_upper, // 'G' 2069 chr, // 'c' 2070 string, // 's' 2071 pointer, // 'p' 2072 debug // '?' 2073 }; 2074 2075 // Format specifiers for built-in and string types. 2076 template <typename Char = char> struct format_specs { 2077 int width; 2078 int precision; 2079 presentation_type type; 2080 align_t align : 4; 2081 sign_t sign : 3; 2082 bool alt : 1; // Alternate form ('#'). 2083 bool localized : 1; 2084 detail::fill_t<Char> fill; 2085 2086 constexpr format_specs() 2087 : width(0), 2088 precision(-1), 2089 type(presentation_type::none), 2090 align(align::none), 2091 sign(sign::none), 2092 alt(false), 2093 localized(false) {} 2094 }; 2095 2096 namespace detail { 2097 2098 enum class arg_id_kind { none, index, name }; 2099 2100 // An argument reference. 2101 template <typename Char> struct arg_ref { 2102 FMT_CONSTEXPR arg_ref() : kind(arg_id_kind::none), val() {} 2103 2104 FMT_CONSTEXPR explicit arg_ref(int index) 2105 : kind(arg_id_kind::index), val(index) {} 2106 FMT_CONSTEXPR explicit arg_ref(basic_string_view<Char> name) 2107 : kind(arg_id_kind::name), val(name) {} 2108 2109 FMT_CONSTEXPR auto operator=(int idx) -> arg_ref& { 2110 kind = arg_id_kind::index; 2111 val.index = idx; 2112 return *this; 2113 } 2114 2115 arg_id_kind kind; 2116 union value { 2117 FMT_CONSTEXPR value(int idx = 0) : index(idx) {} 2118 FMT_CONSTEXPR value(basic_string_view<Char> n) : name(n) {} 2119 2120 int index; 2121 basic_string_view<Char> name; 2122 } val; 2123 }; 2124 2125 // Format specifiers with width and precision resolved at formatting rather 2126 // than parsing time to allow reusing the same parsed specifiers with 2127 // different sets of arguments (precompilation of format strings). 2128 template <typename Char = char> 2129 struct dynamic_format_specs : format_specs<Char> { 2130 arg_ref<Char> width_ref; 2131 arg_ref<Char> precision_ref; 2132 }; 2133 2134 // Converts a character to ASCII. Returns '\0' on conversion failure. 2135 template <typename Char, FMT_ENABLE_IF(std::is_integral<Char>::value)> 2136 constexpr auto to_ascii(Char c) -> char { 2137 return c <= 0xff ? static_cast<char>(c) : '\0'; 2138 } 2139 template <typename Char, FMT_ENABLE_IF(std::is_enum<Char>::value)> 2140 constexpr auto to_ascii(Char c) -> char { 2141 return c <= 0xff ? static_cast<char>(c) : '\0'; 2142 } 2143 2144 // Returns the number of code units in a code point or 1 on error. 2145 template <typename Char> 2146 FMT_CONSTEXPR auto code_point_length(const Char* begin) -> int { 2147 if (const_check(sizeof(Char) != 1)) return 1; 2148 auto c = static_cast<unsigned char>(*begin); 2149 return static_cast<int>((0x3a55000000000000ull >> (2 * (c >> 3))) & 0x3) + 1; 2150 } 2151 2152 // Return the result via the out param to workaround gcc bug 77539. 2153 template <bool IS_CONSTEXPR, typename T, typename Ptr = const T*> 2154 FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr& out) -> bool { 2155 for (out = first; out != last; ++out) { 2156 if (*out == value) return true; 2157 } 2158 return false; 2159 } 2160 2161 template <> 2162 inline auto find<false, char>(const char* first, const char* last, char value, 2163 const char*& out) -> bool { 2164 out = static_cast<const char*>( 2165 std::memchr(first, value, to_unsigned(last - first))); 2166 return out != nullptr; 2167 } 2168 2169 // Parses the range [begin, end) as an unsigned integer. This function assumes 2170 // that the range is non-empty and the first character is a digit. 2171 template <typename Char> 2172 FMT_CONSTEXPR auto parse_nonnegative_int(const Char*& begin, const Char* end, 2173 int error_value) noexcept -> int { 2174 FMT_ASSERT(begin != end && '0' <= *begin && *begin <= '9', ""); 2175 unsigned value = 0, prev = 0; 2176 auto p = begin; 2177 do { 2178 prev = value; 2179 value = value * 10 + unsigned(*p - '0'); 2180 ++p; 2181 } while (p != end && '0' <= *p && *p <= '9'); 2182 auto num_digits = p - begin; 2183 begin = p; 2184 if (num_digits <= std::numeric_limits<int>::digits10) 2185 return static_cast<int>(value); 2186 // Check for overflow. 2187 const unsigned max = to_unsigned((std::numeric_limits<int>::max)()); 2188 return num_digits == std::numeric_limits<int>::digits10 + 1 && 2189 prev * 10ull + unsigned(p[-1] - '0') <= max 2190 ? static_cast<int>(value) 2191 : error_value; 2192 } 2193 2194 FMT_CONSTEXPR inline auto parse_align(char c) -> align_t { 2195 switch (c) { 2196 case '<': 2197 return align::left; 2198 case '>': 2199 return align::right; 2200 case '^': 2201 return align::center; 2202 } 2203 return align::none; 2204 } 2205 2206 template <typename Char> constexpr auto is_name_start(Char c) -> bool { 2207 return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '_'; 2208 } 2209 2210 template <typename Char, typename Handler> 2211 FMT_CONSTEXPR auto do_parse_arg_id(const Char* begin, const Char* end, 2212 Handler&& handler) -> const Char* { 2213 Char c = *begin; 2214 if (c >= '0' && c <= '9') { 2215 int index = 0; 2216 constexpr int max = (std::numeric_limits<int>::max)(); 2217 if (c != '0') 2218 index = parse_nonnegative_int(begin, end, max); 2219 else 2220 ++begin; 2221 if (begin == end || (*begin != '}' && *begin != ':')) 2222 throw_format_error("invalid format string"); 2223 else 2224 handler.on_index(index); 2225 return begin; 2226 } 2227 if (!is_name_start(c)) { 2228 throw_format_error("invalid format string"); 2229 return begin; 2230 } 2231 auto it = begin; 2232 do { 2233 ++it; 2234 } while (it != end && (is_name_start(*it) || ('0' <= *it && *it <= '9'))); 2235 handler.on_name({begin, to_unsigned(it - begin)}); 2236 return it; 2237 } 2238 2239 template <typename Char, typename Handler> 2240 FMT_CONSTEXPR FMT_INLINE auto parse_arg_id(const Char* begin, const Char* end, 2241 Handler&& handler) -> const Char* { 2242 FMT_ASSERT(begin != end, ""); 2243 Char c = *begin; 2244 if (c != '}' && c != ':') return do_parse_arg_id(begin, end, handler); 2245 handler.on_auto(); 2246 return begin; 2247 } 2248 2249 template <typename Char> struct dynamic_spec_id_handler { 2250 basic_format_parse_context<Char>& ctx; 2251 arg_ref<Char>& ref; 2252 2253 FMT_CONSTEXPR void on_auto() { 2254 int id = ctx.next_arg_id(); 2255 ref = arg_ref<Char>(id); 2256 ctx.check_dynamic_spec(id); 2257 } 2258 FMT_CONSTEXPR void on_index(int id) { 2259 ref = arg_ref<Char>(id); 2260 ctx.check_arg_id(id); 2261 ctx.check_dynamic_spec(id); 2262 } 2263 FMT_CONSTEXPR void on_name(basic_string_view<Char> id) { 2264 ref = arg_ref<Char>(id); 2265 ctx.check_arg_id(id); 2266 } 2267 }; 2268 2269 // Parses [integer | "{" [arg_id] "}"]. 2270 template <typename Char> 2271 FMT_CONSTEXPR auto parse_dynamic_spec(const Char* begin, const Char* end, 2272 int& value, arg_ref<Char>& ref, 2273 basic_format_parse_context<Char>& ctx) 2274 -> const Char* { 2275 FMT_ASSERT(begin != end, ""); 2276 if ('0' <= *begin && *begin <= '9') { 2277 int val = parse_nonnegative_int(begin, end, -1); 2278 if (val != -1) 2279 value = val; 2280 else 2281 throw_format_error("number is too big"); 2282 } else if (*begin == '{') { 2283 ++begin; 2284 auto handler = dynamic_spec_id_handler<Char>{ctx, ref}; 2285 if (begin != end) begin = parse_arg_id(begin, end, handler); 2286 if (begin != end && *begin == '}') return ++begin; 2287 throw_format_error("invalid format string"); 2288 } 2289 return begin; 2290 } 2291 2292 template <typename Char> 2293 FMT_CONSTEXPR auto parse_precision(const Char* begin, const Char* end, 2294 int& value, arg_ref<Char>& ref, 2295 basic_format_parse_context<Char>& ctx) 2296 -> const Char* { 2297 ++begin; 2298 if (begin == end || *begin == '}') { 2299 throw_format_error("invalid precision"); 2300 return begin; 2301 } 2302 return parse_dynamic_spec(begin, end, value, ref, ctx); 2303 } 2304 2305 enum class state { start, align, sign, hash, zero, width, precision, locale }; 2306 2307 // Parses standard format specifiers. 2308 template <typename Char> 2309 FMT_CONSTEXPR FMT_INLINE auto parse_format_specs( 2310 const Char* begin, const Char* end, dynamic_format_specs<Char>& specs, 2311 basic_format_parse_context<Char>& ctx, type arg_type) -> const Char* { 2312 auto c = '\0'; 2313 if (end - begin > 1) { 2314 auto next = to_ascii(begin[1]); 2315 c = parse_align(next) == align::none ? to_ascii(*begin) : '\0'; 2316 } else { 2317 if (begin == end) return begin; 2318 c = to_ascii(*begin); 2319 } 2320 2321 struct { 2322 state current_state = state::start; 2323 FMT_CONSTEXPR void operator()(state s, bool valid = true) { 2324 if (current_state >= s || !valid) 2325 throw_format_error("invalid format specifier"); 2326 current_state = s; 2327 } 2328 } enter_state; 2329 2330 using pres = presentation_type; 2331 constexpr auto integral_set = sint_set | uint_set | bool_set | char_set; 2332 struct { 2333 const Char*& begin; 2334 dynamic_format_specs<Char>& specs; 2335 type arg_type; 2336 2337 FMT_CONSTEXPR auto operator()(pres pres_type, int set) -> const Char* { 2338 if (!in(arg_type, set)) { 2339 if (arg_type == type::none_type) return begin; 2340 throw_format_error("invalid format specifier"); 2341 } 2342 specs.type = pres_type; 2343 return begin + 1; 2344 } 2345 } parse_presentation_type{begin, specs, arg_type}; 2346 2347 for (;;) { 2348 switch (c) { 2349 case '<': 2350 case '>': 2351 case '^': 2352 enter_state(state::align); 2353 specs.align = parse_align(c); 2354 ++begin; 2355 break; 2356 case '+': 2357 case '-': 2358 case ' ': 2359 if (arg_type == type::none_type) return begin; 2360 enter_state(state::sign, in(arg_type, sint_set | float_set)); 2361 switch (c) { 2362 case '+': 2363 specs.sign = sign::plus; 2364 break; 2365 case '-': 2366 specs.sign = sign::minus; 2367 break; 2368 case ' ': 2369 specs.sign = sign::space; 2370 break; 2371 } 2372 ++begin; 2373 break; 2374 case '#': 2375 if (arg_type == type::none_type) return begin; 2376 enter_state(state::hash, is_arithmetic_type(arg_type)); 2377 specs.alt = true; 2378 ++begin; 2379 break; 2380 case '0': 2381 enter_state(state::zero); 2382 if (!is_arithmetic_type(arg_type)) { 2383 if (arg_type == type::none_type) return begin; 2384 throw_format_error("format specifier requires numeric argument"); 2385 } 2386 if (specs.align == align::none) { 2387 // Ignore 0 if align is specified for compatibility with std::format. 2388 specs.align = align::numeric; 2389 specs.fill[0] = Char('0'); 2390 } 2391 ++begin; 2392 break; 2393 case '1': 2394 case '2': 2395 case '3': 2396 case '4': 2397 case '5': 2398 case '6': 2399 case '7': 2400 case '8': 2401 case '9': 2402 case '{': 2403 enter_state(state::width); 2404 begin = parse_dynamic_spec(begin, end, specs.width, specs.width_ref, ctx); 2405 break; 2406 case '.': 2407 if (arg_type == type::none_type) return begin; 2408 enter_state(state::precision, 2409 in(arg_type, float_set | string_set | cstring_set)); 2410 begin = parse_precision(begin, end, specs.precision, specs.precision_ref, 2411 ctx); 2412 break; 2413 case 'L': 2414 if (arg_type == type::none_type) return begin; 2415 enter_state(state::locale, is_arithmetic_type(arg_type)); 2416 specs.localized = true; 2417 ++begin; 2418 break; 2419 case 'd': 2420 return parse_presentation_type(pres::dec, integral_set); 2421 case 'o': 2422 return parse_presentation_type(pres::oct, integral_set); 2423 case 'x': 2424 return parse_presentation_type(pres::hex_lower, integral_set); 2425 case 'X': 2426 return parse_presentation_type(pres::hex_upper, integral_set); 2427 case 'b': 2428 return parse_presentation_type(pres::bin_lower, integral_set); 2429 case 'B': 2430 return parse_presentation_type(pres::bin_upper, integral_set); 2431 case 'a': 2432 return parse_presentation_type(pres::hexfloat_lower, float_set); 2433 case 'A': 2434 return parse_presentation_type(pres::hexfloat_upper, float_set); 2435 case 'e': 2436 return parse_presentation_type(pres::exp_lower, float_set); 2437 case 'E': 2438 return parse_presentation_type(pres::exp_upper, float_set); 2439 case 'f': 2440 return parse_presentation_type(pres::fixed_lower, float_set); 2441 case 'F': 2442 return parse_presentation_type(pres::fixed_upper, float_set); 2443 case 'g': 2444 return parse_presentation_type(pres::general_lower, float_set); 2445 case 'G': 2446 return parse_presentation_type(pres::general_upper, float_set); 2447 case 'c': 2448 if (arg_type == type::bool_type) 2449 throw_format_error("invalid format specifier"); 2450 return parse_presentation_type(pres::chr, integral_set); 2451 case 's': 2452 return parse_presentation_type(pres::string, 2453 bool_set | string_set | cstring_set); 2454 case 'p': 2455 return parse_presentation_type(pres::pointer, pointer_set | cstring_set); 2456 case '?': 2457 return parse_presentation_type(pres::debug, 2458 char_set | string_set | cstring_set); 2459 case '}': 2460 return begin; 2461 default: { 2462 if (*begin == '}') return begin; 2463 // Parse fill and alignment. 2464 auto fill_end = begin + code_point_length(begin); 2465 if (end - fill_end <= 0) { 2466 throw_format_error("invalid format specifier"); 2467 return begin; 2468 } 2469 if (*begin == '{') { 2470 throw_format_error("invalid fill character '{'"); 2471 return begin; 2472 } 2473 auto align = parse_align(to_ascii(*fill_end)); 2474 enter_state(state::align, align != align::none); 2475 specs.fill = {begin, to_unsigned(fill_end - begin)}; 2476 specs.align = align; 2477 begin = fill_end + 1; 2478 } 2479 } 2480 if (begin == end) return begin; 2481 c = to_ascii(*begin); 2482 } 2483 } 2484 2485 template <typename Char, typename Handler> 2486 FMT_CONSTEXPR auto parse_replacement_field(const Char* begin, const Char* end, 2487 Handler&& handler) -> const Char* { 2488 struct id_adapter { 2489 Handler& handler; 2490 int arg_id; 2491 2492 FMT_CONSTEXPR void on_auto() { arg_id = handler.on_arg_id(); } 2493 FMT_CONSTEXPR void on_index(int id) { arg_id = handler.on_arg_id(id); } 2494 FMT_CONSTEXPR void on_name(basic_string_view<Char> id) { 2495 arg_id = handler.on_arg_id(id); 2496 } 2497 }; 2498 2499 ++begin; 2500 if (begin == end) return handler.on_error("invalid format string"), end; 2501 if (*begin == '}') { 2502 handler.on_replacement_field(handler.on_arg_id(), begin); 2503 } else if (*begin == '{') { 2504 handler.on_text(begin, begin + 1); 2505 } else { 2506 auto adapter = id_adapter{handler, 0}; 2507 begin = parse_arg_id(begin, end, adapter); 2508 Char c = begin != end ? *begin : Char(); 2509 if (c == '}') { 2510 handler.on_replacement_field(adapter.arg_id, begin); 2511 } else if (c == ':') { 2512 begin = handler.on_format_specs(adapter.arg_id, begin + 1, end); 2513 if (begin == end || *begin != '}') 2514 return handler.on_error("unknown format specifier"), end; 2515 } else { 2516 return handler.on_error("missing '}' in format string"), end; 2517 } 2518 } 2519 return begin + 1; 2520 } 2521 2522 template <bool IS_CONSTEXPR, typename Char, typename Handler> 2523 FMT_CONSTEXPR FMT_INLINE void parse_format_string( 2524 basic_string_view<Char> format_str, Handler&& handler) { 2525 auto begin = format_str.data(); 2526 auto end = begin + format_str.size(); 2527 if (end - begin < 32) { 2528 // Use a simple loop instead of memchr for small strings. 2529 const Char* p = begin; 2530 while (p != end) { 2531 auto c = *p++; 2532 if (c == '{') { 2533 handler.on_text(begin, p - 1); 2534 begin = p = parse_replacement_field(p - 1, end, handler); 2535 } else if (c == '}') { 2536 if (p == end || *p != '}') 2537 return handler.on_error("unmatched '}' in format string"); 2538 handler.on_text(begin, p); 2539 begin = ++p; 2540 } 2541 } 2542 handler.on_text(begin, end); 2543 return; 2544 } 2545 struct writer { 2546 FMT_CONSTEXPR void operator()(const Char* from, const Char* to) { 2547 if (from == to) return; 2548 for (;;) { 2549 const Char* p = nullptr; 2550 if (!find<IS_CONSTEXPR>(from, to, Char('}'), p)) 2551 return handler_.on_text(from, to); 2552 ++p; 2553 if (p == to || *p != '}') 2554 return handler_.on_error("unmatched '}' in format string"); 2555 handler_.on_text(from, p); 2556 from = p + 1; 2557 } 2558 } 2559 Handler& handler_; 2560 } write = {handler}; 2561 while (begin != end) { 2562 // Doing two passes with memchr (one for '{' and another for '}') is up to 2563 // 2.5x faster than the naive one-pass implementation on big format strings. 2564 const Char* p = begin; 2565 if (*begin != '{' && !find<IS_CONSTEXPR>(begin + 1, end, Char('{'), p)) 2566 return write(begin, end); 2567 write(begin, p); 2568 begin = parse_replacement_field(p, end, handler); 2569 } 2570 } 2571 2572 template <typename T, bool = is_named_arg<T>::value> struct strip_named_arg { 2573 using type = T; 2574 }; 2575 template <typename T> struct strip_named_arg<T, true> { 2576 using type = remove_cvref_t<decltype(T::value)>; 2577 }; 2578 2579 template <typename T, typename ParseContext> 2580 FMT_CONSTEXPR auto parse_format_specs(ParseContext& ctx) 2581 -> decltype(ctx.begin()) { 2582 using char_type = typename ParseContext::char_type; 2583 using context = buffer_context<char_type>; 2584 using mapped_type = conditional_t< 2585 mapped_type_constant<T, context>::value != type::custom_type, 2586 decltype(arg_mapper<context>().map(std::declval<const T&>())), 2587 typename strip_named_arg<T>::type>; 2588 #if defined(__cpp_if_constexpr) 2589 if constexpr (std::is_default_constructible< 2590 formatter<mapped_type, char_type>>::value) { 2591 return formatter<mapped_type, char_type>().parse(ctx); 2592 } else { 2593 type_is_unformattable_for<T, char_type> _; 2594 return ctx.begin(); 2595 } 2596 #else 2597 return formatter<mapped_type, char_type>().parse(ctx); 2598 #endif 2599 } 2600 2601 // Checks char specs and returns true iff the presentation type is char-like. 2602 template <typename Char> 2603 FMT_CONSTEXPR auto check_char_specs(const format_specs<Char>& specs) -> bool { 2604 if (specs.type != presentation_type::none && 2605 specs.type != presentation_type::chr && 2606 specs.type != presentation_type::debug) { 2607 return false; 2608 } 2609 if (specs.align == align::numeric || specs.sign != sign::none || specs.alt) 2610 throw_format_error("invalid format specifier for char"); 2611 return true; 2612 } 2613 2614 #if FMT_USE_NONTYPE_TEMPLATE_ARGS 2615 template <int N, typename T, typename... Args, typename Char> 2616 constexpr auto get_arg_index_by_name(basic_string_view<Char> name) -> int { 2617 if constexpr (is_statically_named_arg<T>()) { 2618 if (name == T::name) return N; 2619 } 2620 if constexpr (sizeof...(Args) > 0) 2621 return get_arg_index_by_name<N + 1, Args...>(name); 2622 (void)name; // Workaround an MSVC bug about "unused" parameter. 2623 return -1; 2624 } 2625 #endif 2626 2627 template <typename... Args, typename Char> 2628 FMT_CONSTEXPR auto get_arg_index_by_name(basic_string_view<Char> name) -> int { 2629 #if FMT_USE_NONTYPE_TEMPLATE_ARGS 2630 if constexpr (sizeof...(Args) > 0) 2631 return get_arg_index_by_name<0, Args...>(name); 2632 #endif 2633 (void)name; 2634 return -1; 2635 } 2636 2637 template <typename Char, typename... Args> class format_string_checker { 2638 private: 2639 using parse_context_type = compile_parse_context<Char>; 2640 static constexpr int num_args = sizeof...(Args); 2641 2642 // Format specifier parsing function. 2643 // In the future basic_format_parse_context will replace compile_parse_context 2644 // here and will use is_constant_evaluated and downcasting to access the data 2645 // needed for compile-time checks: https://godbolt.org/z/GvWzcTjh1. 2646 using parse_func = const Char* (*)(parse_context_type&); 2647 2648 type types_[num_args > 0 ? static_cast<size_t>(num_args) : 1]; 2649 parse_context_type context_; 2650 parse_func parse_funcs_[num_args > 0 ? static_cast<size_t>(num_args) : 1]; 2651 2652 public: 2653 explicit FMT_CONSTEXPR format_string_checker(basic_string_view<Char> fmt) 2654 : types_{mapped_type_constant<Args, buffer_context<Char>>::value...}, 2655 context_(fmt, num_args, types_), 2656 parse_funcs_{&parse_format_specs<Args, parse_context_type>...} {} 2657 2658 FMT_CONSTEXPR void on_text(const Char*, const Char*) {} 2659 2660 FMT_CONSTEXPR auto on_arg_id() -> int { return context_.next_arg_id(); } 2661 FMT_CONSTEXPR auto on_arg_id(int id) -> int { 2662 return context_.check_arg_id(id), id; 2663 } 2664 FMT_CONSTEXPR auto on_arg_id(basic_string_view<Char> id) -> int { 2665 #if FMT_USE_NONTYPE_TEMPLATE_ARGS 2666 auto index = get_arg_index_by_name<Args...>(id); 2667 if (index < 0) on_error("named argument is not found"); 2668 return index; 2669 #else 2670 (void)id; 2671 on_error("compile-time checks for named arguments require C++20 support"); 2672 return 0; 2673 #endif 2674 } 2675 2676 FMT_CONSTEXPR void on_replacement_field(int id, const Char* begin) { 2677 on_format_specs(id, begin, begin); // Call parse() on empty specs. 2678 } 2679 2680 FMT_CONSTEXPR auto on_format_specs(int id, const Char* begin, const Char*) 2681 -> const Char* { 2682 context_.advance_to(begin); 2683 // id >= 0 check is a workaround for gcc 10 bug (#2065). 2684 return id >= 0 && id < num_args ? parse_funcs_[id](context_) : begin; 2685 } 2686 2687 FMT_CONSTEXPR void on_error(const char* message) { 2688 throw_format_error(message); 2689 } 2690 }; 2691 2692 // Reports a compile-time error if S is not a valid format string. 2693 template <typename..., typename S, FMT_ENABLE_IF(!is_compile_string<S>::value)> 2694 FMT_INLINE void check_format_string(const S&) { 2695 #ifdef FMT_ENFORCE_COMPILE_STRING 2696 static_assert(is_compile_string<S>::value, 2697 "FMT_ENFORCE_COMPILE_STRING requires all format strings to use " 2698 "FMT_STRING."); 2699 #endif 2700 } 2701 template <typename... Args, typename S, 2702 FMT_ENABLE_IF(is_compile_string<S>::value)> 2703 void check_format_string(S format_str) { 2704 using char_t = typename S::char_type; 2705 FMT_CONSTEXPR auto s = basic_string_view<char_t>(format_str); 2706 using checker = format_string_checker<char_t, remove_cvref_t<Args>...>; 2707 FMT_CONSTEXPR bool error = (parse_format_string<true>(s, checker(s)), true); 2708 ignore_unused(error); 2709 } 2710 2711 template <typename Char = char> struct vformat_args { 2712 using type = basic_format_args< 2713 basic_format_context<std::back_insert_iterator<buffer<Char>>, Char>>; 2714 }; 2715 template <> struct vformat_args<char> { 2716 using type = format_args; 2717 }; 2718 2719 // Use vformat_args and avoid type_identity to keep symbols short. 2720 template <typename Char> 2721 void vformat_to(buffer<Char>& buf, basic_string_view<Char> fmt, 2722 typename vformat_args<Char>::type args, locale_ref loc = {}); 2723 2724 FMT_API void vprint_mojibake(std::FILE*, string_view, format_args); 2725 #ifndef _WIN32 2726 inline void vprint_mojibake(std::FILE*, string_view, format_args) {} 2727 #endif 2728 } // namespace detail 2729 2730 FMT_BEGIN_EXPORT 2731 2732 // A formatter specialization for natively supported types. 2733 template <typename T, typename Char> 2734 struct formatter<T, Char, 2735 enable_if_t<detail::type_constant<T, Char>::value != 2736 detail::type::custom_type>> { 2737 private: 2738 detail::dynamic_format_specs<Char> specs_; 2739 2740 public: 2741 template <typename ParseContext> 2742 FMT_CONSTEXPR auto parse(ParseContext& ctx) -> const Char* { 2743 auto type = detail::type_constant<T, Char>::value; 2744 auto end = 2745 detail::parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx, type); 2746 if (type == detail::type::char_type) detail::check_char_specs(specs_); 2747 return end; 2748 } 2749 2750 template <detail::type U = detail::type_constant<T, Char>::value, 2751 FMT_ENABLE_IF(U == detail::type::string_type || 2752 U == detail::type::cstring_type || 2753 U == detail::type::char_type)> 2754 FMT_CONSTEXPR void set_debug_format(bool set = true) { 2755 specs_.type = set ? presentation_type::debug : presentation_type::none; 2756 } 2757 2758 template <typename FormatContext> 2759 FMT_CONSTEXPR auto format(const T& val, FormatContext& ctx) const 2760 -> decltype(ctx.out()); 2761 }; 2762 2763 template <typename Char = char> struct runtime_format_string { 2764 basic_string_view<Char> str; 2765 }; 2766 2767 /** A compile-time format string. */ 2768 template <typename Char, typename... Args> class basic_format_string { 2769 private: 2770 basic_string_view<Char> str_; 2771 2772 public: 2773 template <typename S, 2774 FMT_ENABLE_IF( 2775 std::is_convertible<const S&, basic_string_view<Char>>::value)> 2776 FMT_CONSTEVAL FMT_INLINE basic_format_string(const S& s) : str_(s) { 2777 static_assert( 2778 detail::count< 2779 (std::is_base_of<detail::view, remove_reference_t<Args>>::value && 2780 std::is_reference<Args>::value)...>() == 0, 2781 "passing views as lvalues is disallowed"); 2782 #ifdef FMT_HAS_CONSTEVAL 2783 if constexpr (detail::count_named_args<Args...>() == 2784 detail::count_statically_named_args<Args...>()) { 2785 using checker = 2786 detail::format_string_checker<Char, remove_cvref_t<Args>...>; 2787 detail::parse_format_string<true>(str_, checker(s)); 2788 } 2789 #else 2790 detail::check_format_string<Args...>(s); 2791 #endif 2792 } 2793 basic_format_string(runtime_format_string<Char> fmt) : str_(fmt.str) {} 2794 2795 FMT_INLINE operator basic_string_view<Char>() const { return str_; } 2796 FMT_INLINE auto get() const -> basic_string_view<Char> { return str_; } 2797 }; 2798 2799 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 2800 // Workaround broken conversion on older gcc. 2801 template <typename...> using format_string = string_view; 2802 inline auto runtime(string_view s) -> string_view { return s; } 2803 #else 2804 template <typename... Args> 2805 using format_string = basic_format_string<char, type_identity_t<Args>...>; 2806 /** 2807 \rst 2808 Creates a runtime format string. 2809 2810 **Example**:: 2811 2812 // Check format string at runtime instead of compile-time. 2813 fmt::print(fmt::runtime("{:d}"), "I am not a number"); 2814 \endrst 2815 */ 2816 inline auto runtime(string_view s) -> runtime_format_string<> { return {{s}}; } 2817 #endif 2818 2819 FMT_API auto vformat(string_view fmt, format_args args) -> std::string; 2820 2821 /** 2822 \rst 2823 Formats ``args`` according to specifications in ``fmt`` and returns the result 2824 as a string. 2825 2826 **Example**:: 2827 2828 #include <fmt/core.h> 2829 std::string message = fmt::format("The answer is {}.", 42); 2830 \endrst 2831 */ 2832 template <typename... T> 2833 FMT_NODISCARD FMT_INLINE auto format(format_string<T...> fmt, T&&... args) 2834 -> std::string { 2835 return vformat(fmt, fmt::make_format_args(args...)); 2836 } 2837 2838 /** Formats a string and writes the output to ``out``. */ 2839 template <typename OutputIt, 2840 FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)> 2841 auto vformat_to(OutputIt out, string_view fmt, format_args args) -> OutputIt { 2842 auto&& buf = detail::get_buffer<char>(out); 2843 detail::vformat_to(buf, fmt, args, {}); 2844 return detail::get_iterator(buf, out); 2845 } 2846 2847 /** 2848 \rst 2849 Formats ``args`` according to specifications in ``fmt``, writes the result to 2850 the output iterator ``out`` and returns the iterator past the end of the output 2851 range. `format_to` does not append a terminating null character. 2852 2853 **Example**:: 2854 2855 auto out = std::vector<char>(); 2856 fmt::format_to(std::back_inserter(out), "{}", 42); 2857 \endrst 2858 */ 2859 template <typename OutputIt, typename... T, 2860 FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)> 2861 FMT_INLINE auto format_to(OutputIt out, format_string<T...> fmt, T&&... args) 2862 -> OutputIt { 2863 return vformat_to(out, fmt, fmt::make_format_args(args...)); 2864 } 2865 2866 template <typename OutputIt> struct format_to_n_result { 2867 /** Iterator past the end of the output range. */ 2868 OutputIt out; 2869 /** Total (not truncated) output size. */ 2870 size_t size; 2871 }; 2872 2873 template <typename OutputIt, typename... T, 2874 FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)> 2875 auto vformat_to_n(OutputIt out, size_t n, string_view fmt, format_args args) 2876 -> format_to_n_result<OutputIt> { 2877 using traits = detail::fixed_buffer_traits; 2878 auto buf = detail::iterator_buffer<OutputIt, char, traits>(out, n); 2879 detail::vformat_to(buf, fmt, args, {}); 2880 return {buf.out(), buf.count()}; 2881 } 2882 2883 /** 2884 \rst 2885 Formats ``args`` according to specifications in ``fmt``, writes up to ``n`` 2886 characters of the result to the output iterator ``out`` and returns the total 2887 (not truncated) output size and the iterator past the end of the output range. 2888 `format_to_n` does not append a terminating null character. 2889 \endrst 2890 */ 2891 template <typename OutputIt, typename... T, 2892 FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)> 2893 FMT_INLINE auto format_to_n(OutputIt out, size_t n, format_string<T...> fmt, 2894 T&&... args) -> format_to_n_result<OutputIt> { 2895 return vformat_to_n(out, n, fmt, fmt::make_format_args(args...)); 2896 } 2897 2898 /** Returns the number of chars in the output of ``format(fmt, args...)``. */ 2899 template <typename... T> 2900 FMT_NODISCARD FMT_INLINE auto formatted_size(format_string<T...> fmt, 2901 T&&... args) -> size_t { 2902 auto buf = detail::counting_buffer<>(); 2903 detail::vformat_to<char>(buf, fmt, fmt::make_format_args(args...), {}); 2904 return buf.count(); 2905 } 2906 2907 FMT_API void vprint(string_view fmt, format_args args); 2908 FMT_API void vprint(std::FILE* f, string_view fmt, format_args args); 2909 2910 /** 2911 \rst 2912 Formats ``args`` according to specifications in ``fmt`` and writes the output 2913 to ``stdout``. 2914 2915 **Example**:: 2916 2917 fmt::print("Elapsed time: {0:.2f} seconds", 1.23); 2918 \endrst 2919 */ 2920 template <typename... T> 2921 FMT_INLINE void print(format_string<T...> fmt, T&&... args) { 2922 const auto& vargs = fmt::make_format_args(args...); 2923 return detail::is_utf8() ? vprint(fmt, vargs) 2924 : detail::vprint_mojibake(stdout, fmt, vargs); 2925 } 2926 2927 /** 2928 \rst 2929 Formats ``args`` according to specifications in ``fmt`` and writes the 2930 output to the file ``f``. 2931 2932 **Example**:: 2933 2934 fmt::print(stderr, "Don't {}!", "panic"); 2935 \endrst 2936 */ 2937 template <typename... T> 2938 FMT_INLINE void print(std::FILE* f, format_string<T...> fmt, T&&... args) { 2939 const auto& vargs = fmt::make_format_args(args...); 2940 return detail::is_utf8() ? vprint(f, fmt, vargs) 2941 : detail::vprint_mojibake(f, fmt, vargs); 2942 } 2943 2944 /** 2945 Formats ``args`` according to specifications in ``fmt`` and writes the 2946 output to the file ``f`` followed by a newline. 2947 */ 2948 template <typename... T> 2949 FMT_INLINE void println(std::FILE* f, format_string<T...> fmt, T&&... args) { 2950 return fmt::print(f, "{}\n", fmt::format(fmt, std::forward<T>(args)...)); 2951 } 2952 2953 /** 2954 Formats ``args`` according to specifications in ``fmt`` and writes the output 2955 to ``stdout`` followed by a newline. 2956 */ 2957 template <typename... T> 2958 FMT_INLINE void println(format_string<T...> fmt, T&&... args) { 2959 return fmt::println(stdout, fmt, std::forward<T>(args)...); 2960 } 2961 2962 FMT_END_EXPORT 2963 FMT_GCC_PRAGMA("GCC pop_options") 2964 FMT_END_NAMESPACE 2965 2966 #ifdef FMT_HEADER_ONLY 2967 # include "format.h" 2968 #endif 2969 #endif // FMT_CORE_H_ 2970