19 # include <functional> 22 # include <type_traits> 27 # if FMT_CPLUSPLUS >= 201703L 28 # if FMT_HAS_INCLUDE(<filesystem>) && \ 29 (!defined(FMT_CPP_LIB_FILESYSTEM) || FMT_CPP_LIB_FILESYSTEM != 0) 30 # include <filesystem> 32 # if FMT_HAS_INCLUDE(<variant>) 35 # if FMT_HAS_INCLUDE(<optional>) 41 # if FMT_CPLUSPLUS > 201703L && FMT_HAS_INCLUDE(<source_location>) 42 # include <source_location> 44 # if FMT_CPLUSPLUS > 202002L && FMT_HAS_INCLUDE(<expected>) 49 #if FMT_HAS_INCLUDE(<version>) 54 #if FMT_HAS_INCLUDE(<cxxabi.h>) || defined(__GLIBCXX__) 58 # ifndef __GABIXX_CXXABI_H__ 59 # define FMT_HAS_ABI_CXA_DEMANGLE 63 #ifdef FMT_CPP_LIB_FILESYSTEM 65 #elif defined(__cpp_lib_filesystem) 66 # define FMT_CPP_LIB_FILESYSTEM __cpp_lib_filesystem 68 # define FMT_CPP_LIB_FILESYSTEM 0 71 #ifdef FMT_CPP_LIB_VARIANT 73 #elif defined(__cpp_lib_variant) 74 # define FMT_CPP_LIB_VARIANT __cpp_lib_variant 76 # define FMT_CPP_LIB_VARIANT 0 82 #if FMT_CPP_LIB_FILESYSTEM 84 template <
typename Char,
typename PathChar>
85 auto get_path_string(
const std::filesystem::path& p,
86 const std::basic_string<PathChar>& native) {
87 if constexpr (std::is_same_v<Char, char> && std::is_same_v<PathChar, wchar_t>)
88 return to_utf8<wchar_t>(native, to_utf8_error_policy::replace);
90 return p.string<Char>();
93 template <
typename Char,
typename PathChar>
95 const std::filesystem::path& p,
96 const std::basic_string<PathChar>& native) {
97 if constexpr (std::is_same_v<Char, char> &&
98 std::is_same_v<PathChar, wchar_t>) {
100 write_escaped_string<wchar_t>(std::back_inserter(buf), native);
101 bool valid = to_utf8<wchar_t>::convert(quoted, {buf.
data(), buf.size()});
102 FMT_ASSERT(valid,
"invalid utf16");
103 }
else if constexpr (std::is_same_v<Char, PathChar>) {
104 write_escaped_string<std::filesystem::path::value_type>(
105 std::back_inserter(quoted), native);
107 write_escaped_string<Char>(std::back_inserter(quoted), p.string<Char>());
111 #endif // FMT_CPP_LIB_FILESYSTEM 113 #if defined(__cpp_lib_expected) || FMT_CPP_LIB_VARIANT 114 template <
typename Char,
typename OutputIt,
typename T>
115 auto write_escaped_alternative(OutputIt out,
const T& v) -> OutputIt {
116 if constexpr (has_to_string_view<T>::value)
117 return write_escaped_string<Char>(out, detail::to_string_view(v));
118 if constexpr (std::is_same_v<T, Char>)
return write_escaped_char(out, v);
119 return write<Char>(out, v);
123 #if FMT_CPP_LIB_VARIANT 125 template <
typename>
struct is_variant_like_ : std::false_type {};
126 template <
typename... Types>
127 struct is_variant_like_<
std::variant<Types...>> : std::true_type {};
129 template <
typename Variant,
typename Char>
class is_variant_formattable {
130 template <
size_t... Is>
131 static auto check(std::index_sequence<Is...>) -> std::conjunction<
132 is_formattable<std::variant_alternative_t<Is, Variant>, Char>...>;
135 static constexpr
bool value = decltype(check(
136 std::make_index_sequence<std::variant_size<Variant>::value>()))::value;
139 #endif // FMT_CPP_LIB_VARIANT 143 template <
typename OutputIt>
144 auto write_demangled_name(OutputIt out,
const std::type_info& ti) -> OutputIt {
145 # ifdef FMT_HAS_ABI_CXA_DEMANGLE 148 std::unique_ptr<char, void (*)(void*)> demangled_name_ptr(
149 abi::__cxa_demangle(ti.name(),
nullptr, &size, &status), &std::free);
152 if (demangled_name_ptr) {
153 demangled_name_view = demangled_name_ptr.get();
162 if (demangled_name_view.starts_with(
"std::")) {
163 char* begin = demangled_name_ptr.get();
164 char* to = begin + 5;
165 for (
char *from = to, *end = begin + demangled_name_view.
size();
168 if (from[0] ==
'_' && from[1] ==
'_') {
169 char*
next = from + 1;
170 while (next < end && *next !=
':') next++;
171 if (next[0] ==
':' && next[1] ==
':') {
178 demangled_name_view = {begin, detail::to_unsigned(to - begin)};
183 return detail::write_bytes<char>(out, demangled_name_view);
184 # elif FMT_MSC_VERSION 186 for (
size_t i = 0; i < demangled_name.size(); ++i) {
187 auto sub = demangled_name;
188 sub.remove_prefix(i);
189 if (sub.starts_with(
"enum ")) {
193 if (sub.starts_with(
"class ") || sub.starts_with(
"union ")) {
197 if (sub.starts_with(
"struct ")) {
201 if (*sub.begin() !=
' ') *out++ = *sub.begin();
205 return detail::write_bytes<char>(out,
string_view(ti.name()));
209 #endif // FMT_USE_RTTI 211 template <
typename T,
typename Enable =
void>
212 struct has_flip : std::false_type {};
214 template <
typename T>
215 struct has_flip<T, void_t<decltype(std::declval<T>().flip())>>
218 template <
typename T>
struct is_bit_reference_like {
219 static constexpr
bool value = std::is_convertible<T, bool>::value &&
220 std::is_nothrow_assignable<T, bool>::value &&
226 #if defined(_LIBCPP_VERSION) && !defined(FMT_IMPORT_STD) 227 template <
typename C>
228 struct is_bit_reference_like<std::__bit_const_reference<C>> {
229 static constexpr
bool value =
true;
233 template <
typename T,
typename Enable =
void>
234 struct has_format_as : std::false_type {};
235 template <
typename T>
236 struct has_format_as<T, void_t<decltype(format_as(std::declval<const T&>()))>>
239 template <
typename T,
typename Enable =
void>
240 struct has_format_as_member : std::false_type {};
241 template <
typename T>
242 struct has_format_as_member<
243 T, void_t<decltype(formatter<T>::format_as(std::declval<const T&>()))>>
248 template <
typename T,
typename Deleter>
249 auto ptr(
const std::unique_ptr<T, Deleter>& p) ->
const void* {
252 template <
typename T>
auto ptr(
const std::shared_ptr<T>& p) ->
const void* {
256 #if FMT_CPP_LIB_FILESYSTEM 258 class path :
public std::filesystem::path {
260 auto display_string() const -> std::
string {
261 const std::filesystem::path& base = *
this;
262 return fmt::format(FMT_STRING(
"{}"), base);
264 auto system_string() const -> std::
string {
return string(); }
266 auto generic_display_string() const -> std::
string {
267 const std::filesystem::path& base = *
this;
268 return fmt::format(FMT_STRING(
"{:g}"), base);
270 auto generic_system_string() const -> std::
string {
return generic_string(); }
273 template <
typename Char>
struct formatter<std::filesystem::path, Char> {
276 detail::arg_ref<Char> width_ref_;
281 FMT_CONSTEXPR
void set_debug_format(
bool set =
true) { debug_ =
set; }
284 auto it = ctx.
begin(), end = ctx.
end();
285 if (it == end)
return it;
287 it = detail::parse_align(it, end, specs_);
288 if (it == end)
return it;
291 if ((c >=
'0' && c <=
'9') || c ==
'{')
292 it = detail::parse_width(it, end, specs_, width_ref_, ctx);
293 if (it != end && *it ==
'?') {
297 if (it != end && (*it ==
'g')) path_type_ = detail::to_ascii(*it++);
301 template <
typename FormatContext>
302 auto format(
const std::filesystem::path& p, FormatContext& ctx)
const {
305 !path_type_ ? p.native()
306 : p.generic_string<std::filesystem::path::value_type>();
308 detail::handle_dynamic_spec(specs.dynamic_width(), specs.width, width_ref_,
311 auto s = detail::get_path_string<Char>(p, path_string);
315 detail::write_escaped_path(quoted, p, path_string);
316 return detail::write(ctx.out(),
322 #endif // FMT_CPP_LIB_FILESYSTEM 324 template <
size_t N,
typename Char>
325 struct formatter<std::bitset<N>, Char>
326 : nested_formatter<basic_string_view<Char>, Char> {
330 const std::bitset<N>& bs;
332 template <
typename OutputIt>
333 FMT_CONSTEXPR
auto operator()(OutputIt out) -> OutputIt {
334 for (
auto pos = N; pos > 0; --pos)
335 out = detail::write<Char>(out, bs[pos - 1] ? Char(
'1') : Char(
'0'));
341 template <
typename FormatContext>
342 auto format(
const std::bitset<N>& bs, FormatContext& ctx)
const 343 -> decltype(ctx.out()) {
344 return this->write_padded(ctx, writer{bs});
348 template <
typename Char>
349 struct formatter<std::thread::id, Char> : basic_ostream_formatter<Char> {};
351 #ifdef __cpp_lib_optional 352 template <
typename T,
typename Char>
353 struct formatter<std::optional<T>, Char,
354 std::enable_if_t<is_formattable<T, Char>::value>> {
356 formatter<T, Char> underlying_;
358 detail::string_literal<Char,
'o',
'p',
't',
'i',
'o',
'n',
'a',
'l',
361 detail::string_literal<Char, 'n', 'o', 'n', 'e'>{};
364 FMT_CONSTEXPR
static auto maybe_set_debug_format(U& u,
bool set)
365 -> decltype(u.set_debug_format(
set)) {
366 u.set_debug_format(
set);
370 FMT_CONSTEXPR
static void maybe_set_debug_format(U&, ...) {}
374 maybe_set_debug_format(underlying_,
true);
375 return underlying_.parse(ctx);
378 template <
typename FormatContext>
379 auto format(
const std::optional<T>& opt, FormatContext& ctx)
const 380 -> decltype(ctx.out()) {
381 if (!opt)
return detail::write<Char>(ctx.out(), none);
383 auto out = ctx.out();
384 out = detail::write<Char>(out, optional);
386 out = underlying_.format(*opt, ctx);
387 return detail::write(out,
')');
390 #endif // __cpp_lib_optional 392 #ifdef __cpp_lib_expected 393 template <
typename T,
typename E,
typename Char>
394 struct formatter<std::expected<T, E>, Char,
395 std::enable_if_t<(std::is_void<T>::value ||
396 is_formattable<T, Char>::value) &&
397 is_formattable<E, Char>::value>> {
402 template <
typename FormatContext>
403 auto format(
const std::expected<T, E>& value, FormatContext& ctx)
const 404 -> decltype(ctx.out()) {
405 auto out = ctx.out();
407 if (value.has_value()) {
408 out = detail::write<Char>(out,
"expected(");
409 if constexpr (!std::is_void<T>::value)
410 out = detail::write_escaped_alternative<Char>(out, *value);
412 out = detail::write<Char>(out,
"unexpected(");
413 out = detail::write_escaped_alternative<Char>(out, value.error());
419 #endif // __cpp_lib_expected 421 #ifdef __cpp_lib_source_location 422 template <>
struct formatter<std::source_location> {
425 template <
typename FormatContext>
426 auto format(
const std::source_location& loc, FormatContext& ctx)
const 427 -> decltype(ctx.out()) {
428 auto out = ctx.out();
429 out = detail::write(out, loc.file_name());
430 out = detail::write(out,
':');
431 out = detail::write<char>(out, loc.line());
432 out = detail::write(out,
':');
433 out = detail::write<char>(out, loc.column());
434 out = detail::write(out,
": ");
435 out = detail::write(out, loc.function_name());
441 #if FMT_CPP_LIB_VARIANT 443 template <
typename T>
struct is_variant_like {
444 static constexpr
bool value = detail::is_variant_like_<T>::value;
447 template <
typename Char>
struct formatter<std::monostate, Char> {
452 template <
typename FormatContext>
453 auto format(
const std::monostate&, FormatContext& ctx)
const 454 -> decltype(ctx.out()) {
455 return detail::write<Char>(ctx.out(),
"monostate");
459 template <
typename Variant,
typename Char>
460 struct formatter<Variant, Char,
461 std::enable_if_t<std::conjunction_v<
462 is_variant_like<Variant>,
463 detail::is_variant_formattable<Variant, Char>>>> {
468 template <
typename FormatContext>
469 auto format(
const Variant& value, FormatContext& ctx)
const 470 -> decltype(ctx.out()) {
471 auto out = ctx.out();
473 out = detail::write<Char>(out,
"variant(");
477 out = detail::write_escaped_alternative<Char>(out, v);
481 FMT_CATCH(
const std::bad_variant_access&) {
482 detail::write<Char>(out,
"valueless by exception");
489 #endif // FMT_CPP_LIB_VARIANT 491 template <>
struct formatter<std::error_code> {
494 detail::arg_ref<char> width_ref_;
499 auto it = ctx.
begin(), end = ctx.
end();
500 if (it == end)
return it;
502 it = detail::parse_align(it, end, specs_);
505 if (it != end && ((c >=
'0' && c <=
'9') || c ==
'{'))
506 it = detail::parse_width(it, end, specs_, width_ref_, ctx);
508 if (it != end && *it ==
'?') {
512 if (it != end && *it ==
's') {
513 specs_.set_type(presentation_type::string);
519 template <
typename FormatContext>
520 FMT_CONSTEXPR20
auto format(
const std::error_code& ec,
521 FormatContext& ctx)
const -> decltype(ctx.out()) {
523 detail::handle_dynamic_spec(specs.dynamic_width(), specs.width, width_ref_,
526 if (specs_.type() == presentation_type::string) {
527 buf.append(ec.message());
531 detail::write<char>(appender(buf), ec.value());
536 detail::write_escaped_string<char>(std::back_inserter(quoted), str);
539 return detail::write<char>(ctx.out(), str, specs);
544 template <>
struct formatter<std::type_info> {
550 template <
typename Context>
551 auto format(
const std::type_info& ti, Context& ctx)
const 552 -> decltype(ctx.out()) {
553 return detail::write_demangled_name(ctx.out(), ti);
556 #endif // FMT_USE_RTTI 558 template <
typename T>
561 typename std::enable_if<std::is_base_of<std::exception, T>::value>::type> {
563 bool with_typename_ =
false;
567 auto it = ctx.
begin();
568 auto end = ctx.
end();
569 if (it == end || *it ==
'}')
return it;
572 with_typename_ = FMT_USE_RTTI != 0;
577 template <
typename Context>
578 auto format(
const std::exception& ex, Context& ctx)
const 579 -> decltype(ctx.out()) {
580 auto out = ctx.out();
582 if (with_typename_) {
583 out = detail::write_demangled_name(out,
typeid(ex));
588 return detail::write_bytes<char>(out,
string_view(ex.what()));
595 template <
typename BitRef,
typename Char>
596 struct formatter<BitRef, Char,
597 enable_if_t<
detail::is_bit_reference_like<BitRef>::value>>
598 : formatter<bool, Char> {
599 template <
typename FormatContext>
600 FMT_CONSTEXPR
auto format(
const BitRef& v, FormatContext& ctx)
const 601 -> decltype(ctx.out()) {
602 return formatter<bool, Char>::format(v, ctx);
606 template <
typename T,
typename Char>
607 struct formatter<std::atomic<T>, Char,
608 enable_if_t<is_formattable<T, Char>::value>>
609 : formatter<T, Char> {
610 template <
typename FormatContext>
611 auto format(
const std::atomic<T>& v, FormatContext& ctx)
const 612 -> decltype(ctx.out()) {
613 return formatter<T, Char>::format(v.load(), ctx);
617 #ifdef __cpp_lib_atomic_flag_test 618 template <
typename Char>
619 struct formatter<std::atomic_flag, Char> : formatter<bool, Char> {
620 template <
typename FormatContext>
621 auto format(
const std::atomic_flag& v, FormatContext& ctx)
const 622 -> decltype(ctx.out()) {
623 return formatter<bool, Char>::format(v.test(), ctx);
626 #endif // __cpp_lib_atomic_flag_test 628 template <
typename T,
typename Char>
struct formatter<std::complex<T>, Char> {
630 detail::dynamic_format_specs<Char> specs_;
632 template <
typename FormatContext,
typename OutputIt>
633 FMT_CONSTEXPR
auto do_format(
const std::complex<T>& c,
634 detail::dynamic_format_specs<Char>& specs,
635 FormatContext& ctx, OutputIt out)
const 639 out = detail::write<Char>(out, c.real(), specs, ctx.locale());
640 specs.set_sign(sign::plus);
641 out = detail::write<Char>(out, c.imag(), specs, ctx.locale());
642 if (!detail::isfinite(c.imag())) *out++ = Char(
' ');
647 out = detail::write<Char>(out, c.imag(), specs, ctx.locale());
648 if (!detail::isfinite(c.imag())) *out++ = Char(
' ');
656 return parse_format_specs(ctx.
begin(), ctx.
end(), specs_, ctx,
657 detail::type_constant<T, Char>::value);
660 template <
typename FormatContext>
661 auto format(
const std::complex<T>& c, FormatContext& ctx)
const 662 -> decltype(ctx.out()) {
664 if (specs.dynamic()) {
665 detail::handle_dynamic_spec(specs.dynamic_width(), specs.width,
666 specs.width_ref, ctx);
667 detail::handle_dynamic_spec(specs.dynamic_precision(), specs.precision,
668 specs.precision_ref, ctx);
671 if (specs.width == 0)
return do_format(c, specs, ctx, ctx.out());
674 auto outer_specs = format_specs();
675 outer_specs.width = specs.width;
676 outer_specs.copy_fill_from(specs);
677 outer_specs.set_align(specs.align());
681 specs.set_align(align::none);
683 do_format(c, specs, ctx, basic_appender<Char>(buf));
684 return detail::write<Char>(ctx.out(),
690 template <
typename T,
typename Char>
691 struct formatter<std::reference_wrapper<T>, Char,
694 enable_if_t<is_formattable<remove_cvref_t<T>, Char>::value &&
695 !detail::has_format_as<T>::value &&
696 !detail::has_format_as_member<T>::value>>
697 : formatter<remove_cvref_t<T>, Char> {
698 template <
typename FormatContext>
699 auto format(std::reference_wrapper<T> ref, FormatContext& ctx)
const 700 -> decltype(ctx.out()) {
701 return formatter<remove_cvref_t<T>, Char>::format(ref.get(), ctx);
A dynamically growing memory buffer for trivially copyable/constructible types with the first SIZE el...
Definition: format.h:785
Parsing context consisting of a format string range being parsed and an argument counter for automati...
Definition: base.h:623
constexpr auto size() const noexcept -> size_t
Returns the string size.
Definition: base.h:560
Converts a string literal into a format string that will be parsed at compile time and converted into...
Definition: args.h:20
constexpr auto end() const noexcept -> iterator
Returns an iterator past the end of the format string range being parsed.
Definition: base.h:872
constexpr auto size() const noexcept -> size_t
Returns the size of this buffer.
Definition: base.h:1805
FMT_CONSTEXPR auto data() noexcept -> T *
Returns a pointer to the buffer data (not null-terminated).
Definition: base.h:1811
constexpr auto begin() const noexcept -> iterator
Returns an iterator to the beginning of the format string range being parsed.
Definition: base.h:869
bool next(BasicCoordinate< num_dimensions, int > &indices, const Array< num_dimensions2, T > &a)
Given an index into an array, increment it to the next one.
Definition: array_index_functions.inl:107
FMT_CONSTEXPR void advance_to(iterator it)
Advances the begin iterator to it.
Definition: base.h:875