diff --git a/include/fmt/std.h b/include/fmt/std.h index 7f484274500a..2896e82a0c12 100644 --- a/include/fmt/std.h +++ b/include/fmt/std.h @@ -214,32 +214,38 @@ struct formatter< std::size_t size = 0; std::unique_ptr demangled_name_ptr( abi::__cxa_demangle(ti.name(), nullptr, &size, &status), &std::free); - string_view demangled_name_view( - demangled_name_ptr ? demangled_name_ptr.get() : ti.name()); - // Normalization of stdlib inline namespace names. - if (demangled_name_view.starts_with("std::")) { - // Separation of user's and system exception classes. - demangled_name_view.remove_prefix(5); - out = detail::write_bytes(out, string_view("std::"), spec); + string_view demangled_name_view; + if (demangled_name_ptr) { + demangled_name_view = demangled_name_ptr.get(); + // Normalization of stdlib inline namespace names. // libc++ inline namespaces. - // std::__1::* -> std::* - // std::__1::__fs::* -> std::* - if (demangled_name_view.starts_with("__1::")) { - demangled_name_view.remove_prefix(5); - if (demangled_name_view.starts_with("__fs::")) - demangled_name_view.remove_prefix(6); - } + // std::__1::* -> std::* + // std::__1::__fs::* -> std::* // libstdc++ inline namespaces. - // std::__cxx11::* -> std::* - // std::filesystem::__cxx11::* -> std::filesystem::* - else if (demangled_name_view.starts_with("__cxx11::")) { - demangled_name_view.remove_prefix(9); - } else if (demangled_name_view.starts_with("filesystem::__cxx11::")) { - demangled_name_view.remove_prefix(21); - out = detail::write_bytes(out, string_view("filesystem::"), spec); + // std::__cxx11::* -> std::* + // std::filesystem::__cxx11::* -> std::filesystem::* + if (demangled_name_view.starts_with("std::")) { + char* begin = demangled_name_ptr.get(); + char* to = begin + 5; // std:: + for (char *from = to, *end = begin + demangled_name_view.size(); + from < end;) { + // This is safe, because demangled_name is NUL-terminated. + if (from[0] == '_' && from[1] == '_') { + char* next = from + 1; + while (next < end && *next != ':') next++; + if (next[0] == ':' && next[1] == ':') { + from = next + 2; + continue; + } + } + *to++ = *from++; + } + demangled_name_view = {begin, detail::to_unsigned(to - begin)}; } + } else { + demangled_name_view = string_view(ti.name()); } out = detail::write_bytes(out, demangled_name_view, spec); #elif FMT_MSC_VERSION