|
|
@ -21,7 +21,7 @@ |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
// The fmt library version in the form major * 10000 + minor * 100 + patch. |
|
|
// The fmt library version in the form major * 10000 + minor * 100 + patch. |
|
|
#define FMT_VERSION 110200 |
|
|
|
|
|
|
|
|
#define FMT_VERSION 120100 |
|
|
|
|
|
|
|
|
// Detect compiler versions. |
|
|
// Detect compiler versions. |
|
|
#if defined(__clang__) && !defined(__ibmxl__) |
|
|
#if defined(__clang__) && !defined(__ibmxl__) |
|
|
@ -114,7 +114,9 @@ |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
// Detect consteval, C++20 constexpr extensions and std::is_constant_evaluated. |
|
|
// Detect consteval, C++20 constexpr extensions and std::is_constant_evaluated. |
|
|
#if !defined(__cpp_lib_is_constant_evaluated) |
|
|
|
|
|
|
|
|
#ifdef FMT_USE_CONSTEVAL |
|
|
|
|
|
// Use the provided definition. |
|
|
|
|
|
#elif !defined(__cpp_lib_is_constant_evaluated) |
|
|
# define FMT_USE_CONSTEVAL 0 |
|
|
# define FMT_USE_CONSTEVAL 0 |
|
|
#elif FMT_CPLUSPLUS < 201709L |
|
|
#elif FMT_CPLUSPLUS < 201709L |
|
|
# define FMT_USE_CONSTEVAL 0 |
|
|
# define FMT_USE_CONSTEVAL 0 |
|
|
@ -201,14 +203,6 @@ |
|
|
# define FMT_NODISCARD |
|
|
# define FMT_NODISCARD |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
#ifdef FMT_DEPRECATED |
|
|
|
|
|
// Use the provided definition. |
|
|
|
|
|
#elif FMT_HAS_CPP14_ATTRIBUTE(deprecated) |
|
|
|
|
|
# define FMT_DEPRECATED [[deprecated]] |
|
|
|
|
|
#else |
|
|
|
|
|
# define FMT_DEPRECATED /* deprecated */ |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if FMT_GCC_VERSION || FMT_CLANG_VERSION |
|
|
#if FMT_GCC_VERSION || FMT_CLANG_VERSION |
|
|
# define FMT_VISIBILITY(value) __attribute__((visibility(value))) |
|
|
# define FMT_VISIBILITY(value) __attribute__((visibility(value))) |
|
|
#else |
|
|
#else |
|
|
@ -242,6 +236,7 @@ FMT_PRAGMA_GCC(optimize("Og")) |
|
|
# define FMT_GCC_OPTIMIZED |
|
|
# define FMT_GCC_OPTIMIZED |
|
|
#endif |
|
|
#endif |
|
|
FMT_PRAGMA_CLANG(diagnostic push) |
|
|
FMT_PRAGMA_CLANG(diagnostic push) |
|
|
|
|
|
FMT_PRAGMA_GCC(diagnostic push) |
|
|
|
|
|
|
|
|
#ifdef FMT_ALWAYS_INLINE |
|
|
#ifdef FMT_ALWAYS_INLINE |
|
|
// Use the provided definition. |
|
|
// Use the provided definition. |
|
|
@ -260,7 +255,7 @@ FMT_PRAGMA_CLANG(diagnostic push) |
|
|
#ifndef FMT_BEGIN_NAMESPACE |
|
|
#ifndef FMT_BEGIN_NAMESPACE |
|
|
# define FMT_BEGIN_NAMESPACE \ |
|
|
# define FMT_BEGIN_NAMESPACE \ |
|
|
namespace fmt { \ |
|
|
namespace fmt { \ |
|
|
inline namespace v11 { |
|
|
|
|
|
|
|
|
inline namespace v12 { |
|
|
# define FMT_END_NAMESPACE \ |
|
|
# define FMT_END_NAMESPACE \ |
|
|
} \ |
|
|
} \ |
|
|
} |
|
|
} |
|
|
@ -356,6 +351,9 @@ template <typename T> constexpr auto max_of(T a, T b) -> T { |
|
|
return a > b ? a : b; |
|
|
return a > b ? a : b; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
FMT_NORETURN FMT_API void assert_fail(const char* file, int line, |
|
|
|
|
|
const char* message); |
|
|
|
|
|
|
|
|
namespace detail { |
|
|
namespace detail { |
|
|
// Suppresses "unused variable" warnings with the method described in |
|
|
// Suppresses "unused variable" warnings with the method described in |
|
|
// https://herbsutter.com/2009/10/18/mailbag-shutting-up-compiler-warnings/. |
|
|
// https://herbsutter.com/2009/10/18/mailbag-shutting-up-compiler-warnings/. |
|
|
@ -396,7 +394,7 @@ FMT_NORETURN FMT_API void assert_fail(const char* file, int line, |
|
|
# define FMT_ASSERT(condition, message) \ |
|
|
# define FMT_ASSERT(condition, message) \ |
|
|
((condition) /* void() fails with -Winvalid-constexpr on clang 4.0.1 */ \ |
|
|
((condition) /* void() fails with -Winvalid-constexpr on clang 4.0.1 */ \ |
|
|
? (void)0 \ |
|
|
? (void)0 \ |
|
|
: fmt::detail::assert_fail(__FILE__, __LINE__, (message))) |
|
|
|
|
|
|
|
|
: ::fmt::assert_fail(__FILE__, __LINE__, (message))) |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
#ifdef FMT_USE_INT128 |
|
|
#ifdef FMT_USE_INT128 |
|
|
@ -419,8 +417,12 @@ inline auto map(int128_opt) -> monostate { return {}; } |
|
|
inline auto map(uint128_opt) -> monostate { return {}; } |
|
|
inline auto map(uint128_opt) -> monostate { return {}; } |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
#ifndef FMT_USE_BITINT |
|
|
|
|
|
# define FMT_USE_BITINT (FMT_CLANG_VERSION >= 1500) |
|
|
|
|
|
|
|
|
#ifdef FMT_USE_BITINT |
|
|
|
|
|
// Use the provided definition. |
|
|
|
|
|
#elif FMT_CLANG_VERSION >= 1500 && !defined(__CUDACC__) |
|
|
|
|
|
# define FMT_USE_BITINT 1 |
|
|
|
|
|
#else |
|
|
|
|
|
# define FMT_USE_BITINT 0 |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
#if FMT_USE_BITINT |
|
|
#if FMT_USE_BITINT |
|
|
@ -463,12 +465,13 @@ enum { use_utf8 = !FMT_WIN32 || is_utf8_enabled }; |
|
|
static_assert(!FMT_UNICODE || use_utf8, |
|
|
static_assert(!FMT_UNICODE || use_utf8, |
|
|
"Unicode support requires compiling with /utf-8"); |
|
|
"Unicode support requires compiling with /utf-8"); |
|
|
|
|
|
|
|
|
template <typename T> constexpr const char* narrow(const T*) { return nullptr; } |
|
|
|
|
|
constexpr FMT_ALWAYS_INLINE const char* narrow(const char* s) { return s; } |
|
|
|
|
|
|
|
|
template <typename T> constexpr auto narrow(T*) -> char* { return nullptr; } |
|
|
|
|
|
constexpr FMT_ALWAYS_INLINE auto narrow(const char* s) -> const char* { |
|
|
|
|
|
return s; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
template <typename Char> |
|
|
template <typename Char> |
|
|
FMT_CONSTEXPR auto compare(const Char* s1, const Char* s2, std::size_t n) |
|
|
|
|
|
-> int { |
|
|
|
|
|
|
|
|
FMT_CONSTEXPR auto compare(const Char* s1, const Char* s2, size_t n) -> int { |
|
|
if (!is_constant_evaluated() && sizeof(Char) == 1) return memcmp(s1, s2, n); |
|
|
if (!is_constant_evaluated() && sizeof(Char) == 1) return memcmp(s1, s2, n); |
|
|
for (; n != 0; ++s1, ++s2, --n) { |
|
|
for (; n != 0; ++s1, ++s2, --n) { |
|
|
if (*s1 < *s2) return -1; |
|
|
if (*s1 < *s2) return -1; |
|
|
@ -540,7 +543,7 @@ template <typename Char> class basic_string_view { |
|
|
FMT_CONSTEXPR20 basic_string_view(const Char* s) : data_(s) { |
|
|
FMT_CONSTEXPR20 basic_string_view(const Char* s) : data_(s) { |
|
|
#if FMT_HAS_BUILTIN(__builtin_strlen) || FMT_GCC_VERSION || FMT_CLANG_VERSION |
|
|
#if FMT_HAS_BUILTIN(__builtin_strlen) || FMT_GCC_VERSION || FMT_CLANG_VERSION |
|
|
if (std::is_same<Char, char>::value && !detail::is_constant_evaluated()) { |
|
|
if (std::is_same<Char, char>::value && !detail::is_constant_evaluated()) { |
|
|
size_ = __builtin_strlen(detail::narrow(s)); // strlen is not costexpr. |
|
|
|
|
|
|
|
|
size_ = __builtin_strlen(detail::narrow(s)); // strlen is not constexpr. |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
#endif |
|
|
#endif |
|
|
@ -616,19 +619,6 @@ template <typename Char> class basic_string_view { |
|
|
|
|
|
|
|
|
using string_view = basic_string_view<char>; |
|
|
using string_view = basic_string_view<char>; |
|
|
|
|
|
|
|
|
// DEPRECATED! Will be merged with is_char and moved to detail. |
|
|
|
|
|
template <typename T> struct is_xchar : std::false_type {}; |
|
|
|
|
|
template <> struct is_xchar<wchar_t> : std::true_type {}; |
|
|
|
|
|
template <> struct is_xchar<char16_t> : std::true_type {}; |
|
|
|
|
|
template <> struct is_xchar<char32_t> : std::true_type {}; |
|
|
|
|
|
#ifdef __cpp_char8_t |
|
|
|
|
|
template <> struct is_xchar<char8_t> : std::true_type {}; |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
// Specifies if `T` is a character (code unit) type. |
|
|
|
|
|
template <typename T> struct is_char : is_xchar<T> {}; |
|
|
|
|
|
template <> struct is_char<char> : std::true_type {}; |
|
|
|
|
|
|
|
|
|
|
|
template <typename T> class basic_appender; |
|
|
template <typename T> class basic_appender; |
|
|
using appender = basic_appender<char>; |
|
|
using appender = basic_appender<char>; |
|
|
|
|
|
|
|
|
@ -781,7 +771,7 @@ class basic_specs { |
|
|
(static_cast<unsigned>(p) << precision_shift); |
|
|
(static_cast<unsigned>(p) << precision_shift); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
constexpr bool dynamic() const { |
|
|
|
|
|
|
|
|
constexpr auto dynamic() const -> bool { |
|
|
return (data_ & (width_mask | precision_mask)) != 0; |
|
|
return (data_ & (width_mask | precision_mask)) != 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -921,14 +911,50 @@ template <typename Char = char> class parse_context { |
|
|
FMT_CONSTEXPR void check_dynamic_spec(int arg_id); |
|
|
FMT_CONSTEXPR void check_dynamic_spec(int arg_id); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
#ifndef FMT_USE_LOCALE |
|
|
|
|
|
# define FMT_USE_LOCALE (FMT_OPTIMIZE_SIZE <= 1) |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
// A type-erased reference to std::locale to avoid the heavy <locale> include. |
|
|
|
|
|
class locale_ref { |
|
|
|
|
|
#if FMT_USE_LOCALE |
|
|
|
|
|
private: |
|
|
|
|
|
const void* locale_; // A type-erased pointer to std::locale. |
|
|
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
|
constexpr locale_ref() : locale_(nullptr) {} |
|
|
|
|
|
|
|
|
|
|
|
template <typename Locale, FMT_ENABLE_IF(sizeof(Locale::collate) != 0)> |
|
|
|
|
|
locale_ref(const Locale& loc) : locale_(&loc) { |
|
|
|
|
|
// Check if std::isalpha is found via ADL to reduce the chance of misuse. |
|
|
|
|
|
isalpha('x', loc); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
inline explicit operator bool() const noexcept { return locale_ != nullptr; } |
|
|
|
|
|
#endif // FMT_USE_LOCALE |
|
|
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
|
template <typename Locale> auto get() const -> Locale; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
FMT_END_EXPORT |
|
|
FMT_END_EXPORT |
|
|
|
|
|
|
|
|
namespace detail { |
|
|
namespace detail { |
|
|
|
|
|
|
|
|
|
|
|
// Specifies if `T` is a code unit type. |
|
|
|
|
|
template <typename T> struct is_code_unit : std::false_type {}; |
|
|
|
|
|
template <> struct is_code_unit<char> : std::true_type {}; |
|
|
|
|
|
template <> struct is_code_unit<wchar_t> : std::true_type {}; |
|
|
|
|
|
template <> struct is_code_unit<char16_t> : std::true_type {}; |
|
|
|
|
|
template <> struct is_code_unit<char32_t> : std::true_type {}; |
|
|
|
|
|
#ifdef __cpp_char8_t |
|
|
|
|
|
template <> struct is_code_unit<char8_t> : bool_constant<is_utf8_enabled> {}; |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
// Constructs fmt::basic_string_view<Char> from types implicitly convertible |
|
|
// Constructs fmt::basic_string_view<Char> from types implicitly convertible |
|
|
// to it, deducing Char. Explicitly convertible types such as the ones returned |
|
|
// to it, deducing Char. Explicitly convertible types such as the ones returned |
|
|
// from FMT_STRING are intentionally excluded. |
|
|
// from FMT_STRING are intentionally excluded. |
|
|
template <typename Char, FMT_ENABLE_IF(is_char<Char>::value)> |
|
|
|
|
|
|
|
|
template <typename Char, FMT_ENABLE_IF(is_code_unit<Char>::value)> |
|
|
constexpr auto to_string_view(const Char* s) -> basic_string_view<Char> { |
|
|
constexpr auto to_string_view(const Char* s) -> basic_string_view<Char> { |
|
|
return s; |
|
|
return s; |
|
|
} |
|
|
} |
|
|
@ -1057,11 +1083,11 @@ template <bool B1, bool B2, bool... Tail> constexpr auto count() -> int { |
|
|
return (B1 ? 1 : 0) + count<B2, Tail...>(); |
|
|
return (B1 ? 1 : 0) + count<B2, Tail...>(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
template <typename... Args> constexpr auto count_named_args() -> int { |
|
|
|
|
|
return count<is_named_arg<Args>::value...>(); |
|
|
|
|
|
|
|
|
template <typename... T> constexpr auto count_named_args() -> int { |
|
|
|
|
|
return count<is_named_arg<T>::value...>(); |
|
|
} |
|
|
} |
|
|
template <typename... Args> constexpr auto count_static_named_args() -> int { |
|
|
|
|
|
return count<is_static_named_arg<Args>::value...>(); |
|
|
|
|
|
|
|
|
template <typename... T> constexpr auto count_static_named_args() -> int { |
|
|
|
|
|
return count<is_static_named_arg<T>::value...>(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
template <typename Char> struct named_arg_info { |
|
|
template <typename Char> struct named_arg_info { |
|
|
@ -1069,7 +1095,7 @@ template <typename Char> struct named_arg_info { |
|
|
int id; |
|
|
int id; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
// named_args is non-const to suppress a bogus -Wmaybe-uninitalized in gcc 13. |
|
|
|
|
|
|
|
|
// named_args is non-const to suppress a bogus -Wmaybe-uninitialized in gcc 13. |
|
|
template <typename Char> |
|
|
template <typename Char> |
|
|
FMT_CONSTEXPR void check_for_duplicate(named_arg_info<Char>* named_args, |
|
|
FMT_CONSTEXPR void check_for_duplicate(named_arg_info<Char>* named_args, |
|
|
int named_arg_index, |
|
|
int named_arg_index, |
|
|
@ -1173,7 +1199,7 @@ template <typename Char> struct type_mapper { |
|
|
static auto map(ubitint<N>) |
|
|
static auto map(ubitint<N>) |
|
|
-> conditional_t<N <= 64, unsigned long long, void>; |
|
|
-> conditional_t<N <= 64, unsigned long long, void>; |
|
|
|
|
|
|
|
|
template <typename T, FMT_ENABLE_IF(is_char<T>::value)> |
|
|
|
|
|
|
|
|
template <typename T, FMT_ENABLE_IF(is_code_unit<T>::value)> |
|
|
static auto map(T) -> conditional_t< |
|
|
static auto map(T) -> conditional_t< |
|
|
std::is_same<T, char>::value || std::is_same<T, Char>::value, Char, void>; |
|
|
std::is_same<T, char>::value || std::is_same<T, Char>::value, Char, void>; |
|
|
|
|
|
|
|
|
@ -1679,12 +1705,12 @@ template <typename... T> struct arg_pack {}; |
|
|
template <typename Char, int NUM_ARGS, int NUM_NAMED_ARGS, bool DYNAMIC_NAMES> |
|
|
template <typename Char, int NUM_ARGS, int NUM_NAMED_ARGS, bool DYNAMIC_NAMES> |
|
|
class format_string_checker { |
|
|
class format_string_checker { |
|
|
private: |
|
|
private: |
|
|
type types_[max_of(1, NUM_ARGS)]; |
|
|
|
|
|
named_arg_info<Char> named_args_[max_of(1, NUM_NAMED_ARGS)]; |
|
|
|
|
|
|
|
|
type types_[max_of<size_t>(1, NUM_ARGS)]; |
|
|
|
|
|
named_arg_info<Char> named_args_[max_of<size_t>(1, NUM_NAMED_ARGS)]; |
|
|
compile_parse_context<Char> context_; |
|
|
compile_parse_context<Char> context_; |
|
|
|
|
|
|
|
|
using parse_func = auto (*)(parse_context<Char>&) -> const Char*; |
|
|
using parse_func = auto (*)(parse_context<Char>&) -> const Char*; |
|
|
parse_func parse_funcs_[max_of(1, NUM_ARGS)]; |
|
|
|
|
|
|
|
|
parse_func parse_funcs_[max_of<size_t>(1, NUM_ARGS)]; |
|
|
|
|
|
|
|
|
public: |
|
|
public: |
|
|
template <typename... T> |
|
|
template <typename... T> |
|
|
@ -1828,12 +1854,17 @@ template <typename T> class buffer { |
|
|
void |
|
|
void |
|
|
append(const U* begin, const U* end) { |
|
|
append(const U* begin, const U* end) { |
|
|
while (begin != end) { |
|
|
while (begin != end) { |
|
|
|
|
|
auto size = size_; |
|
|
|
|
|
auto free_cap = capacity_ - size; |
|
|
auto count = to_unsigned(end - begin); |
|
|
auto count = to_unsigned(end - begin); |
|
|
try_reserve(size_ + count); |
|
|
|
|
|
auto free_cap = capacity_ - size_; |
|
|
|
|
|
if (free_cap < count) count = free_cap; |
|
|
|
|
|
|
|
|
if (free_cap < count) { |
|
|
|
|
|
grow_(*this, size + count); |
|
|
|
|
|
size = size_; |
|
|
|
|
|
free_cap = capacity_ - size; |
|
|
|
|
|
count = count < free_cap ? count : free_cap; |
|
|
|
|
|
} |
|
|
// A loop is faster than memcpy on small sizes. |
|
|
// A loop is faster than memcpy on small sizes. |
|
|
T* out = ptr_ + size_; |
|
|
|
|
|
|
|
|
T* out = ptr_ + size; |
|
|
for (size_t i = 0; i < count; ++i) out[i] = begin[i]; |
|
|
for (size_t i = 0; i < count; ++i) out[i] = begin[i]; |
|
|
size_ += count; |
|
|
size_ += count; |
|
|
begin += count; |
|
|
begin += count; |
|
|
@ -2033,6 +2064,17 @@ struct has_back_insert_iterator_container_append< |
|
|
.append(std::declval<InputIt>(), |
|
|
.append(std::declval<InputIt>(), |
|
|
std::declval<InputIt>()))>> : std::true_type {}; |
|
|
std::declval<InputIt>()))>> : std::true_type {}; |
|
|
|
|
|
|
|
|
|
|
|
template <typename OutputIt, typename InputIt, typename = void> |
|
|
|
|
|
struct has_back_insert_iterator_container_insert_at_end : std::false_type {}; |
|
|
|
|
|
|
|
|
|
|
|
template <typename OutputIt, typename InputIt> |
|
|
|
|
|
struct has_back_insert_iterator_container_insert_at_end< |
|
|
|
|
|
OutputIt, InputIt, |
|
|
|
|
|
void_t<decltype(get_container(std::declval<OutputIt>()) |
|
|
|
|
|
.insert(get_container(std::declval<OutputIt>()).end(), |
|
|
|
|
|
std::declval<InputIt>(), |
|
|
|
|
|
std::declval<InputIt>()))>> : std::true_type {}; |
|
|
|
|
|
|
|
|
// An optimized version of std::copy with the output value type (T). |
|
|
// An optimized version of std::copy with the output value type (T). |
|
|
template <typename T, typename InputIt, typename OutputIt, |
|
|
template <typename T, typename InputIt, typename OutputIt, |
|
|
FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value&& |
|
|
FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value&& |
|
|
@ -2047,6 +2089,8 @@ FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out) |
|
|
template <typename T, typename InputIt, typename OutputIt, |
|
|
template <typename T, typename InputIt, typename OutputIt, |
|
|
FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value && |
|
|
FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value && |
|
|
!has_back_insert_iterator_container_append< |
|
|
!has_back_insert_iterator_container_append< |
|
|
|
|
|
OutputIt, InputIt>::value && |
|
|
|
|
|
has_back_insert_iterator_container_insert_at_end< |
|
|
OutputIt, InputIt>::value)> |
|
|
OutputIt, InputIt>::value)> |
|
|
FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out) |
|
|
FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out) |
|
|
-> OutputIt { |
|
|
-> OutputIt { |
|
|
@ -2056,7 +2100,11 @@ FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
template <typename T, typename InputIt, typename OutputIt, |
|
|
template <typename T, typename InputIt, typename OutputIt, |
|
|
FMT_ENABLE_IF(!is_back_insert_iterator<OutputIt>::value)> |
|
|
|
|
|
|
|
|
FMT_ENABLE_IF(!(is_back_insert_iterator<OutputIt>::value && |
|
|
|
|
|
(has_back_insert_iterator_container_append< |
|
|
|
|
|
OutputIt, InputIt>::value || |
|
|
|
|
|
has_back_insert_iterator_container_insert_at_end< |
|
|
|
|
|
OutputIt, InputIt>::value)))> |
|
|
FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt { |
|
|
FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt { |
|
|
while (begin != end) *out++ = static_cast<T>(*begin++); |
|
|
while (begin != end) *out++ = static_cast<T>(*begin++); |
|
|
return out; |
|
|
return out; |
|
|
@ -2176,7 +2224,7 @@ template <typename Context> class value { |
|
|
static_assert(N <= 64, "unsupported _BitInt"); |
|
|
static_assert(N <= 64, "unsupported _BitInt"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
template <typename T, FMT_ENABLE_IF(is_char<T>::value)> |
|
|
|
|
|
|
|
|
template <typename T, FMT_ENABLE_IF(is_code_unit<T>::value)> |
|
|
constexpr FMT_INLINE value(T x FMT_BUILTIN) : char_value(x) { |
|
|
constexpr FMT_INLINE value(T x FMT_BUILTIN) : char_value(x) { |
|
|
static_assert( |
|
|
static_assert( |
|
|
std::is_same<T, char>::value || std::is_same<T, char_type>::value, |
|
|
std::is_same<T, char>::value || std::is_same<T, char_type>::value, |
|
|
@ -2252,7 +2300,7 @@ template <typename Context> class value { |
|
|
custom.value = const_cast<value_type*>(&x); |
|
|
custom.value = const_cast<value_type*>(&x); |
|
|
#endif |
|
|
#endif |
|
|
} |
|
|
} |
|
|
custom.format = format_custom<value_type, formatter<value_type, char_type>>; |
|
|
|
|
|
|
|
|
custom.format = format_custom<value_type>; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
template <typename T, FMT_ENABLE_IF(!has_formatter<T, char_type>())> |
|
|
template <typename T, FMT_ENABLE_IF(!has_formatter<T, char_type>())> |
|
|
@ -2263,10 +2311,10 @@ template <typename Context> class value { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Formats an argument of a custom type, such as a user-defined class. |
|
|
// Formats an argument of a custom type, such as a user-defined class. |
|
|
template <typename T, typename Formatter> |
|
|
|
|
|
|
|
|
template <typename T> |
|
|
static void format_custom(void* arg, parse_context<char_type>& parse_ctx, |
|
|
static void format_custom(void* arg, parse_context<char_type>& parse_ctx, |
|
|
Context& ctx) { |
|
|
Context& ctx) { |
|
|
auto f = Formatter(); |
|
|
|
|
|
|
|
|
auto f = formatter<T, char_type>(); |
|
|
parse_ctx.advance_to(f.parse(parse_ctx)); |
|
|
parse_ctx.advance_to(f.parse(parse_ctx)); |
|
|
using qualified_type = |
|
|
using qualified_type = |
|
|
conditional_t<has_formatter<const T, char_type>(), const T, T>; |
|
|
conditional_t<has_formatter<const T, char_type>(), const T, T>; |
|
|
@ -2293,35 +2341,14 @@ struct is_output_iterator< |
|
|
enable_if_t<std::is_assignable<decltype(*std::declval<decay_t<It>&>()++), |
|
|
enable_if_t<std::is_assignable<decltype(*std::declval<decay_t<It>&>()++), |
|
|
T>::value>> : std::true_type {}; |
|
|
T>::value>> : std::true_type {}; |
|
|
|
|
|
|
|
|
#ifndef FMT_USE_LOCALE |
|
|
|
|
|
# define FMT_USE_LOCALE (FMT_OPTIMIZE_SIZE <= 1) |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
// A type-erased reference to an std::locale to avoid a heavy <locale> include. |
|
|
|
|
|
class locale_ref { |
|
|
|
|
|
#if FMT_USE_LOCALE |
|
|
|
|
|
private: |
|
|
|
|
|
const void* locale_; // A type-erased pointer to std::locale. |
|
|
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
|
constexpr locale_ref() : locale_(nullptr) {} |
|
|
|
|
|
template <typename Locale> locale_ref(const Locale& loc); |
|
|
|
|
|
|
|
|
|
|
|
inline explicit operator bool() const noexcept { return locale_ != nullptr; } |
|
|
|
|
|
#endif // FMT_USE_LOCALE |
|
|
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
|
template <typename Locale> auto get() const -> Locale; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
template <typename> constexpr auto encode_types() -> unsigned long long { |
|
|
template <typename> constexpr auto encode_types() -> unsigned long long { |
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
template <typename Context, typename Arg, typename... Args> |
|
|
|
|
|
|
|
|
template <typename Context, typename First, typename... T> |
|
|
constexpr auto encode_types() -> unsigned long long { |
|
|
constexpr auto encode_types() -> unsigned long long { |
|
|
return static_cast<unsigned>(stored_type_constant<Arg, Context>::value) | |
|
|
|
|
|
(encode_types<Context, Args...>() << packed_arg_bits); |
|
|
|
|
|
|
|
|
return static_cast<unsigned>(stored_type_constant<First, Context>::value) | |
|
|
|
|
|
(encode_types<Context, T...>() << packed_arg_bits); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
template <typename Context, typename... T, size_t NUM_ARGS = sizeof...(T)> |
|
|
template <typename Context, typename... T, size_t NUM_ARGS = sizeof...(T)> |
|
|
@ -2338,8 +2365,9 @@ template <typename Context, int NUM_ARGS, int NUM_NAMED_ARGS, |
|
|
unsigned long long DESC> |
|
|
unsigned long long DESC> |
|
|
struct named_arg_store { |
|
|
struct named_arg_store { |
|
|
// args_[0].named_args points to named_args to avoid bloating format_args. |
|
|
// args_[0].named_args points to named_args to avoid bloating format_args. |
|
|
arg_t<Context, NUM_ARGS> args[1 + NUM_ARGS]; |
|
|
|
|
|
named_arg_info<typename Context::char_type> named_args[NUM_NAMED_ARGS]; |
|
|
|
|
|
|
|
|
arg_t<Context, NUM_ARGS> args[1u + NUM_ARGS]; |
|
|
|
|
|
named_arg_info<typename Context::char_type> |
|
|
|
|
|
named_args[static_cast<size_t>(NUM_NAMED_ARGS)]; |
|
|
|
|
|
|
|
|
template <typename... T> |
|
|
template <typename... T> |
|
|
FMT_CONSTEXPR FMT_ALWAYS_INLINE named_arg_store(T&... values) |
|
|
FMT_CONSTEXPR FMT_ALWAYS_INLINE named_arg_store(T&... values) |
|
|
@ -2358,8 +2386,8 @@ struct named_arg_store { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
named_arg_store(const named_arg_store& rhs) = delete; |
|
|
named_arg_store(const named_arg_store& rhs) = delete; |
|
|
named_arg_store& operator=(const named_arg_store& rhs) = delete; |
|
|
|
|
|
named_arg_store& operator=(named_arg_store&& rhs) = delete; |
|
|
|
|
|
|
|
|
auto operator=(const named_arg_store& rhs) -> named_arg_store& = delete; |
|
|
|
|
|
auto operator=(named_arg_store&& rhs) -> named_arg_store& = delete; |
|
|
operator const arg_t<Context, NUM_ARGS>*() const { return args + 1; } |
|
|
operator const arg_t<Context, NUM_ARGS>*() const { return args + 1; } |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
@ -2372,7 +2400,7 @@ struct format_arg_store { |
|
|
// +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning. |
|
|
// +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning. |
|
|
using type = |
|
|
using type = |
|
|
conditional_t<NUM_NAMED_ARGS == 0, |
|
|
conditional_t<NUM_NAMED_ARGS == 0, |
|
|
arg_t<Context, NUM_ARGS>[max_of(1, NUM_ARGS)], |
|
|
|
|
|
|
|
|
arg_t<Context, NUM_ARGS>[max_of<size_t>(1, NUM_ARGS)], |
|
|
named_arg_store<Context, NUM_ARGS, NUM_NAMED_ARGS, DESC>>; |
|
|
named_arg_store<Context, NUM_ARGS, NUM_NAMED_ARGS, DESC>>; |
|
|
type args; |
|
|
type args; |
|
|
}; |
|
|
}; |
|
|
@ -2656,22 +2684,17 @@ class context { |
|
|
private: |
|
|
private: |
|
|
appender out_; |
|
|
appender out_; |
|
|
format_args args_; |
|
|
format_args args_; |
|
|
FMT_NO_UNIQUE_ADDRESS detail::locale_ref loc_; |
|
|
|
|
|
|
|
|
FMT_NO_UNIQUE_ADDRESS locale_ref loc_; |
|
|
|
|
|
|
|
|
public: |
|
|
public: |
|
|
/// The character type for the output. |
|
|
|
|
|
using char_type = char; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
using char_type = char; ///< The character type for the output. |
|
|
using iterator = appender; |
|
|
using iterator = appender; |
|
|
using format_arg = basic_format_arg<context>; |
|
|
using format_arg = basic_format_arg<context>; |
|
|
using parse_context_type FMT_DEPRECATED = parse_context<>; |
|
|
|
|
|
template <typename T> using formatter_type FMT_DEPRECATED = formatter<T>; |
|
|
|
|
|
enum { builtin_types = FMT_BUILTIN_TYPES }; |
|
|
enum { builtin_types = FMT_BUILTIN_TYPES }; |
|
|
|
|
|
|
|
|
/// Constructs a `context` object. References to the arguments are stored |
|
|
/// Constructs a `context` object. References to the arguments are stored |
|
|
/// in the object so make sure they have appropriate lifetimes. |
|
|
/// in the object so make sure they have appropriate lifetimes. |
|
|
FMT_CONSTEXPR context(iterator out, format_args args, |
|
|
|
|
|
detail::locale_ref loc = {}) |
|
|
|
|
|
|
|
|
FMT_CONSTEXPR context(iterator out, format_args args, locale_ref loc = {}) |
|
|
: out_(out), args_(args), loc_(loc) {} |
|
|
: out_(out), args_(args), loc_(loc) {} |
|
|
context(context&&) = default; |
|
|
context(context&&) = default; |
|
|
context(const context&) = delete; |
|
|
context(const context&) = delete; |
|
|
@ -2692,7 +2715,7 @@ class context { |
|
|
// Advances the begin iterator to `it`. |
|
|
// Advances the begin iterator to `it`. |
|
|
FMT_CONSTEXPR void advance_to(iterator) {} |
|
|
FMT_CONSTEXPR void advance_to(iterator) {} |
|
|
|
|
|
|
|
|
FMT_CONSTEXPR auto locale() const -> detail::locale_ref { return loc_; } |
|
|
|
|
|
|
|
|
FMT_CONSTEXPR auto locale() const -> locale_ref { return loc_; } |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
template <typename Char = char> struct runtime_format_string { |
|
|
template <typename Char = char> struct runtime_format_string { |
|
|
@ -2779,9 +2802,6 @@ template <typename T, typename Char = char> |
|
|
concept formattable = is_formattable<remove_reference_t<T>, Char>::value; |
|
|
concept formattable = is_formattable<remove_reference_t<T>, Char>::value; |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
template <typename T, typename Char> |
|
|
|
|
|
using has_formatter FMT_DEPRECATED = std::is_constructible<formatter<T, Char>>; |
|
|
|
|
|
|
|
|
|
|
|
// A formatter specialization for natively supported types. |
|
|
// A formatter specialization for natively supported types. |
|
|
template <typename T, typename Char> |
|
|
template <typename T, typename Char> |
|
|
struct formatter<T, Char, |
|
|
struct formatter<T, Char, |
|
|
@ -2978,9 +2998,10 @@ FMT_INLINE void println(format_string<T...> fmt, T&&... args) { |
|
|
return fmt::println(stdout, fmt, static_cast<T&&>(args)...); |
|
|
return fmt::println(stdout, fmt, static_cast<T&&>(args)...); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
FMT_END_EXPORT |
|
|
|
|
|
|
|
|
FMT_PRAGMA_GCC(diagnostic pop) |
|
|
FMT_PRAGMA_CLANG(diagnostic pop) |
|
|
FMT_PRAGMA_CLANG(diagnostic pop) |
|
|
FMT_PRAGMA_GCC(pop_options) |
|
|
FMT_PRAGMA_GCC(pop_options) |
|
|
|
|
|
FMT_END_EXPORT |
|
|
FMT_END_NAMESPACE |
|
|
FMT_END_NAMESPACE |
|
|
|
|
|
|
|
|
#ifdef FMT_HEADER_ONLY |
|
|
#ifdef FMT_HEADER_ONLY |