From daeda942adc6c534d9427b45621617b0c8ae50e0 Mon Sep 17 00:00:00 2001 From: Johannes Kapfhammer Date: Sun, 6 Oct 2019 20:56:37 +0200 Subject: [PATCH] use runtime function to pretty print type name --- example.cpp | 2 + include/bits/soi-dbg.hpp | 143 +++++++++++++++------------------------ 2 files changed, 57 insertions(+), 88 deletions(-) diff --git a/example.cpp b/example.cpp index 9281c42..b2c81d9 100644 --- a/example.cpp +++ b/example.cpp @@ -15,5 +15,7 @@ signed main() { dbg(vector>>{{3,{"hi"}},{4,{"hello", "world"}}}); dbg(set{3,1,4}); dbg(map{{3,"three"},{1,"one"}}); + dbg(unordered_map{{3,"three"},{1,"one"}}); + dbg(unordered_set{3,1,4}); cout << "hi\n"; } diff --git a/include/bits/soi-dbg.hpp b/include/bits/soi-dbg.hpp index cbb47a4..346b3ee 100644 --- a/include/bits/soi-dbg.hpp +++ b/include/bits/soi-dbg.hpp @@ -17,6 +17,12 @@ #include #include +#ifdef __GNUG__ +#include +#include +#include +#endif + #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) #include #endif @@ -28,102 +34,63 @@ namespace soi { namespace detail { // ---------------------------------------------------------------------------- -// detecting the type name: https://stackoverflow.com/a/20170989 +// pretty printing the type name -#ifndef _MSC_VER -#if __cplusplus < 201103 -#define CONSTEXPR11_TN -#define CONSTEXPR14_TN -#define NOEXCEPT_TN -#elif __cplusplus < 201402 -#define CONSTEXPR11_TN constexpr -#define CONSTEXPR14_TN -#define NOEXCEPT_TN noexcept -#else -#define CONSTEXPR11_TN constexpr -#define CONSTEXPR14_TN constexpr -#define NOEXCEPT_TN noexcept -#endif -#else // _MSC_VER -#if _MSC_VER < 1900 -#define CONSTEXPR11_TN -#define CONSTEXPR14_TN -#define NOEXCEPT_TN -#elif _MSC_VER < 2000 -#define CONSTEXPR11_TN constexpr -#define CONSTEXPR14_TN -#define NOEXCEPT_TN noexcept -#else -#define CONSTEXPR11_TN constexpr -#define CONSTEXPR14_TN constexpr -#define NOEXCEPT_TN noexcept -#endif -#endif // _MSC_VER -class static_string { - const char *const p_; - const std::size_t sz_; - -public: - typedef const char *const_iterator; - - template - CONSTEXPR11_TN static_string(const char (&a)[N]) NOEXCEPT_TN : p_(a), - sz_(N - 1) {} - - CONSTEXPR11_TN static_string(const char *p, std::size_t N) NOEXCEPT_TN - : p_(p), - sz_(N) {} - - CONSTEXPR11_TN const char *data() const NOEXCEPT_TN { return p_; } - CONSTEXPR11_TN std::size_t size() const NOEXCEPT_TN { return sz_; } - - CONSTEXPR11_TN const_iterator begin() const NOEXCEPT_TN { return p_; } - CONSTEXPR11_TN const_iterator end() const NOEXCEPT_TN { return p_ + sz_; } - - CONSTEXPR11_TN char operator[](std::size_t n) const { - return n < sz_ ? p_[n] : throw std::out_of_range("static_string"); - } +struct string_view +{ + char const* data; + std::size_t size; }; -inline std::ostream &operator<<(std::ostream &os, static_string const &s) { - return os.write(s.data(), s.size()); +template +constexpr string_view get_name() +{ + char const* p = __PRETTY_FUNCTION__; + while (*p++ != '='); + for (; *p == ' '; ++p); + char const* p2 = p; + int count = 1; + for (;;++p2) + { + switch (*p2) + { + case '[': + ++count; + break; + case ']': + --count; + if (!count) + return {p, std::size_t(p2 - p)}; + } + } + return {}; } -template CONSTEXPR14_TN static_string type_name() { - const int k = sizeof("constexpr soi::detail:: T") / sizeof(char); -#ifdef __clang__ - static_string p = __PRETTY_FUNCTION__; - return static_string(p.data() + 31 + k, p.size() - 31 - k - 1); -#elif defined(__GNUC__) - static_string p = __PRETTY_FUNCTION__; -#if __cplusplus < 201402 - return static_string(p.data() + 36 + k, p.size() - 36 - k - 1); -#else - return static_string(p.data() + 46 + k, p.size() - 46 - k - 1); -#endif -#elif defined(_MSC_VER) - static_string p = __FUNCSIG__; - return static_string(p.data() + 38 + k, p.size() - 38 - k - 7); -#endif +std::string replace_all(std::string str, const std::string& from, const std::string& to) { + size_t start_pos = 0; + while((start_pos = str.find(from, start_pos)) != std::string::npos) { + str.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + return str; } -constexpr bool is_prefix_of(char const *suffix, char const *s) { - return suffix[0] == '\0' || - (suffix[0] == s[0] && is_prefix_of(suffix + 1, s + 1)); +std::string sanitize_type(std::string s) { + auto f = [&](const char *a, const char *b) { + s = replace_all(std::move(s), a, b); + }; + f("std::", ""); + f("__debug::", ""); + f("__cxx11::", ""); + f("basic_string", "string"); + f("long int", "int"); + return s; } -static char const *const type_string = "string"; - -template CONSTEXPR14_TN static_string sanitized_type_name() { - CONSTEXPR14_TN static_string t = type_name(); - CONSTEXPR14_TN std::size_t offset = - is_prefix_of("std::__debug::", t.data()) - ? sizeof("std::__debug::") - 1 - : is_prefix_of("std::", t.data()) ? sizeof("std::") - 1 : 0; - return is_prefix_of("std::__cxx11::basic_string", t.data()) - ? static_string(type_string, sizeof(type_string) - 2) - : static_string(t.data() + offset, t.size() - offset); +template std::string sanitized_type_name() { + auto t = get_name(); + return sanitize_type(std::string(t.data, t.size)); } // ---------------------------------------------------------------------------- @@ -191,7 +158,7 @@ void dbg_init() { dbg_init(are_colors_enabled()); } // printer template -T &&dbg_print(T &&value, static_string const &type, char const *file, int line, +T &&dbg_print(T &&value, std::string const &type, char const *file, int line, char const *function_name, char const *expression) { const T &ref = value; std::stringstream @@ -208,7 +175,7 @@ T &&dbg_print(T &&value, static_string const &type, char const *file, int line, } template -auto dbg_print(const char (&msg)[N], static_string const &, char const *file, +auto dbg_print(const char (&msg)[N], std::string const &, char const *file, int line, char const *function_name, char const *expression) -> decltype(msg) { std::cerr << ANSI_DEBUG << "[" << file << ":" << line << " (" << function_name