forked from fmtlib/fmt
Added std::type_info formatter (#3978)
* 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.
This commit is contained in:
@@ -416,36 +416,11 @@ 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;
|
|
||||||
|
|
||||||
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
|
#if FMT_USE_RTTI
|
||||||
const std::type_info& ti = typeid(ex);
|
namespace detail {
|
||||||
|
|
||||||
|
template <typename Char, typename OutputIt>
|
||||||
|
auto write_demangled_name(OutputIt out, const std::type_info& ti) -> OutputIt {
|
||||||
# ifdef FMT_HAS_ABI_CXA_DEMANGLE
|
# ifdef FMT_HAS_ABI_CXA_DEMANGLE
|
||||||
int status = 0;
|
int status = 0;
|
||||||
std::size_t size = 0;
|
std::size_t size = 0;
|
||||||
@@ -484,22 +459,85 @@ struct formatter<
|
|||||||
} else {
|
} else {
|
||||||
demangled_name_view = string_view(ti.name());
|
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
|
# elif FMT_MSC_VERSION
|
||||||
string_view demangled_name_view(ti.name());
|
const string_view demangled_name(ti.name());
|
||||||
if (demangled_name_view.starts_with("class "))
|
for (std::size_t i = 0; i < demangled_name.size(); ++i) {
|
||||||
demangled_name_view.remove_prefix(6);
|
auto sub = demangled_name;
|
||||||
else if (demangled_name_view.starts_with("struct "))
|
sub.remove_prefix(i);
|
||||||
demangled_name_view.remove_prefix(7);
|
if (sub.starts_with("enum ")) {
|
||||||
out = detail::write_bytes<Char>(out, demangled_name_view);
|
i += 4;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (sub.starts_with("class ") || sub.starts_with("union ")) {
|
||||||
|
i += 5;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (sub.starts_with("struct ")) {
|
||||||
|
i += 6;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*sub.begin() != ' ') *out++ = *sub.begin();
|
||||||
|
}
|
||||||
|
return out;
|
||||||
# else
|
# else
|
||||||
out = detail::write_bytes<Char>(out, string_view(ti.name())
|
return detail::write_bytes<Char>(out, string_view(ti.name()));
|
||||||
});
|
|
||||||
# endif
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
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()) {
|
||||||
|
return ctx.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Context>
|
||||||
|
auto format(const std::type_info& ti, Context& ctx) const
|
||||||
|
-> decltype(ctx.out()) {
|
||||||
|
return detail::write_demangled_name<Char>(ctx.out(), ti);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#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 FMT_USE_RTTI
|
||||||
|
if (with_typename_) {
|
||||||
|
out = detail::write_demangled_name<Char>(out, typeid(ex));
|
||||||
*out++ = ':';
|
*out++ = ':';
|
||||||
*out++ = ' ';
|
*out++ = ' ';
|
||||||
return detail::write_bytes<Char>(out, string_view(ex.what()));
|
}
|
||||||
#endif
|
#endif
|
||||||
|
return detail::write_bytes<Char>(out, string_view(ex.what()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -300,6 +300,13 @@ TEST(std_test, exception) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if FMT_USE_RTTI
|
||||||
|
TEST(std_test, type_info) {
|
||||||
|
EXPECT_EQ(fmt::format("{}", typeid(std::runtime_error)),
|
||||||
|
"std::runtime_error");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
TEST(std_test, format_bit_reference) {
|
TEST(std_test, format_bit_reference) {
|
||||||
std::bitset<2> bs(1);
|
std::bitset<2> bs(1);
|
||||||
EXPECT_EQ(fmt::format("{} {}", bs[0], bs[1]), "true false");
|
EXPECT_EQ(fmt::format("{} {}", bs[0], bs[1]), "true false");
|
||||||
|
Reference in New Issue
Block a user