@@ -416,6 +416,95 @@ template <typename Char> struct formatter<std::error_code, Char> {
416
416
}
417
417
};
418
418
419
+ #if FMT_USE_RTTI
420
+ namespace detail {
421
+
422
+ template <typename Char, typename OutputIt>
423
+ auto write_demangled_name (OutputIt out, const std::type_info& ti) -> OutputIt {
424
+ # ifdef FMT_HAS_ABI_CXA_DEMANGLE
425
+ int status = 0 ;
426
+ std::size_t size = 0 ;
427
+ std::unique_ptr<char , void (*)(void *)> demangled_name_ptr (
428
+ abi::__cxa_demangle (ti.name (), nullptr , &size, &status), &std::free);
429
+
430
+ string_view demangled_name_view;
431
+ if (demangled_name_ptr) {
432
+ demangled_name_view = demangled_name_ptr.get ();
433
+
434
+ // Normalization of stdlib inline namespace names.
435
+ // libc++ inline namespaces.
436
+ // std::__1::* -> std::*
437
+ // std::__1::__fs::* -> std::*
438
+ // libstdc++ inline namespaces.
439
+ // std::__cxx11::* -> std::*
440
+ // std::filesystem::__cxx11::* -> std::filesystem::*
441
+ if (demangled_name_view.starts_with (" std::" )) {
442
+ char * begin = demangled_name_ptr.get ();
443
+ char * to = begin + 5 ; // std::
444
+ for (char *from = to, *end = begin + demangled_name_view.size ();
445
+ from < end;) {
446
+ // This is safe, because demangled_name is NUL-terminated.
447
+ if (from[0 ] == ' _' && from[1 ] == ' _' ) {
448
+ char * next = from + 1 ;
449
+ while (next < end && *next != ' :' ) next++;
450
+ if (next[0 ] == ' :' && next[1 ] == ' :' ) {
451
+ from = next + 2 ;
452
+ continue ;
453
+ }
454
+ }
455
+ *to++ = *from++;
456
+ }
457
+ demangled_name_view = {begin, detail::to_unsigned (to - begin)};
458
+ }
459
+ } else {
460
+ demangled_name_view = string_view (ti.name ());
461
+ }
462
+ return detail::write_bytes<Char>(out, demangled_name_view);
463
+ # elif FMT_MSC_VERSION
464
+ const string_view demangled_name (ti.name ());
465
+ for (std::size_t i = 0 ; i < demangled_name.size (); ++i) {
466
+ auto sub = demangled_name;
467
+ sub.remove_prefix (i);
468
+ if (sub.starts_with (" enum " )) {
469
+ i += 4 ;
470
+ continue ;
471
+ }
472
+ if (sub.starts_with (" class " ) || sub.starts_with (" union " )) {
473
+ i += 5 ;
474
+ continue ;
475
+ }
476
+ if (sub.starts_with (" struct " )) {
477
+ i += 6 ;
478
+ continue ;
479
+ }
480
+ if (*sub.begin () != ' ' ) *out++ = *sub.begin ();
481
+ }
482
+ return out;
483
+ # else
484
+ return detail::write_bytes<Char>(out, string_view (ti.name ()));
485
+ # endif
486
+ }
487
+
488
+ } // namespace detail
489
+
490
+ FMT_EXPORT
491
+ template <typename Char>
492
+ struct formatter <std::type_info, Char // DEPRECATED! Mixing code unit types.
493
+ > {
494
+ public:
495
+ FMT_CONSTEXPR auto parse (basic_format_parse_context<Char>& ctx)
496
+ -> decltype(ctx.begin()) {
497
+ return ctx.begin ();
498
+ }
499
+
500
+ template <typename Context>
501
+ auto format (const std::type_info& ti, Context& ctx) const
502
+ -> decltype(ctx.out()) {
503
+ return detail::write_demangled_name<Char>(ctx.out (), ti);
504
+ }
505
+ };
506
+ #endif
507
+
419
508
FMT_EXPORT
420
509
template <typename T, typename Char>
421
510
struct formatter <
@@ -441,65 +530,14 @@ struct formatter<
441
530
auto format (const std::exception & ex, Context& ctx) const
442
531
-> decltype(ctx.out()) {
443
532
auto out = ctx.out ();
444
- if (!with_typename_)
445
- return detail::write_bytes<Char>(out, string_view (ex.what ()));
446
-
447
533
#if FMT_USE_RTTI
448
- const std::type_info& ti = typeid (ex);
449
- # ifdef FMT_HAS_ABI_CXA_DEMANGLE
450
- int status = 0 ;
451
- std::size_t size = 0 ;
452
- std::unique_ptr<char , void (*)(void *)> demangled_name_ptr (
453
- abi::__cxa_demangle (ti.name (), nullptr , &size, &status), &std::free);
454
-
455
- string_view demangled_name_view;
456
- if (demangled_name_ptr) {
457
- demangled_name_view = demangled_name_ptr.get ();
458
-
459
- // Normalization of stdlib inline namespace names.
460
- // libc++ inline namespaces.
461
- // std::__1::* -> std::*
462
- // std::__1::__fs::* -> std::*
463
- // libstdc++ inline namespaces.
464
- // std::__cxx11::* -> std::*
465
- // std::filesystem::__cxx11::* -> std::filesystem::*
466
- if (demangled_name_view.starts_with (" std::" )) {
467
- char * begin = demangled_name_ptr.get ();
468
- char * to = begin + 5 ; // std::
469
- for (char *from = to, *end = begin + demangled_name_view.size ();
470
- from < end;) {
471
- // This is safe, because demangled_name is NUL-terminated.
472
- if (from[0 ] == ' _' && from[1 ] == ' _' ) {
473
- char * next = from + 1 ;
474
- while (next < end && *next != ' :' ) next++;
475
- if (next[0 ] == ' :' && next[1 ] == ' :' ) {
476
- from = next + 2 ;
477
- continue ;
478
- }
479
- }
480
- *to++ = *from++;
481
- }
482
- demangled_name_view = {begin, detail::to_unsigned (to - begin)};
483
- }
484
- } else {
485
- demangled_name_view = string_view (ti.name ());
534
+ if (with_typename_) {
535
+ out = detail::write_demangled_name<Char>(out, typeid (ex));
536
+ *out++ = ' :' ;
537
+ *out++ = ' ' ;
486
538
}
487
- out = detail::write_bytes<Char>(out, demangled_name_view);
488
- # 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);
495
- # else
496
- out = detail::write_bytes<Char>(out, string_view (ti.name ())
497
- });
498
- # endif
499
- *out++ = ' :' ;
500
- *out++ = ' ' ;
501
- return detail::write_bytes<Char>(out, string_view (ex.what ()));
502
539
#endif
540
+ return detail::write_bytes<Char>(out, string_view (ex.what ()));
503
541
}
504
542
};
505
543
0 commit comments