17 #include <type_traits> 21 #define FMT_VERSION 70103 24 # define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__) 26 # define FMT_CLANG_VERSION 0 29 #if defined(__GNUC__) && !defined(__clang__) 30 # define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) 32 # define FMT_GCC_VERSION 0 35 #if defined(__INTEL_COMPILER) 36 # define FMT_ICC_VERSION __INTEL_COMPILER 38 # define FMT_ICC_VERSION 0 41 #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) 42 # define FMT_HAS_GXX_CXX11 FMT_GCC_VERSION 44 # define FMT_HAS_GXX_CXX11 0 48 # define FMT_NVCC __NVCC__ 54 # define FMT_MSC_VER _MSC_VER 55 # define FMT_SUPPRESS_MSC_WARNING(n) __pragma(warning(suppress : n)) 57 # define FMT_MSC_VER 0 58 # define FMT_SUPPRESS_MSC_WARNING(n) 62 # define FMT_HAS_FEATURE(x) __has_feature(x) 64 # define FMT_HAS_FEATURE(x) 0 67 #if defined(__has_include) && !defined(__INTELLISENSE__) && \ 68 (!FMT_ICC_VERSION || FMT_ICC_VERSION >= 1600) 69 # define FMT_HAS_INCLUDE(x) __has_include(x) 71 # define FMT_HAS_INCLUDE(x) 0 74 #ifdef __has_cpp_attribute 75 # define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) 77 # define FMT_HAS_CPP_ATTRIBUTE(x) 0 80 #define FMT_HAS_CPP14_ATTRIBUTE(attribute) \ 81 (__cplusplus >= 201402L && FMT_HAS_CPP_ATTRIBUTE(attribute)) 83 #define FMT_HAS_CPP17_ATTRIBUTE(attribute) \ 84 (__cplusplus >= 201703L && FMT_HAS_CPP_ATTRIBUTE(attribute)) 88 #ifndef FMT_USE_CONSTEXPR 89 # define FMT_USE_CONSTEXPR \ 90 (FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VER >= 1910 || \ 91 (FMT_GCC_VERSION >= 600 && __cplusplus >= 201402L)) && \ 92 !FMT_NVCC && !FMT_ICC_VERSION 95 # define FMT_CONSTEXPR constexpr 96 # define FMT_CONSTEXPR_DECL constexpr 98 # define FMT_CONSTEXPR inline 99 # define FMT_CONSTEXPR_DECL 103 # if FMT_HAS_FEATURE(cxx_override_control) || \ 104 (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900 105 # define FMT_OVERRIDE override 107 # define FMT_OVERRIDE 112 #ifndef FMT_EXCEPTIONS 113 # if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || \ 114 FMT_MSC_VER && !_HAS_EXCEPTIONS 115 # define FMT_EXCEPTIONS 0 117 # define FMT_EXCEPTIONS 1 122 #ifndef FMT_USE_NOEXCEPT 123 # define FMT_USE_NOEXCEPT 0 126 #if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \ 127 (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900 128 # define FMT_DETECTED_NOEXCEPT noexcept 129 # define FMT_HAS_CXX11_NOEXCEPT 1 131 # define FMT_DETECTED_NOEXCEPT throw() 132 # define FMT_HAS_CXX11_NOEXCEPT 0 136 # if FMT_EXCEPTIONS || FMT_HAS_CXX11_NOEXCEPT 137 # define FMT_NOEXCEPT FMT_DETECTED_NOEXCEPT 139 # define FMT_NOEXCEPT 145 #if FMT_EXCEPTIONS && FMT_HAS_CPP_ATTRIBUTE(noreturn) && !FMT_MSC_VER && \ 147 # define FMT_NORETURN [[noreturn]] 149 # define FMT_NORETURN 152 #ifndef FMT_DEPRECATED 153 # if FMT_HAS_CPP14_ATTRIBUTE(deprecated) || FMT_MSC_VER >= 1900 154 # define FMT_DEPRECATED [[deprecated]] 156 # if (defined(__GNUC__) && !defined(__LCC__)) || defined(__clang__) 157 # define FMT_DEPRECATED __attribute__((deprecated)) 159 # define FMT_DEPRECATED __declspec(deprecated) 161 # define FMT_DEPRECATED 167 #if FMT_ICC_VERSION || defined(__PGI) || FMT_NVCC 168 # define FMT_DEPRECATED_ALIAS 170 # define FMT_DEPRECATED_ALIAS FMT_DEPRECATED 174 # if FMT_GCC_VERSION || FMT_CLANG_VERSION 175 # define FMT_INLINE inline __attribute__((always_inline)) 177 # define FMT_INLINE inline 181 #ifndef FMT_USE_INLINE_NAMESPACES 182 # if FMT_HAS_FEATURE(cxx_inline_namespaces) || FMT_GCC_VERSION >= 404 || \ 183 (FMT_MSC_VER >= 1900 && !_MANAGED) 184 # define FMT_USE_INLINE_NAMESPACES 1 186 # define FMT_USE_INLINE_NAMESPACES 0 190 #ifndef FMT_BEGIN_NAMESPACE 191 # if FMT_USE_INLINE_NAMESPACES 192 # define FMT_INLINE_NAMESPACE inline namespace 193 # define FMT_END_NAMESPACE \ 197 # define FMT_INLINE_NAMESPACE namespace 198 # define FMT_END_NAMESPACE \ 200 using namespace v7; \ 203 # define FMT_BEGIN_NAMESPACE \ 205 FMT_INLINE_NAMESPACE v7 { 208 #if !defined(FMT_HEADER_ONLY) && defined(_WIN32) 209 # define FMT_CLASS_API FMT_SUPPRESS_MSC_WARNING(4275) 211 # define FMT_API __declspec(dllexport) 212 # define FMT_EXTERN_TEMPLATE_API FMT_API 213 # define FMT_EXPORTED 214 # elif defined(FMT_SHARED) 215 # define FMT_API __declspec(dllimport) 216 # define FMT_EXTERN_TEMPLATE_API FMT_API 219 # define FMT_CLASS_API 224 #ifndef FMT_EXTERN_TEMPLATE_API 225 # define FMT_EXTERN_TEMPLATE_API 227 #ifndef FMT_INSTANTIATION_DEF_API 228 # define FMT_INSTANTIATION_DEF_API FMT_API 231 #ifndef FMT_HEADER_ONLY 232 # define FMT_EXTERN extern 238 #if (FMT_HAS_INCLUDE(<string_view>) && \ 239 (__cplusplus > 201402L || defined(_LIBCPP_VERSION))) || \ 240 (defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910) 241 # include <string_view> 242 # define FMT_USE_STRING_VIEW 243 #elif FMT_HAS_INCLUDE("experimental/string_view") && __cplusplus >= 201402L 244 # include <experimental/string_view> 245 # define FMT_USE_EXPERIMENTAL_STRING_VIEW 249 # define FMT_UNICODE !FMT_MSC_VER 251 #if FMT_UNICODE && FMT_MSC_VER 252 # pragma execution_character_set("utf-8") 258 template <
bool B,
class T =
void>
259 using enable_if_t =
typename std::enable_if<B, T>::type;
260 template <
bool B,
class T,
class F>
261 using conditional_t =
typename std::conditional<B, T, F>::type;
262 template <
bool B>
using bool_constant = std::integral_constant<bool, B>;
263 template <
typename T>
264 using remove_reference_t =
typename std::remove_reference<T>::type;
265 template <
typename T>
266 using remove_const_t =
typename std::remove_const<T>::type;
267 template <
typename T>
268 using remove_cvref_t =
typename std::remove_cv<remove_reference_t<T>>::type;
270 template <
typename T>
using type_identity_t =
typename type_identity<T>::type;
277 #define FMT_ENABLE_IF(...) enable_if_t<(__VA_ARGS__), int> = 0 282 template <
typename T> constexpr T const_check(T value) {
return value; }
284 FMT_NORETURN FMT_API
void assert_fail(
const char* file,
int line,
285 const char* message);
290 # define FMT_ASSERT(condition, message) ((void)0) 292 # define FMT_ASSERT(condition, message) \ 295 : ::fmt::detail::assert_fail(__FILE__, __LINE__, (message))) 299 #if defined(FMT_USE_STRING_VIEW) 300 template <
typename Char>
using std_string_view = std::basic_string_view<Char>;
301 #elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW) 302 template <
typename Char>
303 using std_string_view = std::experimental::basic_string_view<Char>;
308 #ifdef FMT_USE_INT128 310 #elif defined(__SIZEOF_INT128__) && !FMT_NVCC && \ 311 !(FMT_CLANG_VERSION && FMT_MSC_VER) 312 # define FMT_USE_INT128 1 316 # define FMT_USE_INT128 0 324 template <
typename Int>
325 FMT_CONSTEXPR
typename std::make_unsigned<Int>::type to_unsigned(Int value) {
326 FMT_ASSERT(value >= 0,
"negative value");
327 return static_cast<typename std::make_unsigned<Int>::type
>(value);
330 FMT_SUPPRESS_MSC_WARNING(4566) constexpr
unsigned char micro[] =
"\u00B5";
332 template <
typename Char> constexpr
bool is_unicode() {
333 return FMT_UNICODE ||
sizeof(Char) != 1 ||
334 (
sizeof(micro) == 3 && micro[0] == 0xC2 && micro[1] == 0xB5);
338 using char8_type = char8_t;
340 enum char8_type :
unsigned char {};
344 #ifdef FMT_USE_INTERNAL 345 namespace internal =
detail;
361 using value_type = Char;
362 using iterator =
const Char*;
377 #if __cplusplus >= 201703L // C++17's char_traits::length() is constexpr. 381 : data_(s), size_(
std::char_traits<Char>::length(s)) {}
384 template <
typename Traits,
typename Alloc>
386 const std::basic_string<Char, Traits, Alloc>&
s) FMT_NOEXCEPT
390 template <
typename S, FMT_ENABLE_IF(std::is_same<
396 constexpr
const Char*
data()
const {
return data_; }
399 constexpr
size_t size()
const {
return size_; }
401 constexpr iterator begin()
const {
return data_; }
402 constexpr iterator end()
const {
return data_ + size_; }
404 constexpr
const Char& operator[](
size_t pos)
const {
return data_[pos]; }
406 FMT_CONSTEXPR
void remove_prefix(
size_t n) {
413 size_t str_size = size_ < other.size_ ? size_ : other.size_;
414 int result = std::char_traits<Char>::compare(data_, other.data_, str_size);
416 result = size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1);
421 return lhs.compare(rhs) == 0;
424 return lhs.compare(rhs) != 0;
427 return lhs.compare(rhs) < 0;
430 return lhs.compare(rhs) <= 0;
433 return lhs.compare(rhs) > 0;
436 return lhs.compare(rhs) >= 0;
444 template <
typename T>
struct is_char : std::false_type {};
445 template <>
struct is_char<char> : std::true_type {};
446 template <>
struct is_char<wchar_t> : std::true_type {};
448 template <>
struct is_char<char16_t> : std::true_type {};
449 template <>
struct is_char<char32_t> : std::true_type {};
467 template <typename Char, FMT_ENABLE_IF(is_char<Char>::value)>
472 template <
typename Char,
typename Traits,
typename Alloc>
474 const std::basic_string<Char, Traits, Alloc>& s) {
478 template <
typename Char>
483 template <
typename Char,
493 template <
typename S>
496 template <typename S, FMT_ENABLE_IF(is_compile_string<S>::value)>
502 void to_string_view(...);
503 using fmt::v7::to_string_view;
508 template <
typename S>
509 struct is_string : std::is_class<decltype(to_string_view(std::declval<S>()))> {
514 using result = decltype(to_string_view(std::declval<S>()));
515 using type =
typename result::value_type;
520 FMT_INLINE
void check_format_string(
const S&) {
521 #ifdef FMT_ENFORCE_COMPILE_STRING 523 "FMT_ENFORCE_COMPILE_STRING requires all format strings to use " 528 void check_format_string(S);
535 FMT_NORETURN FMT_API
void on_error(
const char* message);
558 template <
typename Char,
typename ErrorHandler = detail::error_handler>
565 using char_type = Char;
566 using iterator =
typename basic_string_view<Char>::iterator;
571 : ErrorHandler(eh), format_str_(format_str), next_arg_id_(next_arg_id) {}
577 constexpr iterator
begin() const FMT_NOEXCEPT {
return format_str_.begin(); }
582 constexpr iterator
end() const FMT_NOEXCEPT {
return format_str_.end(); }
586 format_str_.remove_prefix(detail::to_unsigned(it - begin()));
596 if (next_arg_id_ >= 0)
return next_arg_id_++;
597 on_error(
"cannot switch from manual to automatic argument indexing");
606 if (next_arg_id_ > 0)
607 on_error(
"cannot switch from automatic to manual argument indexing");
614 FMT_CONSTEXPR
void on_error(
const char* message) {
615 ErrorHandler::on_error(message);
618 constexpr ErrorHandler error_handler()
const {
return *
this; }
629 template <
typename T,
typename Char =
char,
typename Enable =
void>
637 template <
typename T,
typename Context>
638 using has_formatter =
639 std::is_constructible<typename Context::template formatter_type<T>>;
643 template <
typename Char>
649 template <
typename Container>
650 inline Container& get_container(std::back_insert_iterator<Container> it) {
651 using bi_iterator = std::back_insert_iterator<Container>;
652 struct accessor : bi_iterator {
653 accessor(bi_iterator iter) : bi_iterator(iter) {}
654 using bi_iterator::container;
656 return *accessor(it).container;
673 FMT_SUPPRESS_MSC_WARNING(26495)
674 buffer(
size_t sz) FMT_NOEXCEPT : size_(sz), capacity_(sz) {}
676 buffer(T* p =
nullptr,
size_t sz = 0,
size_t cap = 0) FMT_NOEXCEPT
684 void set(T* buf_data,
size_t buf_capacity) FMT_NOEXCEPT {
686 capacity_ = buf_capacity;
690 virtual void grow(
size_t capacity) = 0;
693 using value_type = T;
694 using const_reference =
const T&;
697 void operator=(
const buffer&) =
delete;
699 T* begin() FMT_NOEXCEPT {
return ptr_; }
700 T* end() FMT_NOEXCEPT {
return ptr_ + size_; }
702 const T* begin()
const FMT_NOEXCEPT {
return ptr_; }
703 const T* end()
const FMT_NOEXCEPT {
return ptr_ + size_; }
706 size_t size() const FMT_NOEXCEPT {
return size_; }
709 size_t capacity() const FMT_NOEXCEPT {
return capacity_; }
712 T*
data() FMT_NOEXCEPT {
return ptr_; }
715 const T*
data() const FMT_NOEXCEPT {
return ptr_; }
722 void try_resize(
size_t count) {
724 size_ = count <= capacity_ ? count : capacity_;
731 void try_reserve(
size_t new_capacity) {
732 if (new_capacity > capacity_) grow(new_capacity);
735 void push_back(
const T&
value) {
736 try_reserve(size_ + 1);
737 ptr_[size_++] = value;
741 template <
typename U>
void append(
const U* begin,
const U* end);
743 template <
typename I> T& operator[](I index) {
return ptr_[index]; }
744 template <
typename I>
const T& operator[](I index)
const {
751 size_t count()
const {
return 0; }
752 size_t limit(
size_t size) {
return size; }
762 size_t count()
const {
return count_; }
763 size_t limit(
size_t size) {
764 size_t n = limit_ > count_ ? limit_ - count_ : 0;
766 return size < n ? size : n;
771 template <
typename OutputIt,
typename T,
typename Traits = buffer_traits>
775 enum { buffer_size = 256 };
776 T data_[buffer_size];
779 void grow(
size_t)
final FMT_OVERRIDE {
780 if (this->size() == buffer_size) flush();
795 size_t count()
const {
return Traits::count() + this->size(); }
800 void grow(
size_t)
final FMT_OVERRIDE {}
805 T* out() {
return &*this->end(); }
809 template <
typename Container>
811 enable_if_t<is_contiguous<Container>::value,
812 typename Container::value_type>>
813 final :
public buffer<typename Container::value_type> {
815 Container& container_;
818 void grow(
size_t capacity)
final FMT_OVERRIDE {
819 container_.resize(capacity);
820 this->
set(&container_[0], capacity);
826 explicit iterator_buffer(std::back_insert_iterator<Container> out,
size_t = 0)
828 std::back_insert_iterator<Container> out() {
829 return std::back_inserter(container_);
836 enum { buffer_size = 256 };
837 T data_[buffer_size];
841 void grow(
size_t)
final FMT_OVERRIDE {
842 if (this->size() != buffer_size)
return;
843 count_ += this->size();
850 size_t count() {
return count_ + this->size(); }
855 template <
typename T>
857 using base = std::back_insert_iterator<buffer<T>>;
876 template <
typename T,
typename OutputIt>
880 template <
typename OutputIt> OutputIt get_buffer_init(OutputIt out) {
884 return get_container(out);
887 template <
typename Buffer>
888 auto get_iterator(Buffer& buf) -> decltype(buf.out()) {
895 template <
typename T,
typename Char =
char,
typename Enable =
void>
901 template <
typename T,
typename Context>
902 using has_fallback_formatter =
903 std::is_constructible<fallback_formatter<T, typename Context::char_type>>;
910 named_arg(
const Char* n,
const T& v) : name(n), value(v) {}
918 template <
typename T,
typename Char,
size_t NUM_ARGS,
size_t NUM_NAMED_ARGS>
922 T args_[1 + (NUM_ARGS != 0 ? NUM_ARGS : +1)];
925 template <
typename... U>
926 arg_data(
const U&... init) : args_{T(named_args_, NUM_NAMED_ARGS), init...} {}
927 arg_data(
const arg_data& other) =
delete;
928 const T* args()
const {
return args_ + 1; }
932 template <
typename T,
typename Char,
size_t NUM_ARGS>
935 T args_[NUM_ARGS != 0 ? NUM_ARGS : +1];
937 template <
typename... U>
938 FMT_INLINE
arg_data(
const U&... init) : args_{init...} {}
939 FMT_INLINE
const T* args()
const {
return args_; }
940 FMT_INLINE std::nullptr_t named_args() {
return nullptr; }
943 template <
typename Char>
946 template <
typename Char,
typename T,
typename... Tail>
948 int named_arg_count,
const T&,
const Tail&... args) {
949 init_named_args(named_args, arg_count + 1, named_arg_count, args...);
952 template <
typename Char,
typename T,
typename... Tail>
955 const Tail&... args) {
956 named_args[named_arg_count++] = {arg.name, arg_count};
957 init_named_args(named_args, arg_count + 1, named_arg_count, args...);
960 template <
typename... Args>
961 FMT_INLINE
void init_named_args(std::nullptr_t,
int,
int,
const Args&...) {}
965 template <
typename T,
typename Char>
968 template <
bool B = false> constexpr
size_t count() {
return B ? 1 : 0; }
969 template <
bool B1,
bool B2,
bool... Tail> constexpr
size_t count() {
970 return (B1 ? 1 : 0) + count<B2, Tail...>();
973 template <
typename... Args> constexpr
size_t count_named_args() {
974 return count<is_named_arg<Args>::value...>();
988 last_integer_type = char_type,
993 last_numeric_type = long_double_type,
1001 template <
typename T,
typename Char>
1004 #define FMT_TYPE_CONSTANT(Type, constant) \ 1005 template <typename Char> \ 1006 struct type_constant<Type, Char> \ 1007 : std::integral_constant<type, type::constant> {} 1009 FMT_TYPE_CONSTANT(
int, int_type);
1010 FMT_TYPE_CONSTANT(
unsigned, uint_type);
1011 FMT_TYPE_CONSTANT(
long long, long_long_type);
1012 FMT_TYPE_CONSTANT(
unsigned long long, ulong_long_type);
1013 FMT_TYPE_CONSTANT(
int128_t, int128_type);
1014 FMT_TYPE_CONSTANT(
uint128_t, uint128_type);
1015 FMT_TYPE_CONSTANT(
bool, bool_type);
1016 FMT_TYPE_CONSTANT(Char, char_type);
1017 FMT_TYPE_CONSTANT(
float, float_type);
1018 FMT_TYPE_CONSTANT(
double, double_type);
1019 FMT_TYPE_CONSTANT(
long double, long_double_type);
1020 FMT_TYPE_CONSTANT(
const Char*, cstring_type);
1022 FMT_TYPE_CONSTANT(
const void*, pointer_type);
1024 constexpr
bool is_integral_type(type t) {
1025 return t > type::none_type && t <= type::last_integer_type;
1028 constexpr
bool is_arithmetic_type(type t) {
1029 return t > type::none_type && t <= type::last_numeric_type;
1043 using parse_context =
typename Context::parse_context_type;
1045 void (*format)(
const void* arg, parse_context& parse_ctx, Context& ctx);
1049 template <
typename Context>
class value {
1051 using char_type =
typename Context::char_type;
1055 unsigned uint_value;
1056 long long long_long_value;
1057 unsigned long long ulong_long_value;
1061 char_type char_value;
1063 double double_value;
1064 long double long_double_value;
1065 const void* pointer;
1071 constexpr FMT_INLINE
value(
int val = 0) : int_value(val) {}
1072 constexpr FMT_INLINE value(
unsigned val) : uint_value(val) {}
1073 FMT_INLINE value(
long long val) : long_long_value(val) {}
1074 FMT_INLINE value(
unsigned long long val) : ulong_long_value(val) {}
1075 FMT_INLINE value(
int128_t val) : int128_value(val) {}
1076 FMT_INLINE value(
uint128_t val) : uint128_value(val) {}
1077 FMT_INLINE value(
float val) : float_value(val) {}
1078 FMT_INLINE value(
double val) : double_value(val) {}
1079 FMT_INLINE value(
long double val) : long_double_value(val) {}
1080 FMT_INLINE value(
bool val) : bool_value(val) {}
1081 FMT_INLINE value(char_type val) : char_value(val) {}
1082 FMT_INLINE value(
const char_type* val) {
string.data = val; }
1084 string.data = val.
data();
1085 string.size = val.
size();
1087 FMT_INLINE value(
const void* val) : pointer(val) {}
1089 : named_args{args, size} {}
1091 template <
typename T> FMT_INLINE value(
const T& val) {
1092 custom.value = &val;
1096 custom.format = format_custom_arg<
1097 T, conditional_t<has_formatter<T, Context>::value,
1098 typename Context::template formatter_type<T>,
1104 template <
typename T,
typename Formatter>
1105 static void format_custom_arg(
const void* arg,
1106 typename Context::parse_context_type& parse_ctx,
1109 parse_ctx.advance_to(f.parse(parse_ctx));
1110 ctx.advance_to(f.format(*static_cast<const T*>(arg), ctx));
1114 template <
typename Context,
typename T>
1119 enum { long_short =
sizeof(long) ==
sizeof(
int) };
1120 using long_type = conditional_t<long_short, int, long long>;
1121 using ulong_type = conditional_t<long_short, unsigned, unsigned long long>;
1127 using char_type =
typename Context::char_type;
1129 FMT_CONSTEXPR
int map(
signed char val) {
return val; }
1130 FMT_CONSTEXPR
unsigned map(
unsigned char val) {
return val; }
1131 FMT_CONSTEXPR
int map(
short val) {
return val; }
1132 FMT_CONSTEXPR
unsigned map(
unsigned short val) {
return val; }
1133 FMT_CONSTEXPR
int map(
int val) {
return val; }
1134 FMT_CONSTEXPR
unsigned map(
unsigned val) {
return val; }
1135 FMT_CONSTEXPR long_type map(
long val) {
return val; }
1136 FMT_CONSTEXPR ulong_type map(
unsigned long val) {
return val; }
1137 FMT_CONSTEXPR
long long map(
long long val) {
return val; }
1138 FMT_CONSTEXPR
unsigned long long map(
unsigned long long val) {
return val; }
1141 FMT_CONSTEXPR
bool map(
bool val) {
return val; }
1143 template <typename T, FMT_ENABLE_IF(is_char<T>::value)>
1144 FMT_CONSTEXPR char_type map(T val) {
1146 std::is_same<T, char>::value || std::is_same<T, char_type>::value,
1147 "mixing character types is disallowed");
1151 FMT_CONSTEXPR
float map(
float val) {
return val; }
1152 FMT_CONSTEXPR
double map(
double val) {
return val; }
1153 FMT_CONSTEXPR
long double map(
long double val) {
return val; }
1155 FMT_CONSTEXPR
const char_type* map(char_type* val) {
return val; }
1156 FMT_CONSTEXPR
const char_type* map(
const char_type* val) {
return val; }
1157 template <typename T, FMT_ENABLE_IF(is_string<T>::value)>
1159 static_assert(std::is_same<char_type, char_t<T>>::value,
1160 "mixing character types is disallowed");
1161 return to_string_view(val);
1163 template <
typename T,
1167 !has_fallback_formatter<T, Context>::value)>
1177 !has_fallback_formatter<T, Context>::value)>
1181 FMT_CONSTEXPR
const char* map(
const signed char* val) {
1182 static_assert(std::is_same<char_type, char>::value,
"invalid string type");
1183 return reinterpret_cast<const char*
>(val);
1185 FMT_CONSTEXPR
const char* map(
const unsigned char* val) {
1186 static_assert(std::is_same<char_type, char>::value,
"invalid string type");
1187 return reinterpret_cast<const char*
>(val);
1189 FMT_CONSTEXPR
const char* map(
signed char* val) {
1190 const auto* const_val = val;
1191 return map(const_val);
1193 FMT_CONSTEXPR
const char* map(
unsigned char* val) {
1194 const auto* const_val = val;
1195 return map(const_val);
1198 FMT_CONSTEXPR
const void* map(
void* val) {
return val; }
1199 FMT_CONSTEXPR
const void* map(
const void* val) {
return val; }
1200 FMT_CONSTEXPR
const void* map(std::nullptr_t val) {
return val; }
1201 template <
typename T> FMT_CONSTEXPR
int map(
const T*) {
1206 static_assert(!
sizeof(T),
"formatting of non-void pointers is disallowed");
1210 template <
typename T,
1211 FMT_ENABLE_IF(std::is_enum<T>::value &&
1212 !has_formatter<T, Context>::value &&
1213 !has_fallback_formatter<T, Context>::value)>
1214 FMT_CONSTEXPR
auto map(
const T& val)
1215 -> decltype(std::declval<arg_mapper>().map(
1216 static_cast<typename std::underlying_type<T>::type
>(val))) {
1217 return map(
static_cast<typename std::underlying_type<T>::type
>(val));
1219 template <
typename T,
1221 (has_formatter<T, Context>::value ||
1222 has_fallback_formatter<T, Context>::value))>
1223 FMT_CONSTEXPR
const T& map(
const T& val) {
1227 template <
typename T>
1229 -> decltype(std::declval<arg_mapper>().map(val.value)) {
1230 return map(val.value);
1237 template <
typename T,
typename Context>
1240 typename Context::char_type>;
1242 enum { packed_arg_bits = 4 };
1244 enum { max_packed_args = 62 / packed_arg_bits };
1245 enum :
unsigned long long { is_unpacked_bit = 1ULL << 63 };
1246 enum :
unsigned long long { has_named_args_bit = 1ULL << 62 };
1256 template <
typename ContextType,
typename T>
1260 template <
typename Visitor,
typename Ctx>
1261 friend FMT_CONSTEXPR
auto visit_format_arg(Visitor&& vis,
1263 -> decltype(vis(0));
1268 using char_type =
typename Context::char_type;
1270 template <
typename T,
typename Char,
size_t NUM_ARGS,
size_t NUM_NAMED_ARGS>
1274 : value_(args, size) {}
1281 void format(
typename Context::parse_context_type& parse_ctx,
1282 Context& ctx)
const {
1283 custom_.format(custom_.value, parse_ctx, ctx);
1290 constexpr basic_format_arg() : type_(detail::type::none_type) {}
1292 constexpr
explicit operator bool()
const FMT_NOEXCEPT {
1293 return type_ != detail::type::none_type;
1296 detail::type type()
const {
return type_; }
1298 bool is_integral()
const {
return detail::is_integral_type(type_); }
1299 bool is_arithmetic()
const {
return detail::is_arithmetic_type(type_); }
1309 template <
typename Visitor,
typename Context>
1310 FMT_CONSTEXPR_DECL FMT_INLINE
auto visit_format_arg(
1312 using char_type =
typename Context::char_type;
1313 switch (arg.type_) {
1314 case detail::type::none_type:
1316 case detail::type::int_type:
1317 return vis(arg.value_.int_value);
1318 case detail::type::uint_type:
1319 return vis(arg.value_.uint_value);
1320 case detail::type::long_long_type:
1321 return vis(arg.value_.long_long_value);
1322 case detail::type::ulong_long_type:
1323 return vis(arg.value_.ulong_long_value);
1325 case detail::type::int128_type:
1326 return vis(arg.value_.int128_value);
1327 case detail::type::uint128_type:
1328 return vis(arg.value_.uint128_value);
1330 case detail::type::int128_type:
1331 case detail::type::uint128_type:
1334 case detail::type::bool_type:
1335 return vis(arg.value_.bool_value);
1336 case detail::type::char_type:
1337 return vis(arg.value_.char_value);
1338 case detail::type::float_type:
1339 return vis(arg.value_.float_value);
1340 case detail::type::double_type:
1341 return vis(arg.value_.double_value);
1342 case detail::type::long_double_type:
1343 return vis(arg.value_.long_double_value);
1344 case detail::type::cstring_type:
1345 return vis(arg.value_.string.data);
1346 case detail::type::string_type:
1348 arg.value_.string.size));
1349 case detail::type::pointer_type:
1350 return vis(arg.value_.pointer);
1351 case detail::type::custom_type:
1363 template <
typename... Ts>
1366 template <
typename It,
typename T,
typename Enable =
void>
1369 template <
typename It,
typename T>
1372 void_t<typename std::iterator_traits<It>::iterator_category,
1373 decltype(*std::declval<It>() = std::declval<T>())>>
1374 : std::true_type {};
1376 template <
typename OutputIt>
1378 template <
typename Container>
1380 : std::true_type {};
1382 template <
typename OutputIt>
1384 template <
typename Container>
1387 template <
typename Char>
1389 : std::true_type {};
1394 const void* locale_;
1398 template <
typename Locale>
explicit locale_ref(
const Locale& loc);
1400 explicit operator bool()
const FMT_NOEXCEPT {
return locale_ !=
nullptr; }
1402 template <
typename Locale> Locale
get()
const;
1405 template <
typename> constexpr
unsigned long long encode_types() {
return 0; }
1407 template <
typename Context,
typename Arg,
typename... Args>
1408 constexpr
unsigned long long encode_types() {
1410 (encode_types<Context, Args...>() << packed_arg_bits);
1413 template <
typename Context,
typename T>
1424 "Cannot format an argument. To make type T formattable provide a " 1425 "formatter<T> specialization: https://fmt.dev/latest/api.html#udt");
1428 template <
typename T,
typename U>
inline const U& check(
const U& val) {
1435 template <
bool IS_PACKED,
typename Context, type,
typename T,
1436 FMT_ENABLE_IF(IS_PACKED)>
1441 template <
bool IS_PACKED,
typename Context, type,
typename T,
1442 FMT_ENABLE_IF(!IS_PACKED)>
1444 return make_arg<Context>(value);
1448 template <
typename T>
1451 template <
typename T>
const T& unwrap(
const T& v) {
return v; }
1452 template <
typename T>
const T& unwrap(
const std::reference_wrapper<T>& v) {
1453 return static_cast<const T&
>(v);
1460 template <
typename =
void>
struct node {
1461 virtual ~node() =
default;
1462 std::unique_ptr<node<>> next;
1465 template <
typename T>
struct typed_node : node<> {
1468 template <
typename Arg>
1469 FMT_CONSTEXPR typed_node(
const Arg& arg) : value(arg) {}
1471 template <
typename Char>
1476 std::unique_ptr<node<>> head_;
1479 template <
typename T,
typename Arg>
const T& push(
const Arg& arg) {
1480 auto new_node = std::unique_ptr<typed_node<T>>(
new typed_node<T>(arg));
1481 auto& value = new_node->value;
1482 new_node->next = std::move(head_);
1483 head_ = std::move(new_node);
1501 using iterator = OutputIt;
1515 : out_(out), args_(ctx_args), loc_(loc) {}
1523 void on_error(
const char* message) { error_handler().on_error(message); }
1526 iterator out() {
return out_; }
1529 void advance_to(iterator it) {
1536 template <
typename Char>
1543 #define FMT_BUFFER_CONTEXT(Char) \ 1544 basic_format_context<detail::buffer_appender<Char>, Char> 1553 template <
typename Context,
typename... Args>
1555 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
1561 static const size_t num_args =
sizeof...(Args);
1562 static const size_t num_named_args = detail::count_named_args<Args...>();
1563 static const bool is_packed = num_args <= detail::max_packed_args;
1565 using value_type = conditional_t<is_packed, detail::value<Context>,
1574 static constexpr
unsigned long long desc =
1575 (is_packed ? detail::encode_types<Context, Args...>()
1576 : detail::is_unpacked_bit | num_args) |
1577 (num_named_args != 0
1578 ?
static_cast<unsigned long long>(detail::has_named_args_bit)
1584 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 1587 data_{detail::make_arg<
1590 detail::init_named_args(data_.named_args(), 0, 0, args...);
1604 const Args&... args) {
1616 template <
typename... Args,
typename S,
typename Char = char_t<S>>
1617 inline auto make_args_checked(
const S& format_str,
1618 const remove_reference_t<Args>&... args)
1622 std::is_base_of<
detail::view, remove_reference_t<Args>>::value &&
1623 std::is_reference<Args>::value)...>() == 0,
1624 "passing views as lvalues is disallowed");
1625 detail::check_format_string<Args...>(format_str);
1639 template <
typename Char,
typename T>
1655 template <
typename Context>
1657 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
1663 using char_type =
typename Context::char_type;
1665 template <
typename T>
struct need_copy {
1666 static constexpr detail::type mapped_type =
1671 std::is_same<T, basic_string_view<char_type>>::value ||
1672 std::is_same<T, detail::std_string_view<char_type>>::value ||
1673 (mapped_type != detail::type::cstring_type &&
1674 mapped_type != detail::type::string_type &&
1675 mapped_type != detail::type::custom_type))
1679 template <
typename T>
1680 using stored_type = conditional_t<detail::is_string<T>::value,
1681 std::basic_string<char_type>, T>;
1684 std::vector<basic_format_arg<Context>> data_;
1685 std::vector<detail::named_arg_info<char_type>> named_info_;
1693 unsigned long long get_types()
const {
1694 return detail::is_unpacked_bit | data_.size() |
1695 (named_info_.empty()
1697 :
static_cast<unsigned long long>(detail::has_named_args_bit));
1701 return named_info_.empty() ? data_.data() : data_.data() + 1;
1704 template <
typename T>
void emplace_arg(
const T& arg) {
1705 data_.emplace_back(detail::make_arg<Context>(arg));
1708 template <
typename T>
1710 if (named_info_.empty()) {
1712 data_.insert(data_.begin(), {zero_ptr, 0});
1714 data_.emplace_back(detail::make_arg<Context>(detail::unwrap(arg.value)));
1715 auto pop_one = [](std::vector<basic_format_arg<Context>>* data) {
1718 std::unique_ptr<std::vector<basic_format_arg<Context>>, decltype(pop_one)>
1719 guard{&data_, pop_one};
1720 named_info_.push_back({arg.name,
static_cast<int>(data_.size() - 2u)});
1721 data_[0].value_.named_args = {named_info_.data(), named_info_.size()};
1744 if (detail::const_check(need_copy<T>::value))
1745 emplace_arg(dynamic_args_.push<stored_type<T>>(arg));
1747 emplace_arg(detail::unwrap(arg));
1772 template <
typename T>
void push_back(std::reference_wrapper<T> arg) {
1775 need_copy<T>::value,
1776 "objects of built-in types and string views are always copied");
1777 emplace_arg(arg.get());
1785 template <
typename T>
1787 const char_type* arg_name =
1788 dynamic_args_.push<std::basic_string<char_type>>(arg.name).c_str();
1789 if (detail::const_check(need_copy<T>::value)) {
1791 fmt::arg(arg_name, dynamic_args_.push<stored_type<T>>(arg.value)));
1793 emplace_arg(fmt::arg(arg_name, arg.value));
1800 named_info_.clear();
1810 void reserve(
size_t new_cap,
size_t new_cap_named) {
1811 FMT_ASSERT(new_cap >= new_cap_named,
1812 "Set of arguments includes set of named arguments");
1813 data_.reserve(new_cap);
1814 named_info_.reserve(new_cap_named);
1830 using size_type = int;
1838 unsigned long long desc_;
1846 const format_arg* args_;
1849 bool is_packed()
const {
return (desc_ & detail::is_unpacked_bit) == 0; }
1850 bool has_named_args()
const {
1851 return (desc_ & detail::has_named_args_bit) != 0;
1854 detail::type type(
int index)
const {
1855 int shift = index * detail::packed_arg_bits;
1856 unsigned int mask = (1 << detail::packed_arg_bits) - 1;
1857 return static_cast<detail::type
>((desc_ >> shift) & mask);
1862 : desc_(desc), values_(values) {}
1864 : desc_(desc), args_(args) {}
1874 template <
typename... Args>
1876 : basic_format_args(store.desc, store.data_.args()) {}
1885 : basic_format_args(store.get_types(), store.data()) {}
1900 if (
id < max_size()) arg = args_[
id];
1903 if (
id >= detail::max_packed_args)
return arg;
1904 arg.type_ = type(
id);
1905 if (arg.type_ == detail::type::none_type)
return arg;
1906 arg.value_ = values_[id];
1911 int id = get_id(name);
1916 if (!has_named_args())
return -1;
1917 const auto& named_args =
1918 (is_packed() ? values_[-1] : args_[-1].value_).named_args;
1919 for (
size_t i = 0; i < named_args.size; ++i) {
1920 if (named_args.data[i].name == name)
return named_args.data[i].id;
1925 int max_size()
const {
1926 unsigned long long max_packed = detail::max_packed_args;
1927 return static_cast<int>(is_packed() ? max_packed
1928 : desc_ & ~detail::is_unpacked_bit);
1932 #ifdef FMT_ARM_ABI_COMPATIBILITY 1942 template <
typename... Args>
1946 using basic_format_args::basic_format_args;
1952 template <typename Char, FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
1953 std::basic_string<Char> vformat(
1959 template <
typename Char>
1965 template <
typename Char,
typename Args,
1966 FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
1978 template <
typename OutputIt,
typename S,
typename Char =
char_t<S>,
1979 bool enable = detail::is_output_iterator<OutputIt, Char>::value>
1980 auto vformat_to(OutputIt out,
const S& format_str,
1982 ->
typename std::enable_if<enable, OutputIt>::type {
1983 decltype(detail::get_buffer<Char>(out)) buf(detail::get_buffer_init(out));
1984 detail::vformat_to(buf, to_string_view(format_str), args);
1985 return detail::get_iterator(buf);
2000 template <
typename OutputIt,
typename S,
typename... Args,
2002 inline auto format_to(OutputIt out,
const S& format_str, Args&&... args) ->
2003 typename std::enable_if<enable, OutputIt>::type {
2004 const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
2005 return vformat_to(out, to_string_view(format_str), vargs);
2015 template <
typename OutputIt,
typename Char,
typename... Args,
2022 detail::vformat_to(buf, format_str, args);
2023 return {buf.out(), buf.count()};
2033 template <
typename OutputIt,
typename S,
typename... Args,
2035 inline auto format_to_n(OutputIt out,
size_t n,
const S& format_str,
2036 const Args&... args) ->
2037 typename std::enable_if<enable, format_to_n_result<OutputIt>>::type {
2038 const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
2039 return vformat_to_n(out, n, to_string_view(format_str), vargs);
2046 template <
typename... Args>
2047 inline size_t formatted_size(
string_view format_str, Args&&... args) {
2048 const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
2050 detail::vformat_to(buf, format_str, vargs);
2054 template <
typename S,
typename Char =
char_t<S>>
2055 FMT_INLINE std::basic_string<Char> vformat(
2056 const S& format_str,
2058 return detail::vformat(to_string_view(format_str), args);
2073 template <
typename S,
typename... Args,
typename Char = char_t<S>>
2074 FMT_INLINE std::basic_string<Char> format(
const S& format_str, Args&&... args) {
2075 const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
2076 return detail::vformat(to_string_view(format_str), vargs);
2093 template <
typename S,
typename... Args,
typename Char = char_t<S>>
2094 inline void print(std::FILE* f,
const S& format_str, Args&&... args) {
2095 const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
2096 return detail::is_unicode<Char>()
2097 ? vprint(f, to_string_view(format_str), vargs)
2098 : detail::vprint_mojibake(f, to_string_view(format_str), vargs);
2112 template <
typename S,
typename... Args,
typename Char = char_t<S>>
2113 inline void print(
const S& format_str, Args&&... args) {
2114 const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
2115 return detail::is_unicode<Char>()
2116 ? vprint(to_string_view(format_str), vargs)
2117 : detail::vprint_mojibake(stdout, to_string_view(format_str),
2122 #endif // FMT_CORE_H_
FMT_CONSTEXPR basic_string_view(const std::basic_string< Char, Traits, Alloc > &s) FMT_NOEXCEPT
Constructs a string reference from a std::basic_string object.
Definition: core.h:385
basic_format_context(OutputIt out, basic_format_args< basic_format_context > ctx_args, detail::locale_ref loc=detail::locale_ref())
Constructs a basic_format_context object.
Definition: core.h:1512
FMT_CONSTEXPR void advance_to(iterator it)
Advances the begin iterator to it.
Definition: core.h:585
Definition: blocking.hpp:208
constexpr const Char * data() const
Returns a pointer to the string data.
Definition: core.h:396
constexpr iterator end() const FMT_NOEXCEPT
Returns an iterator past the end of the format string range being parsed.
Definition: core.h:582
void grow(size_t) final FMT_OVERRIDE
Increases the buffer capacity to hold at least capacity elements.
Definition: core.h:841
size_t size() const FMT_NOEXCEPT
Returns the size of this buffer.
Definition: core.h:706
Definition: awaitable.hpp:421
const T * data() const FMT_NOEXCEPT
Returns a pointer to the buffer data.
Definition: core.h:715
basic_string_view(const Char *s)
Constructs a string reference object from a C string computing the size with std::char_traits<Char>::...
Definition: core.h:380
void grow(size_t) final FMT_OVERRIDE
Increases the buffer capacity to hold at least capacity elements.
Definition: core.h:779
An implementation of std::basic_string_view for pre-C++17.
Definition: core.h:355
constexpr iterator begin() const FMT_NOEXCEPT
Returns an iterator to the beginning of the format string range being parsed.
Definition: core.h:577
Char char_type
The character type for the output.
Definition: core.h:1493
void clear()
Clears this buffer.
Definition: core.h:718
void grow(size_t capacity) final FMT_OVERRIDE
Increases the buffer capacity to hold at least capacity elements.
Definition: core.h:818
ASIO_MUTABLE_BUFFER buffer(const mutable_buffer &b) ASIO_NOEXCEPT
Create a new modifiable buffer from an existing buffer.
Definition: buffer.hpp:909
FMT_CONSTEXPR int next_arg_id()
Reports an error if using the manual argument indexing; otherwise returns the next argument index and...
Definition: core.h:593
constexpr basic_string_view(const Char *s, size_t count) FMT_NOEXCEPT
Constructs a string reference object from a C string and a size.
Definition: core.h:367
void grow(size_t) final FMT_OVERRIDE
Increases the buffer capacity to hold at least capacity elements.
Definition: core.h:800
Parsing context consisting of a format string range being parsed and an argument counter for automati...
Definition: core.h:559
FMT_CONSTEXPR void check_arg_id(int)
Reports an error if using the automatic argument indexing; otherwise switches to the manual indexing...
Definition: core.h:605
A contiguous memory buffer with an optional growing ability.
Definition: core.h:665
Specifies if T is a character type.
Definition: core.h:444
T * data() FMT_NOEXCEPT
Returns a pointer to the buffer data.
Definition: core.h:712
constexpr size_t size() const
Returns the string size.
Definition: core.h:399
size_t capacity() const FMT_NOEXCEPT
Returns the capacity of this buffer.
Definition: core.h:709