Skip to content

Commit

Permalink
Added std::type_info formatter
Browse files Browse the repository at this point in the history
* Added std::type_info formatter;
* Reused std::type_info formatter in std::exception formatters;
* Updated MSVC std::type_info outputting to exclude all class, struct and enum occurences.
  • Loading branch information
matt77hias committed May 25, 2024
1 parent 1768bf9 commit cb58b68
Showing 1 changed file with 72 additions and 31 deletions.
103 changes: 72 additions & 31 deletions include/fmt/std.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
# include <cstdlib>
# include <exception>
# include <memory>
# include <string>
# include <thread>
# include <type_traits>
# include <typeinfo>
Expand Down Expand Up @@ -416,36 +417,34 @@ template <typename Char> struct formatter<std::error_code, Char> {
}
};

FMT_EXPORT
template <typename T, typename Char>
struct formatter<
T, Char, // DEPRECATED! Mixing code unit types.
typename std::enable_if<std::is_base_of<std::exception, T>::value>::type> {
private:
bool with_typename_ = false;
#if FMT_USE_RTTI
namespace details {
template <typename Char>
inline void remove_all_substrings(
std::basic_string<Char>& src,
type_identity_t<basic_string_view<Char>> pattern) {
const auto pattern_length = pattern.size();
for (auto i = src.find(pattern.data(), 0, pattern_length);
i != std::basic_string<Char>::npos;
i = src.find(pattern.data(), 0, pattern_length))
src.erase(i, pattern_length);
}
} // namespace details

FMT_EXPORT
template <typename Char>
struct formatter<std::type_info, Char // DEPRECATED! Mixing code unit types.
> {
public:
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
-> decltype(ctx.begin()) {
auto it = ctx.begin();
auto end = ctx.end();
if (it == end || *it == '}') return it;
if (*it == 't') {
++it;
with_typename_ = FMT_USE_RTTI != 0;
}
return it;
return ctx.begin();
}

template <typename Context>
auto format(const std::exception& ex, Context& ctx) const
auto format(const std::type_info& ti, Context& ctx) const
-> decltype(ctx.out()) {
auto out = ctx.out();
if (!with_typename_)
return detail::write_bytes<Char>(out, string_view(ex.what()));

#if FMT_USE_RTTI
const std::type_info& ti = typeid(ex);
# ifdef FMT_HAS_ABI_CXA_DEMANGLE
int status = 0;
std::size_t size = 0;
Expand Down Expand Up @@ -484,22 +483,64 @@ struct formatter<
} else {
demangled_name_view = string_view(ti.name());
}
out = detail::write_bytes<Char>(out, demangled_name_view);
return detail::write_bytes<Char>(out, demangled_name_view);
# elif FMT_MSC_VERSION
string_view demangled_name_view(ti.name());
if (demangled_name_view.starts_with("class "))
demangled_name_view.remove_prefix(6);
else if (demangled_name_view.starts_with("struct "))
demangled_name_view.remove_prefix(7);
out = detail::write_bytes<Char>(out, demangled_name_view);
std::basic_string<Char> demangled_name(ti.name());
auto class_space =
detail::string_literal<Char, 'c', 'l', 'a', 's', 's', ' '>{};
auto enum_space = detail::string_literal<Char, 'e', 'n', 'u', 'm', ' '>{};
auto struct_space =
detail::string_literal<Char, 's', 't', 'r', 'u', 'c', 't', ' '>{};
auto union_space =
detail::string_literal<Char, 'u', 'n', 'i', 'o', 'n', ' '>{};
details::remove_all_substrings(demangled_name, class_space);
details::remove_all_substrings(demangled_name, enum_space);
details::remove_all_substrings(demangled_name, struct_space);
details::remove_all_substrings(demangled_name, union_space);
return detail::write_bytes<Char>(out, demangled_name);
# else
out = detail::write_bytes<Char>(out, string_view(ti.name())
});
return detail::write_bytes<Char>(out, string_view(ti.name()));
# endif
}
};
#endif

FMT_EXPORT
template <typename T, typename Char>
struct formatter<
T, Char, // DEPRECATED! Mixing code unit types.
typename std::enable_if<std::is_base_of<std::exception, T>::value>::type> {
private:
bool with_typename_ = false;

public:
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
-> decltype(ctx.begin()) {
auto it = ctx.begin();
auto end = ctx.end();
if (it == end || *it == '}') return it;
if (*it == 't') {
++it;
with_typename_ = FMT_USE_RTTI != 0;
}
return it;
}

template <typename Context>
auto format(const std::exception& ex, Context& ctx) const
-> decltype(ctx.out()) {
auto out = ctx.out();
if (!with_typename_)
return detail::write_bytes<Char>(out, string_view(ex.what()));

#if FMT_USE_RTTI
const std::type_info& ti = typeid(ex);
auto format_imag = detail::string_literal<Char, '{', '}'>{};
out = fmt::format_to(out, basic_string_view<Char>(format_imag), ti);
#endif
*out++ = ':';
*out++ = ' ';
return detail::write_bytes<Char>(out, string_view(ex.what()));
#endif
}
};

Expand Down

0 comments on commit cb58b68

Please sign in to comment.