Skip to content

Commit

Permalink
Add class name output to formatter for std::exception
Browse files Browse the repository at this point in the history
Signed-off-by: Vladislav Shchapov <vladislav@shchapov.ru>
  • Loading branch information
phprus committed Sep 2, 2022
1 parent 56c72a6 commit b187daf
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 16 deletions.
12 changes: 12 additions & 0 deletions include/fmt/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,18 @@ template <typename Char> class basic_string_view {
size_ -= n;
}

FMT_CONSTEXPR_CHAR_TRAITS bool starts_with(
basic_string_view<Char> sv) const noexcept {
return size_ >= sv.size_ &&
std::char_traits<Char>::compare(data_, sv.data_, sv.size_) == 0;
}
FMT_CONSTEXPR_CHAR_TRAITS bool starts_with(Char c) const noexcept {
return size_ >= 1 && std::char_traits<Char>::eq(*data_, c);
}
FMT_CONSTEXPR_CHAR_TRAITS bool starts_with(const Char* s) const {
return starts_with(basic_string_view<Char>(s));
}

// Lexicographically compare this string reference to other.
FMT_CONSTEXPR_CHAR_TRAITS auto compare(basic_string_view other) const -> int {
size_t str_size = size_ < other.size_ ? size_ : other.size_;
Expand Down
41 changes: 40 additions & 1 deletion include/fmt/std.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@
#ifndef FMT_STD_H_
#define FMT_STD_H_

#include <cstdlib>
#include <exception>
#include <memory>
#include <thread>
#include <type_traits>
#include <typeinfo>
#include <utility>

#include "ostream.h"
Expand All @@ -28,6 +31,16 @@
# endif
#endif

#if FMT_HAS_INCLUDE(<cxxabi.h>)
# include <cxxabi.h>
# ifndef __GABIXX_CXXABI_H__
# define FMT_HAS_CXXABI_H 1
# endif
#endif
#ifndef FMT_HAS_CXXABI_H
# define FMT_HAS_CXXABI_H 0
#endif

#ifdef __cpp_lib_filesystem
FMT_BEGIN_NAMESPACE

Expand Down Expand Up @@ -178,7 +191,33 @@ struct formatter<
template <typename FormatContext>
auto format(const std::exception& ex, FormatContext& ctx) const ->
typename FormatContext::iterator {
return fmt::formatter<string_view>::format(ex.what(), ctx);
basic_memory_buffer<Char> msg;
const std::type_info& ti = typeid(ex);
#if FMT_HAS_CXXABI_H
int status = 0;
std::size_t size = 0;
std::unique_ptr<char, decltype(std::free)*> demangled_name(
abi::__cxa_demangle(ti.name(), nullptr, &size, &status), std::free);
if (demangled_name) {
msg.append(string_view(demangled_name.get()));
} else {
msg.append(string_view(ti.name()));
}
#elif FMT_MSC_VERSION
string_view sv(ti.name());
if (sv.starts_with("class "))
sv.remove_prefix(6);
else if (sv.starts_with("struct "))
sv.remove_prefix(7);
msg.append(sv);
#else
msg.append(string_view(ti.name()));
#endif
msg.append(string_view(": "));
msg.append(string_view(ex.what()));

return fmt::formatter<string_view>::format(
basic_string_view<Char>(msg.data(), msg.size()), ctx);
}
};
FMT_END_NAMESPACE
Expand Down
33 changes: 18 additions & 15 deletions test/std-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
#include <vector>

#include "fmt/ranges.h"
#include "gtest/gtest.h"
#include "gtest-extra.h"

using testing::Contains;

TEST(std_test, path) {
#ifdef __cpp_lib_filesystem
Expand Down Expand Up @@ -78,21 +80,22 @@ TEST(std_test, variant) {
#endif
}

TEST(std_test, exception) {
std::string str("Test Exception");
std::string escstr = fmt::format("\"{}\"", str);

template <typename Catch> void exception_test() {
try {
throw std::runtime_error(str);
} catch (const std::exception& ex) {
EXPECT_EQ(fmt::format("{}", ex), str);
EXPECT_EQ(fmt::format("{:?}", ex), escstr);
throw std::runtime_error("Test Exception");
} catch (const Catch& ex) {
// St13runtime_error - libstdc++ with old ABI.
EXPECT_THAT((std::vector<std::string>{"std::runtime_error: Test Exception",
"St13runtime_error: Test Exception"}),
Contains(fmt::format("{}", ex)));
EXPECT_THAT(
(std::vector<std::string>{"\"std::runtime_error: Test Exception\"",
"\"St13runtime_error: Test Exception\""}),
Contains(fmt::format("{:?}", ex)));
}
}

try {
throw std::runtime_error(str);
} catch (const std::runtime_error& ex) {
EXPECT_EQ(fmt::format("{}", ex), str);
EXPECT_EQ(fmt::format("{:?}", ex), escstr);
}
TEST(std_test, exception) {
exception_test<std::exception>();
exception_test<std::runtime_error>();
}

0 comments on commit b187daf

Please sign in to comment.