|
15 | 15 | # include <cstdlib>
|
16 | 16 | # include <exception>
|
17 | 17 | # include <memory>
|
| 18 | +# include <string> |
18 | 19 | # include <thread>
|
19 | 20 | # include <type_traits>
|
20 | 21 | # include <typeinfo>
|
@@ -416,36 +417,34 @@ template <typename Char> struct formatter<std::error_code, Char> {
|
416 | 417 | }
|
417 | 418 | };
|
418 | 419 |
|
419 |
| -FMT_EXPORT |
420 |
| -template <typename T, typename Char> |
421 |
| -struct formatter< |
422 |
| - T, Char, // DEPRECATED! Mixing code unit types. |
423 |
| - typename std::enable_if<std::is_base_of<std::exception, T>::value>::type> { |
424 |
| - private: |
425 |
| - bool with_typename_ = false; |
| 420 | +#if FMT_USE_RTTI |
| 421 | +namespace details { |
| 422 | +template <typename Char> |
| 423 | +inline void remove_all_substrings( |
| 424 | + std::basic_string<Char>& src, |
| 425 | + type_identity_t<basic_string_view<Char>> pattern) { |
| 426 | + const auto pattern_length = pattern.size(); |
| 427 | + for (auto i = src.find(pattern.data(), 0, pattern_length); |
| 428 | + i != std::basic_string<Char>::npos; |
| 429 | + i = src.find(pattern.data(), 0, pattern_length)) |
| 430 | + src.erase(i, pattern_length); |
| 431 | +} |
| 432 | +} // namespace details |
426 | 433 |
|
| 434 | +FMT_EXPORT |
| 435 | +template <typename Char> |
| 436 | +struct formatter<std::type_info, Char // DEPRECATED! Mixing code unit types. |
| 437 | + > { |
427 | 438 | public:
|
428 | 439 | FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
|
429 | 440 | -> decltype(ctx.begin()) {
|
430 |
| - auto it = ctx.begin(); |
431 |
| - auto end = ctx.end(); |
432 |
| - if (it == end || *it == '}') return it; |
433 |
| - if (*it == 't') { |
434 |
| - ++it; |
435 |
| - with_typename_ = FMT_USE_RTTI != 0; |
436 |
| - } |
437 |
| - return it; |
| 441 | + return ctx.begin(); |
438 | 442 | }
|
439 | 443 |
|
440 | 444 | template <typename Context>
|
441 |
| - auto format(const std::exception& ex, Context& ctx) const |
| 445 | + auto format(const std::type_info& ti, Context& ctx) const |
442 | 446 | -> decltype(ctx.out()) {
|
443 | 447 | auto out = ctx.out();
|
444 |
| - if (!with_typename_) |
445 |
| - return detail::write_bytes<Char>(out, string_view(ex.what())); |
446 |
| - |
447 |
| -#if FMT_USE_RTTI |
448 |
| - const std::type_info& ti = typeid(ex); |
449 | 448 | # ifdef FMT_HAS_ABI_CXA_DEMANGLE
|
450 | 449 | int status = 0;
|
451 | 450 | std::size_t size = 0;
|
@@ -484,22 +483,61 @@ struct formatter<
|
484 | 483 | } else {
|
485 | 484 | demangled_name_view = string_view(ti.name());
|
486 | 485 | }
|
487 |
| - out = detail::write_bytes<Char>(out, demangled_name_view); |
| 486 | + return detail::write_bytes<Char>(out, demangled_name_view); |
488 | 487 | # elif FMT_MSC_VERSION
|
489 |
| - string_view demangled_name_view(ti.name()); |
490 |
| - if (demangled_name_view.starts_with("class ")) |
491 |
| - demangled_name_view.remove_prefix(6); |
492 |
| - else if (demangled_name_view.starts_with("struct ")) |
493 |
| - demangled_name_view.remove_prefix(7); |
494 |
| - out = detail::write_bytes<Char>(out, demangled_name_view); |
| 488 | + std::basic_string<Char> demangled_name(ti.name()); |
| 489 | + auto class_space = |
| 490 | + detail::string_literal<Char, 'c', 'l', 'a', 's', 's', ' '>{}; |
| 491 | + auto enum_space = detail::string_literal<Char, 'e', 'n', 'u', 'm', ' '>{}; |
| 492 | + auto struct_space = |
| 493 | + detail::string_literal<Char, 's', 't', 'r', 'u', 'c', 't', ' '>{}; |
| 494 | + details::remove_all_substrings(demangled_name, class_space); |
| 495 | + details::remove_all_substrings(demangled_name, enum_space); |
| 496 | + details::remove_all_substrings(demangled_name, struct_space); |
| 497 | + return detail::write_bytes<Char>(out, demangled_name); |
495 | 498 | # else
|
496 |
| - out = detail::write_bytes<Char>(out, string_view(ti.name()) |
497 |
| - }); |
| 499 | + return detail::write_bytes<Char>(out, string_view(ti.name())); |
498 | 500 | # endif
|
| 501 | + } |
| 502 | +}; |
| 503 | +#endif |
| 504 | + |
| 505 | +FMT_EXPORT |
| 506 | +template <typename T, typename Char> |
| 507 | +struct formatter< |
| 508 | + T, Char, // DEPRECATED! Mixing code unit types. |
| 509 | + typename std::enable_if<std::is_base_of<std::exception, T>::value>::type> { |
| 510 | + private: |
| 511 | + bool with_typename_ = false; |
| 512 | + |
| 513 | + public: |
| 514 | + FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx) |
| 515 | + -> decltype(ctx.begin()) { |
| 516 | + auto it = ctx.begin(); |
| 517 | + auto end = ctx.end(); |
| 518 | + if (it == end || *it == '}') return it; |
| 519 | + if (*it == 't') { |
| 520 | + ++it; |
| 521 | + with_typename_ = FMT_USE_RTTI != 0; |
| 522 | + } |
| 523 | + return it; |
| 524 | + } |
| 525 | + |
| 526 | + template <typename Context> |
| 527 | + auto format(const std::exception& ex, Context& ctx) const |
| 528 | + -> decltype(ctx.out()) { |
| 529 | + auto out = ctx.out(); |
| 530 | + if (!with_typename_) |
| 531 | + return detail::write_bytes<Char>(out, string_view(ex.what())); |
| 532 | + |
| 533 | +#if FMT_USE_RTTI |
| 534 | + const std::type_info& ti = typeid(ex); |
| 535 | + auto format_imag = detail::string_literal<Char, '{', '}'>{}; |
| 536 | + out = fmt::format_to(out, basic_string_view<Char>(format_imag), ti); |
| 537 | +#endif |
499 | 538 | *out++ = ':';
|
500 | 539 | *out++ = ' ';
|
501 | 540 | return detail::write_bytes<Char>(out, string_view(ex.what()));
|
502 |
| -#endif |
503 | 541 | }
|
504 | 542 | };
|
505 | 543 |
|
|
0 commit comments