21#define FMT_VERSION 60201
24# define FMT_HAS_FEATURE(x) __has_feature(x)
26# define FMT_HAS_FEATURE(x) 0
29#if defined(__has_include) && !defined(__INTELLISENSE__) && \
30 !(defined(__INTEL_COMPILER) && __INTEL_COMPILER < 1600)
31# define FMT_HAS_INCLUDE(x) __has_include(x)
33# define FMT_HAS_INCLUDE(x) 0
36#ifdef __has_cpp_attribute
37# define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
39# define FMT_HAS_CPP_ATTRIBUTE(x) 0
42#define FMT_HAS_CPP14_ATTRIBUTE(attribute) \
43 (__cplusplus >= 201402L && FMT_HAS_CPP_ATTRIBUTE(attribute))
45#define FMT_HAS_CPP17_ATTRIBUTE(attribute) \
46 (__cplusplus >= 201703L && FMT_HAS_CPP_ATTRIBUTE(attribute))
49# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
51# define FMT_CLANG_VERSION 0
54#if defined(__GNUC__) && !defined(__clang__)
55# define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
57# define FMT_GCC_VERSION 0
60#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
61# define FMT_HAS_GXX_CXX11 FMT_GCC_VERSION
63# define FMT_HAS_GXX_CXX11 0
67# define FMT_NVCC __NVCC__
73# define FMT_MSC_VER _MSC_VER
80#ifndef FMT_USE_CONSTEXPR
81# define FMT_USE_CONSTEXPR \
82 (FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VER >= 1910 || \
83 (FMT_GCC_VERSION >= 600 && __cplusplus >= 201402L)) && \
87# define FMT_CONSTEXPR constexpr
88# define FMT_CONSTEXPR_DECL constexpr
90# define FMT_CONSTEXPR inline
91# define FMT_CONSTEXPR_DECL
95# if FMT_HAS_FEATURE(cxx_override) || \
96 (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900
97# define FMT_OVERRIDE override
104#ifndef FMT_EXCEPTIONS
105# if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || \
106 FMT_MSC_VER && !_HAS_EXCEPTIONS
107# define FMT_EXCEPTIONS 0
109# define FMT_EXCEPTIONS 1
114#ifndef FMT_USE_NOEXCEPT
115# define FMT_USE_NOEXCEPT 0
118#if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \
119 (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900
120# define FMT_DETECTED_NOEXCEPT noexcept
121# define FMT_HAS_CXX11_NOEXCEPT 1
123# define FMT_DETECTED_NOEXCEPT throw()
124# define FMT_HAS_CXX11_NOEXCEPT 0
128# if FMT_EXCEPTIONS || FMT_HAS_CXX11_NOEXCEPT
129# define FMT_NOEXCEPT FMT_DETECTED_NOEXCEPT
137#if FMT_EXCEPTIONS && FMT_HAS_CPP_ATTRIBUTE(noreturn) && !FMT_MSC_VER && \
139# define FMT_NORETURN [[noreturn]]
144#ifndef FMT_MAYBE_UNUSED
145# if FMT_HAS_CPP17_ATTRIBUTE(maybe_unused)
146# define FMT_MAYBE_UNUSED [[maybe_unused]]
148# define FMT_MAYBE_UNUSED
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(__clang__)
157# define FMT_DEPRECATED __attribute__((deprecated))
159# define FMT_DEPRECATED __declspec(deprecated)
161# define FMT_DEPRECATED
167#if defined(__INTEL_COMPILER) || defined(__PGI) || FMT_NVCC
168# define FMT_DEPRECATED_ALIAS
170# define FMT_DEPRECATED_ALIAS FMT_DEPRECATED
173#ifndef FMT_BEGIN_NAMESPACE
174# if FMT_HAS_FEATURE(cxx_inline_namespaces) || FMT_GCC_VERSION >= 404 || \
176# define FMT_INLINE_NAMESPACE inline namespace
177# define FMT_END_NAMESPACE \
181# define FMT_INLINE_NAMESPACE namespace
182# define FMT_END_NAMESPACE \
184 using namespace v6; \
187# define FMT_BEGIN_NAMESPACE \
189 FMT_INLINE_NAMESPACE v6 {
192#if !defined(FMT_HEADER_ONLY) && defined(_WIN32)
194# define FMT_NO_W4275 __pragma(warning(suppress : 4275))
198# define FMT_CLASS_API FMT_NO_W4275
200# define FMT_API __declspec(dllexport)
201# elif defined(FMT_SHARED)
202# define FMT_API __declspec(dllimport)
203# define FMT_EXTERN_TEMPLATE_API FMT_API
207# define FMT_CLASS_API
210# if FMT_GCC_VERSION || FMT_CLANG_VERSION
211# define FMT_API __attribute__((visibility("default")))
212# define FMT_EXTERN_TEMPLATE_API FMT_API
213# define FMT_INSTANTIATION_DEF_API
218#ifndef FMT_EXTERN_TEMPLATE_API
219# define FMT_EXTERN_TEMPLATE_API
221#ifndef FMT_INSTANTIATION_DEF_API
222# define FMT_INSTANTIATION_DEF_API FMT_API
225#ifndef FMT_HEADER_ONLY
226# define FMT_EXTERN extern
232#if (FMT_HAS_INCLUDE(<string_view>) && \
233 (__cplusplus > 201402L || defined(_LIBCPP_VERSION))) || \
234 (defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910)
235# include <string_view>
236# define FMT_USE_STRING_VIEW
237#elif FMT_HAS_INCLUDE("experimental/string_view") && __cplusplus >= 201402L
238# include <experimental/string_view>
239# define FMT_USE_EXPERIMENTAL_STRING_VIEW
243# define FMT_UNICODE !FMT_MSC_VER
245#if FMT_UNICODE && FMT_MSC_VER
246# pragma execution_character_set("utf-8")
252template <
bool B,
class T =
void>
253using enable_if_t =
typename std::enable_if<B, T>::type;
254template <
bool B,
class T,
class F>
255using conditional_t =
typename std::conditional<B, T, F>::type;
256template <
bool B>
using bool_constant = std::integral_constant<bool, B>;
258using remove_reference_t =
typename std::remove_reference<T>::type;
260using remove_const_t =
typename std::remove_const<T>::type;
262using remove_cvref_t =
typename std::remove_cv<remove_reference_t<T>>::type;
263template <
typename T>
struct type_identity {
using type = T; };
264template <
typename T>
using type_identity_t =
typename type_identity<T>::type;
271#define FMT_ENABLE_IF(...) enable_if_t<(__VA_ARGS__), int> = 0
277template <
typename T> FMT_CONSTEXPR T const_check(T value) {
return value; }
280template <
typename... Ts>
struct void_t_impl {
using type = void; };
282FMT_NORETURN FMT_API
void assert_fail(
const char* file,
int line,
283 const char* message);
288# define FMT_ASSERT(condition, message) ((void)0)
290# define FMT_ASSERT(condition, message) \
293 : ::fmt::internal::assert_fail(__FILE__, __LINE__, (message)))
297#if defined(FMT_USE_STRING_VIEW)
298template <
typename Char>
using std_string_view = std::basic_string_view<Char>;
299#elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW)
300template <
typename Char>
301using std_string_view = std::experimental::basic_string_view<Char>;
303template <
typename T>
struct std_string_view {};
308#elif defined(__SIZEOF_INT128__) && !FMT_NVCC
309# define FMT_USE_INT128 1
310using int128_t = __int128_t;
311using uint128_t = __uint128_t;
313# define FMT_USE_INT128 0
321template <
typename Int>
322FMT_CONSTEXPR
typename std::make_unsigned<Int>::type to_unsigned(Int value) {
323 FMT_ASSERT(value >= 0,
"negative value");
324 return static_cast<typename std::make_unsigned<Int>::type
>(value);
327constexpr unsigned char micro[] =
"\u00B5";
329template <
typename Char>
constexpr bool is_unicode() {
330 return FMT_UNICODE ||
sizeof(Char) != 1 ||
331 (
sizeof(micro) == 3 && micro[0] == 0xC2 && micro[1] == 0xB5);
335using char8_type = char8_t;
337enum char8_type :
unsigned char {};
341template <
typename... Ts>
342using void_t =
typename internal::void_t_impl<Ts...>::type;
357 using char_type FMT_DEPRECATED_ALIAS = Char;
358 using value_type = Char;
359 using iterator =
const Char*;
374#if __cplusplus >= 201703L
378 : data_(s), size_(std::char_traits<Char>::length(s)) {}
381 template <
typename Traits,
typename Alloc>
383 const std::basic_string<Char, Traits, Alloc>& s) FMT_NOEXCEPT
389 FMT_ENABLE_IF(std::is_same<S, internal::std_string_view<Char>>::value)>
394 FMT_CONSTEXPR
const Char*
data()
const {
return data_; }
397 FMT_CONSTEXPR
size_t size()
const {
return size_; }
399 FMT_CONSTEXPR iterator begin()
const {
return data_; }
400 FMT_CONSTEXPR iterator end()
const {
return data_ + size_; }
402 FMT_CONSTEXPR
const Char& operator[](
size_t pos)
const {
return data_[pos]; }
404 FMT_CONSTEXPR
void remove_prefix(
size_t n) {
411 size_t str_size = size_ < other.size_ ? size_ : other.size_;
412 int result = std::char_traits<Char>::compare(data_, other.data_, str_size);
414 result = size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1);
419 return lhs.compare(rhs) == 0;
422 return lhs.compare(rhs) != 0;
425 return lhs.compare(rhs) < 0;
428 return lhs.compare(rhs) <= 0;
431 return lhs.compare(rhs) > 0;
434 return lhs.compare(rhs) >= 0;
443using char8_t FMT_DEPRECATED_ALIAS = internal::char8_type;
447template <
typename T>
struct is_char : std::false_type {};
448template <>
struct is_char<char> : std::true_type {};
449template <>
struct is_char<wchar_t> : std::true_type {};
450template <>
struct is_char<internal::char8_type> : std::true_type {};
451template <>
struct is_char<char16_t> : std::true_type {};
452template <>
struct is_char<char32_t> : std::true_type {};
470template <
typename Char, FMT_ENABLE_IF(is_
char<Char>::value)>
475template <
typename Char,
typename Traits,
typename Alloc>
477 const std::basic_string<Char, Traits, Alloc>& s) {
481template <
typename Char>
486template <
typename Char,
487 FMT_ENABLE_IF(!std::is_empty<internal::std_string_view<Char>>::value)>
489 internal::std_string_view<Char> s) {
495struct compile_string {};
498struct is_compile_string : std::is_base_of<compile_string, S> {};
500template <
typename S, FMT_ENABLE_IF(is_compile_
string<S>::value)>
506void to_string_view(...);
507using fmt::v6::to_string_view;
513struct is_string : std::is_class<decltype(to_string_view(std::declval<S>()))> {
516template <
typename S,
typename =
void>
struct char_t_impl {};
517template <
typename S>
struct char_t_impl<S, enable_if_t<is_string<S>::value>> {
518 using result =
decltype(to_string_view(std::declval<S>()));
519 using type =
typename result::value_type;
522struct error_handler {
523 FMT_CONSTEXPR error_handler() =
default;
524 FMT_CONSTEXPR error_handler(
const error_handler&) =
default;
527 FMT_NORETURN FMT_API
void on_error(
const char* message);
532template <
typename S>
using char_t =
typename internal::char_t_impl<S>::type;
550template <
typename Char,
typename ErrorHandler =
internal::error_handler>
557 using char_type = Char;
558 using iterator =
typename basic_string_view<Char>::iterator;
562 : ErrorHandler(eh), format_str_(format_str), next_arg_id_(0) {}
568 FMT_CONSTEXPR iterator
begin() const FMT_NOEXCEPT {
569 return format_str_.begin();
575 FMT_CONSTEXPR iterator
end() const FMT_NOEXCEPT {
return format_str_.end(); }
579 format_str_.remove_prefix(internal::to_unsigned(it -
begin()));
587 if (next_arg_id_ >= 0)
return next_arg_id_++;
588 on_error(
"cannot switch from manual to automatic argument indexing");
597 if (next_arg_id_ > 0)
598 on_error(
"cannot switch from automatic to manual argument indexing");
605 FMT_CONSTEXPR
void on_error(
const char* message) {
606 ErrorHandler::on_error(message);
609 FMT_CONSTEXPR ErrorHandler error_handler()
const {
return *
this; }
615template <
typename Char,
typename ErrorHandler =
internal::error_handler>
616using basic_parse_context FMT_DEPRECATED_ALIAS =
621template <
typename Context>
class basic_format_arg;
625template <
typename T,
typename Char =
char,
typename Enable =
void>
628 formatter() =
delete;
631template <
typename T,
typename Char,
typename Enable =
void>
632struct FMT_DEPRECATED convert_to_int
633 : bool_constant<!std::is_arithmetic<T>::value &&
634 std::is_convertible<T, int>::value> {};
638template <
typename T,
typename Context>
640 std::is_constructible<typename Context::template formatter_type<T>>;
649 std::size_t capacity_;
653 buffer(std::size_t sz) FMT_NOEXCEPT : size_(sz), capacity_(sz) {}
655 buffer(T* p =
nullptr, std::size_t sz = 0, std::size_t cap = 0) FMT_NOEXCEPT
661 void set(T* buf_data, std::size_t buf_capacity) FMT_NOEXCEPT {
663 capacity_ = buf_capacity;
670 using value_type = T;
671 using const_reference =
const T&;
674 void operator=(
const buffer&) =
delete;
677 T* begin() FMT_NOEXCEPT {
return ptr_; }
678 T* end() FMT_NOEXCEPT {
return ptr_ + size_; }
680 const T* begin() const FMT_NOEXCEPT {
return ptr_; }
681 const T* end() const FMT_NOEXCEPT {
return ptr_ + size_; }
684 std::size_t
size() const FMT_NOEXCEPT {
return size_; }
687 std::size_t
capacity() const FMT_NOEXCEPT {
return capacity_; }
690 T*
data() FMT_NOEXCEPT {
return ptr_; }
693 const T*
data() const FMT_NOEXCEPT {
return ptr_; }
708 if (new_capacity > capacity_)
grow(new_capacity);
711 void push_back(
const T& value) {
713 ptr_[size_++] = value;
717 template <
typename U>
void append(
const U* begin,
const U* end);
719 template <
typename I> T& operator[](I index) {
return ptr_[index]; }
720 template <
typename I>
const T& operator[](I index)
const {
726template <
typename Container>
727class container_buffer :
public buffer<typename Container::value_type> {
729 Container& container_;
732 void grow(std::size_t
capacity) FMT_OVERRIDE {
738 explicit container_buffer(Container& c)
739 : buffer<typename Container::value_type>(c.
size()), container_(c) {}
743template <
typename Container>
744inline Container& get_container(std::back_insert_iterator<Container> it) {
745 using bi_iterator = std::back_insert_iterator<Container>;
746 struct accessor : bi_iterator {
747 accessor(bi_iterator iter) : bi_iterator(iter) {}
748 using bi_iterator::container;
750 return *accessor(it).container;
753template <
typename T,
typename Char =
char,
typename Enable =
void>
754struct fallback_formatter {
755 fallback_formatter() =
delete;
759template <
typename T,
typename Context>
760using has_fallback_formatter =
761 std::is_constructible<fallback_formatter<T, typename Context::char_type>>;
763template <
typename Char>
struct named_arg_base;
764template <
typename T,
typename Char>
struct named_arg;
778 last_integer_type = char_type,
783 last_numeric_type = long_double_type,
791template <
typename T,
typename Char>
792struct type_constant : std::integral_constant<type, type::custom_type> {};
794#define FMT_TYPE_CONSTANT(Type, constant) \
795 template <typename Char> \
796 struct type_constant<Type, Char> \
797 : std::integral_constant<type, type::constant> {}
799FMT_TYPE_CONSTANT(
const named_arg_base<Char>&, named_arg_type);
800FMT_TYPE_CONSTANT(
int, int_type);
801FMT_TYPE_CONSTANT(
unsigned, uint_type);
802FMT_TYPE_CONSTANT(
long long, long_long_type);
803FMT_TYPE_CONSTANT(
unsigned long long, ulong_long_type);
804FMT_TYPE_CONSTANT(int128_t, int128_type);
805FMT_TYPE_CONSTANT(uint128_t, uint128_type);
806FMT_TYPE_CONSTANT(
bool, bool_type);
807FMT_TYPE_CONSTANT(Char, char_type);
808FMT_TYPE_CONSTANT(
float, float_type);
809FMT_TYPE_CONSTANT(
double, double_type);
810FMT_TYPE_CONSTANT(
long double, long_double_type);
811FMT_TYPE_CONSTANT(
const Char*, cstring_type);
813FMT_TYPE_CONSTANT(
const void*, pointer_type);
815FMT_CONSTEXPR
bool is_integral_type(type t) {
816 FMT_ASSERT(t != type::named_arg_type,
"invalid argument type");
817 return t > type::none_type && t <= type::last_integer_type;
820FMT_CONSTEXPR
bool is_arithmetic_type(type t) {
821 FMT_ASSERT(t != type::named_arg_type,
"invalid argument type");
822 return t > type::none_type && t <= type::last_numeric_type;
825template <
typename Char>
struct string_value {
830template <
typename Context>
struct custom_value {
833 void (*format)(
const void* arg,
834 typename Context::parse_context_type& parse_ctx, Context& ctx);
838template <
typename Context>
class value {
840 using char_type =
typename Context::char_type;
845 long long long_long_value;
846 unsigned long long ulong_long_value;
847 int128_t int128_value;
848 uint128_t uint128_value;
850 char_type char_value;
853 long double long_double_value;
855 string_value<char_type> string;
856 custom_value<Context> custom;
857 const named_arg_base<char_type>* named_arg;
860 FMT_CONSTEXPR value(
int val = 0) : int_value(val) {}
861 FMT_CONSTEXPR value(
unsigned val) : uint_value(val) {}
862 value(
long long val) : long_long_value(val) {}
863 value(
unsigned long long val) : ulong_long_value(val) {}
864 value(int128_t val) : int128_value(val) {}
865 value(uint128_t val) : uint128_value(val) {}
866 value(
float val) : float_value(val) {}
867 value(
double val) : double_value(val) {}
868 value(
long double val) : long_double_value(val) {}
869 value(
bool val) : bool_value(val) {}
870 value(char_type val) : char_value(val) {}
871 value(
const char_type* val) {
string.data = val; }
873 string.data = val.
data();
874 string.size = val.
size();
876 value(
const void* val) : pointer(val) {}
878 template <
typename T> value(
const T& val) {
883 custom.format = format_custom_arg<
884 T, conditional_t<has_formatter<T, Context>::value,
885 typename Context::template formatter_type<T>,
886 fallback_formatter<T, char_type>>>;
889 value(
const named_arg_base<char_type>& val) { named_arg = &val; }
893 template <
typename T,
typename Formatter>
894 static void format_custom_arg(
const void* arg,
895 typename Context::parse_context_type& parse_ctx,
898 parse_ctx.advance_to(f.parse(parse_ctx));
899 ctx.advance_to(f.format(*
static_cast<const T*
>(arg), ctx));
903template <
typename Context,
typename T>
904FMT_CONSTEXPR basic_format_arg<Context> make_arg(
const T& value);
908enum { long_short =
sizeof(long) ==
sizeof(
int) };
909using long_type = conditional_t<long_short, int, long long>;
910using ulong_type = conditional_t<long_short, unsigned, unsigned long long>;
913template <
typename Context>
struct arg_mapper {
914 using char_type =
typename Context::char_type;
916 FMT_CONSTEXPR
int map(
signed char val) {
return val; }
917 FMT_CONSTEXPR
unsigned map(
unsigned char val) {
return val; }
918 FMT_CONSTEXPR
int map(
short val) {
return val; }
919 FMT_CONSTEXPR
unsigned map(
unsigned short val) {
return val; }
920 FMT_CONSTEXPR
int map(
int val) {
return val; }
921 FMT_CONSTEXPR
unsigned map(
unsigned val) {
return val; }
922 FMT_CONSTEXPR long_type map(
long val) {
return val; }
923 FMT_CONSTEXPR ulong_type map(
unsigned long val) {
return val; }
924 FMT_CONSTEXPR
long long map(
long long val) {
return val; }
925 FMT_CONSTEXPR
unsigned long long map(
unsigned long long val) {
return val; }
926 FMT_CONSTEXPR int128_t map(int128_t val) {
return val; }
927 FMT_CONSTEXPR uint128_t map(uint128_t val) {
return val; }
928 FMT_CONSTEXPR
bool map(
bool val) {
return val; }
930 template <
typename T, FMT_ENABLE_IF(is_
char<T>::value)>
931 FMT_CONSTEXPR char_type map(T val) {
933 std::is_same<T, char>::value || std::is_same<T, char_type>::value,
934 "mixing character types is disallowed");
938 FMT_CONSTEXPR
float map(
float val) {
return val; }
939 FMT_CONSTEXPR
double map(
double val) {
return val; }
940 FMT_CONSTEXPR
long double map(
long double val) {
return val; }
942 FMT_CONSTEXPR
const char_type* map(char_type* val) {
return val; }
943 FMT_CONSTEXPR
const char_type* map(
const char_type* val) {
return val; }
944 template <
typename T, FMT_ENABLE_IF(is_
string<T>::value)>
946 static_assert(std::is_same<char_type, char_t<T>>::value,
947 "mixing character types is disallowed");
948 return to_string_view(val);
950 template <
typename T,
953 !is_string<T>::value && !has_formatter<T, Context>::value &&
954 !has_fallback_formatter<T, Context>::value)>
961 std::is_constructible<std_string_view<char_type>, T>::value &&
963 !is_string<T>::value && !has_formatter<T, Context>::value &&
964 !has_fallback_formatter<T, Context>::value)>
966 return std_string_view<char_type>(val);
968 FMT_CONSTEXPR
const char* map(
const signed char* val) {
969 static_assert(std::is_same<char_type, char>::value,
"invalid string type");
970 return reinterpret_cast<const char*
>(val);
972 FMT_CONSTEXPR
const char* map(
const unsigned char* val) {
973 static_assert(std::is_same<char_type, char>::value,
"invalid string type");
974 return reinterpret_cast<const char*
>(val);
977 FMT_CONSTEXPR
const void* map(
void* val) {
return val; }
978 FMT_CONSTEXPR
const void* map(
const void* val) {
return val; }
979 FMT_CONSTEXPR
const void* map(std::nullptr_t val) {
return val; }
980 template <
typename T> FMT_CONSTEXPR
int map(
const T*) {
985 static_assert(!
sizeof(T),
"formatting of non-void pointers is disallowed");
989 template <
typename T,
990 FMT_ENABLE_IF(std::is_enum<T>::value &&
991 !has_formatter<T, Context>::value &&
992 !has_fallback_formatter<T, Context>::value)>
993 FMT_CONSTEXPR
auto map(
const T& val)
994 ->
decltype(std::declval<arg_mapper>().map(
995 static_cast<typename std::underlying_type<T>::type
>(val))) {
996 return map(
static_cast<typename std::underlying_type<T>::type
>(val));
998 template <
typename T,
1000 (has_formatter<T, Context>::value ||
1001 has_fallback_formatter<T, Context>::value))>
1002 FMT_CONSTEXPR
const T& map(
const T& val) {
1006 template <
typename T>
1007 FMT_CONSTEXPR
const named_arg_base<char_type>& map(
1008 const named_arg<T, char_type>& val) {
1009 auto arg = make_arg<Context>(val.value);
1010 std::memcpy(val.data, &arg,
sizeof(arg));
1015 constexpr bool formattable =
sizeof(Context) == 0;
1018 "Cannot format argument. To make type T formattable provide a "
1019 "formatter<T> specialization: "
1020 "https://fmt.dev/latest/api.html#formatting-user-defined-types");
1026template <
typename T,
typename Context>
1027using mapped_type_constant =
1028 type_constant<decltype(arg_mapper<Context>().map(std::declval<const T&>())),
1029 typename Context::char_type>;
1031enum { packed_arg_bits = 5 };
1033enum { max_packed_args = 63 / packed_arg_bits };
1034enum :
unsigned long long { is_unpacked_bit = 1ULL << 63 };
1036template <
typename Context>
class arg_map;
1041template <
typename Context>
class basic_format_arg {
1043 internal::value<Context> value_;
1044 internal::type type_;
1046 template <
typename ContextType,
typename T>
1047 friend FMT_CONSTEXPR basic_format_arg<ContextType> internal::make_arg(
1050 template <
typename Visitor,
typename Ctx>
1051 friend FMT_CONSTEXPR
auto visit_format_arg(Visitor&& vis,
1052 const basic_format_arg<Ctx>& arg)
1053 ->
decltype(vis(0));
1056 friend class internal::arg_map<Context>;
1058 using char_type =
typename Context::char_type;
1063 explicit handle(internal::custom_value<Context> custom) : custom_(custom) {}
1065 void format(
typename Context::parse_context_type& parse_ctx,
1066 Context& ctx)
const {
1067 custom_.format(custom_.value, parse_ctx, ctx);
1071 internal::custom_value<Context> custom_;
1074 FMT_CONSTEXPR basic_format_arg() : type_(internal::type::none_type) {}
1076 FMT_CONSTEXPR
explicit operator bool() const FMT_NOEXCEPT {
1077 return type_ != internal::type::none_type;
1080 internal::type type()
const {
return type_; }
1082 bool is_integral()
const {
return internal::is_integral_type(type_); }
1083 bool is_arithmetic()
const {
return internal::is_arithmetic_type(type_); }
1093template <
typename Visitor,
typename Context>
1094FMT_CONSTEXPR
auto visit_format_arg(Visitor&& vis,
1095 const basic_format_arg<Context>& arg)
1096 ->
decltype(vis(0)) {
1097 using char_type =
typename Context::char_type;
1098 switch (arg.type_) {
1099 case internal::type::none_type:
1101 case internal::type::named_arg_type:
1102 FMT_ASSERT(
false,
"invalid argument type");
1104 case internal::type::int_type:
1105 return vis(arg.value_.int_value);
1106 case internal::type::uint_type:
1107 return vis(arg.value_.uint_value);
1108 case internal::type::long_long_type:
1109 return vis(arg.value_.long_long_value);
1110 case internal::type::ulong_long_type:
1111 return vis(arg.value_.ulong_long_value);
1113 case internal::type::int128_type:
1114 return vis(arg.value_.int128_value);
1115 case internal::type::uint128_type:
1116 return vis(arg.value_.uint128_value);
1118 case internal::type::int128_type:
1119 case internal::type::uint128_type:
1122 case internal::type::bool_type:
1123 return vis(arg.value_.bool_value);
1124 case internal::type::char_type:
1125 return vis(arg.value_.char_value);
1126 case internal::type::float_type:
1127 return vis(arg.value_.float_value);
1128 case internal::type::double_type:
1129 return vis(arg.value_.double_value);
1130 case internal::type::long_double_type:
1131 return vis(arg.value_.long_double_value);
1132 case internal::type::cstring_type:
1133 return vis(arg.value_.string.data);
1134 case internal::type::string_type:
1136 arg.value_.string.size));
1137 case internal::type::pointer_type:
1138 return vis(arg.value_.pointer);
1139 case internal::type::custom_type:
1140 return vis(
typename basic_format_arg<Context>::handle(arg.value_.custom));
1142 return vis(monostate());
1147template <
typename Context>
class arg_map {
1149 using char_type =
typename Context::char_type;
1153 basic_format_arg<Context> arg;
1159 void push_back(value<Context> val) {
1160 const auto& named = *val.named_arg;
1161 map_[size_] = {named.name, named.template deserialize<Context>()};
1166 arg_map(
const arg_map&) =
delete;
1167 void operator=(
const arg_map&) =
delete;
1168 arg_map() : map_(nullptr), size_(0) {}
1170 ~arg_map() {
delete[] map_; }
1174 for (entry *it = map_, *end = map_ + size_; it != end; ++it) {
1175 if (it->name == name)
return it->arg;
1184 const void* locale_;
1187 locale_ref() : locale_(nullptr) {}
1188 template <
typename Locale>
explicit locale_ref(
const Locale& loc);
1190 explicit operator bool() const FMT_NOEXCEPT {
return locale_ !=
nullptr; }
1192 template <
typename Locale> Locale get()
const;
1195template <
typename>
constexpr unsigned long long encode_types() {
return 0; }
1197template <
typename Context,
typename Arg,
typename... Args>
1198constexpr unsigned long long encode_types() {
1199 return static_cast<unsigned>(mapped_type_constant<Arg, Context>::value) |
1200 (encode_types<Context, Args...>() << packed_arg_bits);
1203template <
typename Context,
typename T>
1204FMT_CONSTEXPR basic_format_arg<Context> make_arg(
const T& value) {
1205 basic_format_arg<Context> arg;
1206 arg.type_ = mapped_type_constant<T, Context>::value;
1207 arg.value_ = arg_mapper<Context>().map(value);
1214template <
bool IS_PACKED,
typename Context, type,
typename T,
1215 FMT_ENABLE_IF(IS_PACKED)>
1216inline value<Context> make_arg(
const T& val) {
1217 return arg_mapper<Context>().map(val);
1220template <
bool IS_PACKED,
typename Context, type,
typename T,
1221 FMT_ENABLE_IF(!IS_PACKED)>
1222inline basic_format_arg<Context> make_arg(
const T& value) {
1223 return make_arg<Context>(value);
1226template <
typename T>
struct is_reference_wrapper : std::false_type {};
1228template <
typename T>
1229struct is_reference_wrapper<std::reference_wrapper<T>> : std::true_type {};
1231class dynamic_arg_list {
1235 template <
typename =
void>
struct node {
1236 virtual ~node() =
default;
1237 std::unique_ptr<node<>> next;
1240 template <
typename T>
struct typed_node : node<> {
1243 template <
typename Arg>
1244 FMT_CONSTEXPR typed_node(
const Arg& arg) : value(arg) {}
1246 template <
typename Char>
1248 : value(arg.data(), arg.size()) {}
1251 std::unique_ptr<node<>> head_;
1254 template <
typename T,
typename Arg>
const T& push(
const Arg& arg) {
1255 auto node = std::unique_ptr<typed_node<T>>(
new typed_node<T>(arg));
1256 auto& value = node->value;
1257 node->next = std::move(head_);
1258 head_ = std::move(node);
1265template <
typename OutputIt,
typename Char>
class basic_format_context {
1268 using char_type = Char;
1273 internal::arg_map<basic_format_context> map_;
1274 internal::locale_ref loc_;
1277 using iterator = OutputIt;
1278 using format_arg = basic_format_arg<basic_format_context>;
1280 template <
typename T>
using formatter_type = formatter<T, char_type>;
1282 basic_format_context(
const basic_format_context&) =
delete;
1283 void operator=(
const basic_format_context&) =
delete;
1288 basic_format_context(OutputIt out,
1290 internal::locale_ref loc = internal::locale_ref())
1291 : out_(out), args_(ctx_args), loc_(loc) {}
1293 format_arg arg(
int id)
const {
return args_.
get(
id); }
1299 internal::error_handler error_handler() {
return {}; }
1300 void on_error(
const char* message) { error_handler().on_error(message); }
1303 iterator out() {
return out_; }
1306 void advance_to(iterator it) { out_ = it; }
1308 internal::locale_ref locale() {
return loc_; }
1311template <
typename Char>
1312using buffer_context =
1313 basic_format_context<std::back_insert_iterator<internal::buffer<Char>>,
1315using format_context = buffer_context<char>;
1316using wformat_context = buffer_context<wchar_t>;
1325template <
typename Context,
typename... Args>
1327#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
1333 static const size_t num_args =
sizeof...(Args);
1334 static const bool is_packed = num_args < internal::max_packed_args;
1336 using value_type = conditional_t<is_packed, internal::value<Context>,
1337 basic_format_arg<Context>>;
1340 value_type data_[num_args + (num_args == 0 ? 1 : 0)];
1345 static constexpr unsigned long long types =
1346 is_packed ? internal::encode_types<Context, Args...>()
1347 : internal::is_unpacked_bit | num_args;
1351#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
1354 data_{internal::make_arg<
1356 internal::mapped_type_constant<Args, Context>::value>(args)...} {
1368template <
typename Context = format_context,
typename... Args>
1370 const Args&... args) {
1384template <
typename Context>
1386#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
1392 using char_type =
typename Context::char_type;
1394 template <
typename T>
struct need_copy {
1395 static constexpr internal::type mapped_type =
1396 internal::mapped_type_constant<T, Context>::value;
1399 value = !(internal::is_reference_wrapper<T>::value ||
1400 std::is_same<T, basic_string_view<char_type>>::value ||
1401 std::is_same<T, internal::std_string_view<char_type>>::value ||
1402 (mapped_type != internal::type::cstring_type &&
1403 mapped_type != internal::type::string_type &&
1404 mapped_type != internal::type::custom_type &&
1405 mapped_type != internal::type::named_arg_type))
1409 template <
typename T>
1410 using stored_type = conditional_t<internal::is_string<T>::value,
1411 std::basic_string<char_type>, T>;
1414 std::vector<basic_format_arg<Context>> data_;
1418 internal::dynamic_arg_list dynamic_args_;
1422 unsigned long long get_types()
const {
1423 return internal::is_unpacked_bit | data_.size();
1426 template <
typename T>
void emplace_arg(
const T& arg) {
1427 data_.emplace_back(internal::make_arg<Context>(arg));
1450 !std::is_base_of<internal::named_arg_base<char_type>, T>::value,
1451 "named arguments are not supported yet");
1452 if (internal::const_check(need_copy<T>::value))
1453 emplace_arg(dynamic_args_.push<stored_type<T>>(arg));
1462 template <
typename T>
void push_back(std::reference_wrapper<T> arg) {
1464 need_copy<T>::value,
1465 "objects of built-in types and string views are always copied");
1466 emplace_arg(arg.get());
1482 using size_type = int;
1483 using format_arg = basic_format_arg<Context>;
1488 unsigned long long types_;
1495 const internal::value<Context>* values_;
1496 const format_arg* args_;
1499 bool is_packed()
const {
return (types_ & internal::is_unpacked_bit) == 0; }
1501 internal::type type(
int index)
const {
1502 int shift = index * internal::packed_arg_bits;
1503 unsigned int mask = (1 << internal::packed_arg_bits) - 1;
1504 return static_cast<internal::type
>((types_ >> shift) & mask);
1507 friend class internal::arg_map<Context>;
1509 void set_data(
const internal::value<Context>* values) { values_ = values; }
1510 void set_data(
const format_arg* args) { args_ = args; }
1512 format_arg do_get(
int index)
const {
1515 auto num_args = max_size();
1516 if (index < num_args) arg = args_[index];
1519 if (index > internal::max_packed_args)
return arg;
1520 arg.type_ = type(index);
1521 if (arg.type_ == internal::type::none_type)
return arg;
1522 internal::value<Context>& val = arg.value_;
1523 val = values_[index];
1535 template <
typename... Args>
1537 : types_(store.types) {
1538 set_data(store.data_);
1548 : types_(store.get_types()) {
1549 set_data(store.data_.data());
1558 : types_(internal::is_unpacked_bit | internal::to_unsigned(count)) {
1563 format_arg
get(
int index)
const {
1564 format_arg arg = do_get(index);
1565 if (arg.type_ == internal::type::named_arg_type)
1566 arg = arg.value_.named_arg->template deserialize<Context>();
1570 int max_size()
const {
1571 unsigned long long max_packed = internal::max_packed_args;
1572 return static_cast<int>(is_packed() ? max_packed
1573 : types_ & ~internal::is_unpacked_bit);
1580 template <
typename... Args>
1585 template <
typename... Args>
1586 wformat_args(Args&&... args)
1590template <
typename Container>
struct is_contiguous : std::false_type {};
1592template <
typename Char>
1593struct is_contiguous<std::basic_string<Char>> : std::true_type {};
1595template <
typename Char>
1596struct is_contiguous<internal::buffer<Char>> : std::true_type {};
1600template <
typename OutputIt>
1601struct is_contiguous_back_insert_iterator : std::false_type {};
1602template <
typename Container>
1603struct is_contiguous_back_insert_iterator<std::back_insert_iterator<Container>>
1604 : is_contiguous<Container> {};
1606template <
typename Char>
struct named_arg_base {
1610 mutable char data[
sizeof(basic_format_arg<buffer_context<Char>>)];
1614 template <
typename Context> basic_format_arg<Context> deserialize()
const {
1615 basic_format_arg<Context> arg;
1616 std::memcpy(&arg, data,
sizeof(basic_format_arg<Context>));
1623template <
typename T,
typename Char>
1624struct named_arg : view, named_arg_base<Char> {
1628 : named_arg_base<Char>(name), value(val) {}
1631template <
typename...,
typename S, FMT_ENABLE_IF(!is_compile_string<S>::value)>
1632inline void check_format_string(
const S&) {
1633#if defined(FMT_ENFORCE_COMPILE_STRING)
1634 static_assert(is_compile_string<S>::value,
1635 "FMT_ENFORCE_COMPILE_STRING requires all format strings to "
1636 "utilize FMT_STRING() or fmt().");
1639template <
typename...,
typename S, FMT_ENABLE_IF(is_compile_string<S>::value)>
1640void check_format_string(S);
1642template <
bool...>
struct bool_pack;
1643template <
bool... Args>
1645 std::is_same<bool_pack<Args...,
true>, bool_pack<
true, Args...>>;
1647template <
typename... Args,
typename S,
typename Char = char_t<S>>
1649make_args_checked(
const S& format_str,
1650 const remove_reference_t<Args>&... args) {
1652 all_true<(!std::is_base_of<view, remove_reference_t<Args>>::value ||
1653 !std::is_reference<Args>::value)...>::value,
1654 "passing views as lvalues is disallowed");
1655 check_format_string<Args...>(format_str);
1659template <
typename Char>
1660std::basic_string<Char> vformat(
1664template <
typename Char>
1665typename buffer_context<Char>::iterator vformat_to(
1669template <
typename Char,
typename Args,
1670 FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
1689template <
typename S,
typename T,
typename Char =
char_t<S>>
1690inline internal::named_arg<T, Char> arg(
const S& name,
const T& arg) {
1691 static_assert(internal::is_string<S>::value,
"");
1696template <
typename S,
typename T,
typename Char>
1697void arg(S, internal::named_arg<T, Char>) =
delete;
1702template <
typename OutputIt,
typename S,
typename Char =
char_t<S>,
1704 internal::is_contiguous_back_insert_iterator<OutputIt>::value)>
1706 OutputIt out,
const S& format_str,
1708 using container = remove_reference_t<
decltype(internal::get_container(out))>;
1709 internal::container_buffer<container> buf((internal::get_container(out)));
1710 internal::vformat_to(buf, to_string_view(format_str), args);
1714template <
typename Container,
typename S,
typename... Args,
1716 is_contiguous<Container>::value&& internal::is_string<S>::value)>
1717inline std::back_insert_iterator<Container> format_to(
1718 std::back_insert_iterator<Container> out,
const S& format_str,
1720 return vformat_to(out, to_string_view(format_str),
1721 internal::make_args_checked<Args...>(format_str, args...));
1724template <
typename S,
typename Char =
char_t<S>>
1725inline std::basic_string<Char> vformat(
1726 const S& format_str,
1728 return internal::vformat(to_string_view(format_str), args);
1743template <
typename S,
typename... Args,
typename Char = char_t<S>>
1744inline std::basic_string<Char> format(
const S& format_str, Args&&... args) {
1745 return internal::vformat(
1746 to_string_view(format_str),
1747 internal::make_args_checked<Args...>(format_str, args...));
1764template <
typename S,
typename... Args,
typename Char = char_t<S>>
1765inline void print(std::FILE* f,
const S& format_str, Args&&... args) {
1766 return internal::is_unicode<Char>()
1767 ? vprint(f, to_string_view(format_str),
1768 internal::make_args_checked<Args...>(format_str, args...))
1769 : internal::vprint_mojibake(
1770 f, to_string_view(format_str),
1771 internal::make_args_checked<Args...>(format_str, args...));
1785template <
typename S,
typename... Args,
typename Char = char_t<S>>
1786inline void print(
const S& format_str, Args&&... args) {
1787 return internal::is_unicode<Char>()
1788 ? vprint(to_string_view(format_str),
1789 internal::make_args_checked<Args...>(format_str, args...))
1790 : internal::vprint_mojibake(
1791 stdout, to_string_view(format_str),
1792 internal::make_args_checked<Args...>(format_str, args...));
FMT_CONSTEXPR iterator end() const FMT_NOEXCEPT
Definition: core.h:575
FMT_CONSTEXPR iterator begin() const FMT_NOEXCEPT
Definition: core.h:568
FMT_CONSTEXPR int next_arg_id()
Definition: core.h:586
FMT_CONSTEXPR void check_arg_id(int)
Definition: core.h:596
FMT_CONSTEXPR void advance_to(iterator it)
Definition: core.h:578
FMT_CONSTEXPR basic_string_view(const std::basic_string< Char, Traits, Alloc > &s) FMT_NOEXCEPT
Definition: core.h:382
FMT_CONSTEXPR basic_string_view(const Char *s, size_t count) FMT_NOEXCEPT
Definition: core.h:364
FMT_CONSTEXPR size_t size() const
Definition: core.h:397
basic_string_view(const Char *s)
Definition: core.h:377
FMT_CONSTEXPR const Char * data() const
Definition: core.h:394
void append(const U *begin, const U *end)
Definition: format.h:557
void clear()
Definition: core.h:704
void set(T *buf_data, std::size_t buf_capacity) FMT_NOEXCEPT
Definition: core.h:661
virtual void grow(std::size_t capacity)=0
void resize(std::size_t new_size)
Definition: core.h:698
void reserve(std::size_t new_capacity)
Definition: core.h:707
std::size_t capacity() const FMT_NOEXCEPT
Definition: core.h:687
std::size_t size() const FMT_NOEXCEPT
Definition: core.h:684
const T * data() const FMT_NOEXCEPT
Definition: core.h:693
T * data() FMT_NOEXCEPT
Definition: core.h:690