From cbe29fead3c80b816631da4497c8d7aa253aaa53 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 30 Jul 2016 23:19:21 +0200 Subject: [PATCH] Library: allow for pretty-printing of smart-ptr values - an extension to our custom toString and typeString helpers. - currently just for shared_ptr and unique_ptr - might add further overloads for other smart-ptr types --- src/lib/format-obj.cpp | 4 ++++ src/lib/format-obj.hpp | 12 +++++++++++ src/lib/format-string.hpp | 45 +++++++++++++++++++++++++++++++++++++++ src/lib/meta/util.hpp | 10 +++++++++ 4 files changed, 71 insertions(+) diff --git a/src/lib/format-obj.cpp b/src/lib/format-obj.cpp index d9beae8b9..5913f1f69 100644 --- a/src/lib/format-obj.cpp +++ b/src/lib/format-obj.cpp @@ -214,6 +214,9 @@ apologies for that." static regex mapAllocator {"(map<(" TYP_EXP "), (" TYP_EXP ")),.+allocator\\s*>\\s*" , regex::ECMAScript | regex::optimize}; + static regex uniquePtr {"unique_ptr<(\\w+), default_delete<\\1>\\s*" + , regex::ECMAScript | regex::optimize}; + static regex lumieraP {"P<(\\w+), shared_ptr<\\1>\\s*" , regex::ECMAScript | regex::optimize}; @@ -224,6 +227,7 @@ apologies for that." end = regex_replace(pos, pos, end, commonPrefixes, ""); end = regex_replace(pos, pos, end, stdAllocator, "$1"); end = regex_replace(pos, pos, end, mapAllocator, "$1"); + end = regex_replace(pos, pos, end, uniquePtr, "unique_ptr<$1"); end = regex_replace(pos, pos, end, lumieraP, "P<$1"); typeName.resize(end - typeName.begin()); diff --git a/src/lib/format-obj.hpp b/src/lib/format-obj.hpp index e0772ea6f..23486f000 100644 --- a/src/lib/format-obj.hpp +++ b/src/lib/format-obj.hpp @@ -95,6 +95,9 @@ namespace util { /** toggle to prefer specialisation with direct lexical conversion */ template using enable_LexicalConversion = lib::meta::enable_if< lib::meta::use_LexicalConversion>; + + template + using show_SmartPointer = lib::meta::enable_if< lib::meta::is_smart_ptr::TypeReferred>>; } @@ -111,6 +114,15 @@ namespace util { catch(...) { return FAILURE_INDICATOR; } }; + template + struct StringConv> + { + static std::string + invoke (SP const& smP) noexcept + try { return showSmartPtr (smP, lib::meta::typeSymbol(smP)); } + catch(...) { return FAILURE_INDICATOR; } + }; + /** explicit specialisation to control precision of double values. * @note we set an explicit precision, since this is a diagnostic facility * and we typically do not want to see all digits, but, for test code, diff --git a/src/lib/format-string.hpp b/src/lib/format-string.hpp index a7bc6b0ad..327f009a4 100644 --- a/src/lib/format-string.hpp +++ b/src/lib/format-string.hpp @@ -278,6 +278,33 @@ namespace util { }; }; + template + struct _is_smart_wrapper + : std::false_type + { }; + template + struct _is_smart_wrapper> + : std::true_type + { }; + template + struct _is_smart_wrapper> + : std::true_type + { }; + + + + template + struct _shall_show_smartWrapper + { + enum{ value = not _shall_convert_toString::value + and _is_smart_wrapper::type>::type>::value + }; + }; + + + + inline void _clear_errorflag() @@ -404,6 +431,24 @@ namespace util { } }; + template + struct _Fmt::Converter> > + { + static void + dump (SP const& smP, Implementation& impl) + try { + format (showSmartPtr (smP, lib::meta::typeSymbol(smP)), impl); + } + catch(std::exception const& ex) + { + format (_log_and_stringify(ex), impl); + } + catch(...) + { + format (_log_unknown_exception(), impl); + } + }; + /** some basic types are directly forwarded down to the implementation; * @note this requires explicit specialisations in format-string.cpp */ template diff --git a/src/lib/meta/util.hpp b/src/lib/meta/util.hpp index 0cdc3db58..77c631c11 100644 --- a/src/lib/meta/util.hpp +++ b/src/lib/meta/util.hpp @@ -374,6 +374,16 @@ namespace util { : BOTTOM_INDICATOR + " «" + typeStr(ptr) + "»"; } + template + inline std::string + showSmartPtr (SP const& smPtr, std::string label = "smP") + { + using TargetType = typename SP::element_type; + + return smPtr? label+"("+showAddr(smPtr.get()) + ") ↗" + StringConv::invoke(*smPtr) + : BOTTOM_INDICATOR + " «" + typeStr(smPtr) + "»"; + } + /** human readable display of boolean values * @return "`true`" or "`false`" */