8 #ifndef FMTQUILL_STD_H_ 9 #define FMTQUILL_STD_H_ 14 #ifndef FMTQUILL_MODULE 19 # include <functional> 22 # include <type_traits> 27 # if FMTQUILL_CPLUSPLUS >= 201703L 28 # if FMTQUILL_HAS_INCLUDE(<filesystem>) && \ 29 (!defined(FMTQUILL_CPP_LIB_FILESYSTEM) || FMTQUILL_CPP_LIB_FILESYSTEM != 0) 30 # include <filesystem> 32 # if FMTQUILL_HAS_INCLUDE(<variant>) 35 # if FMTQUILL_HAS_INCLUDE(<optional>) 41 # if FMTQUILL_CPLUSPLUS > 201703L && FMTQUILL_HAS_INCLUDE(<source_location>) 42 # include <source_location> 44 # if FMTQUILL_CPLUSPLUS > 202002L && FMTQUILL_HAS_INCLUDE(<expected>) 47 #endif // FMTQUILL_MODULE 49 #if FMTQUILL_HAS_INCLUDE(<version>) 54 #if FMTQUILL_HAS_INCLUDE(<cxxabi.h>) || defined(__GLIBCXX__) 58 # ifndef __GABIXX_CXXABI_H__ 59 # define FMTQUILL_HAS_ABI_CXA_DEMANGLE 63 #ifdef FMTQUILL_CPP_LIB_FILESYSTEM 65 #elif defined(__cpp_lib_filesystem) 66 # define FMTQUILL_CPP_LIB_FILESYSTEM __cpp_lib_filesystem 68 # define FMTQUILL_CPP_LIB_FILESYSTEM 0 71 #ifdef FMTQUILL_CPP_LIB_VARIANT 73 #elif defined(__cpp_lib_variant) 74 # define FMTQUILL_CPP_LIB_VARIANT __cpp_lib_variant 76 # define FMTQUILL_CPP_LIB_VARIANT 0 79 FMTQUILL_BEGIN_NAMESPACE
82 #if FMTQUILL_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 FMTQUILL_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 // FMTQUILL_CPP_LIB_FILESYSTEM 113 #if defined(__cpp_lib_expected) || FMTQUILL_CPP_LIB_VARIANT 115 template <
typename Char,
typename OutputIt,
typename T,
typename FormatContext>
116 auto write_escaped_alternative(OutputIt out,
const T& v, FormatContext& ctx)
118 if constexpr (has_to_string_view<T>::value)
119 return write_escaped_string<Char>(out, detail::to_string_view(v));
120 if constexpr (std::is_same_v<T, Char>)
return write_escaped_char(out, v);
123 maybe_set_debug_format(underlying,
true);
124 return underlying.format(v, ctx);
128 #if FMTQUILL_CPP_LIB_VARIANT 130 template <
typename>
struct is_variant_like_ : std::false_type {};
131 template <
typename... Types>
132 struct is_variant_like_<
std::variant<Types...>> : std::true_type {};
134 template <
typename Variant,
typename Char>
class is_variant_formattable {
135 template <
size_t... Is>
136 static auto check(std::index_sequence<Is...>) -> std::conjunction<
137 is_formattable<std::variant_alternative_t<Is, Variant>, Char>...>;
140 static constexpr
bool value = decltype(check(
141 std::make_index_sequence<std::variant_size<Variant>::value>()))::value;
144 #endif // FMTQUILL_CPP_LIB_VARIANT 146 #if FMTQUILL_USE_RTTI 147 inline auto normalize_libcxx_inline_namespaces(
string_view demangled_name_view,
156 if (demangled_name_view.starts_with(
"std::")) {
157 char* to = begin + 5;
158 for (
const char *from = to, *end = begin + demangled_name_view.size();
161 if (from[0] ==
'_' && from[1] ==
'_') {
162 const char* next = from + 1;
163 while (next < end && *next !=
':') next++;
164 if (next[0] ==
':' && next[1] ==
':') {
171 demangled_name_view = {begin, detail::to_unsigned(to - begin)};
173 return demangled_name_view;
176 template <
class OutputIt>
177 auto normalize_msvc_abi_name(
string_view abi_name_view, OutputIt out)
180 for (
size_t i = 0; i < demangled_name.size(); ++i) {
181 auto sub = demangled_name;
182 sub.remove_prefix(i);
183 if (sub.starts_with(
"enum ")) {
187 if (sub.starts_with(
"class ") || sub.starts_with(
"union ")) {
191 if (sub.starts_with(
"struct ")) {
195 if (*sub.begin() !=
' ') *out++ = *sub.begin();
200 template <
typename OutputIt>
201 auto write_demangled_name(OutputIt out,
const std::type_info& ti) -> OutputIt {
202 # ifdef FMTQUILL_HAS_ABI_CXA_DEMANGLE 205 std::unique_ptr<char, void (*)(void*)> demangled_name_ptr(
206 abi::__cxa_demangle(ti.name(),
nullptr, &size, &status), &free);
209 if (demangled_name_ptr) {
210 demangled_name_view = normalize_libcxx_inline_namespaces(
211 demangled_name_ptr.get(), demangled_name_ptr.get());
215 return detail::write_bytes<char>(out, demangled_name_view);
216 # elif FMTQUILL_MSC_VERSION && defined(_MSVC_STL_UPDATE) 217 return normalize_msvc_abi_name(ti.name(), out);
218 # elif FMTQUILL_MSC_VERSION && defined(_LIBCPP_VERSION) 220 std::string name_copy(demangled_name.size(),
'\0');
223 name_copy.erase(normalize_msvc_abi_name(demangled_name, name_copy.begin()),
229 normalize_libcxx_inline_namespaces(name_copy, name_copy.data());
230 return detail::write_bytes<char>(out, normalized_name);
232 return detail::write_bytes<char>(out,
string_view(ti.name()));
236 #endif // FMTQUILL_USE_RTTI 238 template <
typename T,
typename Enable =
void>
241 template <
typename T>
242 struct has_flip<T, void_t<decltype(std::declval<T>().flip())>>
246 static constexpr
bool value = std::is_convertible<T, bool>::value &&
247 std::is_nothrow_assignable<T, bool>::value &&
253 #if defined(_LIBCPP_VERSION) && !defined(FMTQUILL_IMPORT_STD) 254 template <
typename C>
256 static constexpr
bool value =
true;
260 template <
typename T,
typename Enable =
void>
262 template <
typename T>
263 struct has_format_as<T, void_t<decltype(format_as(std::declval<const T&>()))>>
266 template <
typename T,
typename Enable =
void>
268 template <
typename T>
270 T, void_t<decltype(
formatter<T>::format_as(std::declval<const T&>()))>>
275 template <
typename T,
typename Deleter>
276 auto ptr(
const std::unique_ptr<T, Deleter>& p) ->
const void* {
279 template <
typename T>
auto ptr(
const std::shared_ptr<T>& p) ->
const void* {
283 #if FMTQUILL_CPP_LIB_FILESYSTEM 285 template <
typename Char>
struct formatter<std::filesystem::path, Char> {
293 FMTQUILL_CONSTEXPR
void set_debug_format(
bool set =
true) { debug_ =
set; }
296 auto it = ctx.
begin(), end = ctx.
end();
297 if (it == end)
return it;
299 it = detail::parse_align(it, end, specs_);
300 if (it == end)
return it;
303 if ((c >=
'0' && c <=
'9') || c ==
'{')
304 it = detail::parse_width(it, end, specs_, width_ref_, ctx);
305 if (it != end && *it ==
'?') {
309 if (it != end && (*it ==
'g')) path_type_ = detail::to_ascii(*it++);
313 template <
typename FormatContext>
314 auto format(
const std::filesystem::path& p, FormatContext& ctx)
const {
317 !path_type_ ? p.native()
318 : p.generic_string<std::filesystem::path::value_type>();
320 detail::handle_dynamic_spec(specs.dynamic_width(), specs.width, width_ref_,
323 auto s = detail::get_path_string<Char>(p, path_string);
327 detail::write_escaped_path(quoted, p, path_string);
328 return detail::write(ctx.out(),
334 class path :
public std::filesystem::path {
336 auto display_string()
const -> std::string {
337 const std::filesystem::path& base = *
this;
338 return fmtquill::format(FMTQUILL_STRING(
"{}"), base);
340 auto system_string()
const -> std::string {
return string(); }
342 auto generic_display_string()
const -> std::string {
343 const std::filesystem::path& base = *
this;
344 return fmtquill::format(FMTQUILL_STRING(
"{:g}"), base);
346 auto generic_system_string()
const -> std::string {
return generic_string(); }
349 #endif // FMTQUILL_CPP_LIB_FILESYSTEM 351 template <
size_t N,
typename Char>
357 const std::bitset<N>& bs;
359 template <
typename OutputIt>
360 FMTQUILL_CONSTEXPR
auto operator()(OutputIt out) -> OutputIt {
361 for (
auto pos = N; pos > 0; --pos)
362 out = detail::write<Char>(out, bs[pos - 1] ? Char(
'1') : Char(
'0'));
368 template <
typename FormatContext>
369 auto format(
const std::bitset<N>& bs, FormatContext& ctx)
const 370 -> decltype(ctx.out()) {
371 return this->write_padded(ctx,
writer{bs});
375 template <
typename Char>
378 #ifdef __cpp_lib_optional 379 template <
typename T,
typename Char>
381 std::enable_if_t<is_formattable<T, Char>::value>> {
392 detail::maybe_set_debug_format(underlying_,
true);
393 return underlying_.parse(ctx);
396 template <
typename FormatContext>
397 auto format(
const std::optional<T>& opt, FormatContext& ctx)
const 398 -> decltype(ctx.out()) {
399 if (!opt)
return detail::write<Char>(ctx.out(), none);
401 auto out = ctx.out();
402 out = detail::write<Char>(out, optional);
404 out = underlying_.format(*opt, ctx);
405 return detail::write(out,
')');
408 #endif // __cpp_lib_optional 410 #ifdef __cpp_lib_expected 411 template <
typename T,
typename E,
typename Char>
412 struct formatter<std::expected<T, E>, Char,
413 std::enable_if_t<(std::is_void<T>::value ||
414 is_formattable<T, Char>::value) &&
415 is_formattable<E, Char>::value>> {
420 template <
typename FormatContext>
421 auto format(
const std::expected<T, E>& value, FormatContext& ctx)
const 422 -> decltype(ctx.out()) {
423 auto out = ctx.out();
425 if (value.has_value()) {
426 out = detail::write<Char>(out,
"expected(");
427 if constexpr (!std::is_void<T>::value)
428 out = detail::write_escaped_alternative<Char>(out, *value, ctx);
430 out = detail::write<Char>(out,
"unexpected(");
431 out = detail::write_escaped_alternative<Char>(out, value.error(), ctx);
437 #endif // __cpp_lib_expected 439 #ifdef __cpp_lib_source_location 440 template <>
struct formatter<std::source_location> {
443 template <
typename FormatContext>
444 auto format(
const std::source_location& loc, FormatContext& ctx)
const 445 -> decltype(ctx.out()) {
446 auto out = ctx.out();
447 out = detail::write(out, loc.file_name());
448 out = detail::write(out,
':');
449 out = detail::write<char>(out, loc.line());
450 out = detail::write(out,
':');
451 out = detail::write<char>(out, loc.column());
452 out = detail::write(out,
": ");
453 out = detail::write(out, loc.function_name());
459 #if FMTQUILL_CPP_LIB_VARIANT 461 template <
typename T>
struct is_variant_like {
462 static constexpr
bool value = detail::is_variant_like_<T>::value;
470 template <
typename FormatContext>
471 auto format(
const std::monostate&, FormatContext& ctx)
const 472 -> decltype(ctx.out()) {
473 return detail::write<Char>(ctx.out(),
"monostate");
477 template <
typename Variant,
typename Char>
479 std::enable_if_t<std::conjunction_v<
480 is_variant_like<Variant>,
481 detail::is_variant_formattable<Variant, Char>>>> {
486 template <
typename FormatContext>
487 auto format(
const Variant& value, FormatContext& ctx)
const 488 -> decltype(ctx.out()) {
489 auto out = ctx.out();
491 out = detail::write<Char>(out,
"variant(");
495 out = detail::write_escaped_alternative<Char>(out, v, ctx);
499 FMTQUILL_CATCH(
const std::bad_variant_access&) {
500 detail::write<Char>(out,
"valueless by exception");
507 #endif // FMTQUILL_CPP_LIB_VARIANT 516 FMTQUILL_CONSTEXPR
void set_debug_format(
bool set =
true) { debug_ =
set; }
519 auto it = ctx.
begin(), end = ctx.
end();
520 if (it == end)
return it;
522 it = detail::parse_align(it, end, specs_);
525 if (it != end && ((c >=
'0' && c <=
'9') || c ==
'{'))
526 it = detail::parse_width(it, end, specs_, width_ref_, ctx);
528 if (it != end && *it ==
'?') {
532 if (it != end && *it ==
's') {
533 specs_.set_type(presentation_type::string);
539 template <
typename FormatContext>
540 FMTQUILL_CONSTEXPR20
auto format(
const std::error_code& ec,
541 FormatContext& ctx)
const -> decltype(ctx.out()) {
543 detail::handle_dynamic_spec(specs.dynamic_width(), specs.width, width_ref_,
546 if (specs_.type() == presentation_type::string) {
547 buf.append(ec.message());
551 detail::write<char>(
appender(buf), ec.value());
556 detail::write_escaped_string<char>(std::back_inserter(quoted), str);
559 return detail::write<char>(ctx.out(), str, specs);
563 #if FMTQUILL_USE_RTTI 564 template <>
struct formatter<std::type_info> {
570 template <
typename Context>
571 auto format(
const std::type_info& ti, Context& ctx)
const 572 -> decltype(ctx.out()) {
573 return detail::write_demangled_name(ctx.out(), ti);
576 #endif // FMTQUILL_USE_RTTI 578 template <
typename T>
581 typename std::enable_if<std::is_base_of<std::exception, T>::value>::type> {
583 bool with_typename_ =
false;
587 auto it = ctx.
begin();
588 auto end = ctx.
end();
589 if (it == end || *it ==
'}')
return it;
592 with_typename_ = FMTQUILL_USE_RTTI != 0;
597 template <
typename Context>
598 auto format(
const std::exception& ex, Context& ctx)
const 599 -> decltype(ctx.out()) {
600 auto out = ctx.out();
601 #if FMTQUILL_USE_RTTI 602 if (with_typename_) {
603 out = detail::write_demangled_name(out,
typeid(ex));
608 return detail::write_bytes<char>(out,
string_view(ex.what()));
615 template <
typename BitRef,
typename Char>
617 enable_if_t<
detail::is_bit_reference_like<BitRef>::value>>
619 template <
typename FormatContext>
620 FMTQUILL_CONSTEXPR
auto format(
const BitRef& v, FormatContext& ctx)
const 621 -> decltype(ctx.out()) {
626 template <
typename T,
typename Char>
628 enable_if_t<is_formattable<T, Char>::value>>
630 template <
typename FormatContext>
631 auto format(
const std::atomic<T>& v, FormatContext& ctx)
const 632 -> decltype(ctx.out()) {
637 #ifdef __cpp_lib_atomic_flag_test 638 template <
typename Char>
640 template <
typename FormatContext>
641 auto format(
const std::atomic_flag& v, FormatContext& ctx)
const 642 -> decltype(ctx.out()) {
646 #endif // __cpp_lib_atomic_flag_test 648 template <
typename T,
typename Char>
struct formatter<std::complex<T>, Char> {
652 template <
typename FormatContext,
typename OutputIt>
653 FMTQUILL_CONSTEXPR
auto do_format(
const std::complex<T>& c,
655 FormatContext& ctx, OutputIt out)
const 659 out = detail::write<Char>(out, c.real(), specs, ctx.locale());
660 specs.set_sign(sign::plus);
661 out = detail::write<Char>(out, c.imag(), specs, ctx.locale());
662 if (!detail::isfinite(c.imag())) *out++ = Char(
' ');
667 out = detail::write<Char>(out, c.imag(), specs, ctx.locale());
668 if (!detail::isfinite(c.imag())) *out++ = Char(
' ');
676 return parse_format_specs(ctx.
begin(), ctx.
end(), specs_, ctx,
680 template <
typename FormatContext>
681 auto format(
const std::complex<T>& c, FormatContext& ctx)
const 682 -> decltype(ctx.out()) {
684 if (specs.dynamic()) {
685 detail::handle_dynamic_spec(specs.dynamic_width(), specs.width,
686 specs.width_ref, ctx);
687 detail::handle_dynamic_spec(specs.dynamic_precision(), specs.precision,
688 specs.precision_ref, ctx);
691 if (specs.width == 0)
return do_format(c, specs, ctx, ctx.out());
695 outer_specs.width = specs.width;
696 outer_specs.copy_fill_from(specs);
697 outer_specs.set_align(specs.align());
701 specs.set_align(align::none);
704 return detail::write<Char>(ctx.out(),
710 template <
typename T,
typename Char>
714 enable_if_t<is_formattable<remove_cvref_t<T>, Char>::value &&
715 !detail::has_format_as<T>::value &&
716 !detail::has_format_as_member<T>::value>>
718 template <
typename FormatContext>
719 auto format(std::reference_wrapper<T> ref, FormatContext& ctx)
const 720 -> decltype(ctx.out()) {
725 FMTQUILL_END_NAMESPACE
727 #endif // FMTQUILL_STD_H_ A dynamically growing memory buffer for trivially copyable/constructible types with the first SIZE el...
Definition: format.h:809
FMTQUILL_CONSTEXPR auto data() noexcept -> T *
Returns a pointer to the buffer data (not null-terminated).
Definition: base.h:1825
Parsing context consisting of a format string range being parsed and an argument counter for automati...
Definition: base.h:634
Definition: UserDefinedDirectFormatFuzzer.cpp:81
Setups a signal handler to handle fatal signals.
Definition: BackendManager.h:24
constexpr auto end() const noexcept -> iterator
Returns an iterator past the end of the format string range being parsed.
Definition: base.h:883
constexpr auto size() const noexcept -> size_t
Returns the size of this buffer.
Definition: base.h:1819
constexpr auto begin() const noexcept -> iterator
Returns an iterator to the beginning of the format string range being parsed.
Definition: base.h:880