From e518a19435759e40cdea8968981c5964bc2a3696 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 10 Jan 2016 11:21:34 +0100 Subject: [PATCH] wrap-up(#985): resolve various leftovers - replace remaining usages of typeid(T).name() - add another type simplification to handle the STL map allocator - clean-up usage in lib/format-string - complete the unit tests - fix some more bugs --- src/backend/engine/job.cpp | 2 +- src/lib/error-exception.cpp | 3 +- src/lib/format-obj.cpp | 10 +- src/lib/format-string.cpp | 9 +- src/lib/format-string.hpp | 9 +- src/lib/meta/size-trait.hpp | 4 +- src/lib/meta/util.hpp | 4 +- src/lib/query-util.hpp | 3 +- src/proc/asset/struct-scheme.hpp | 3 +- tests/library/format-helper-test.cpp | 119 +++++++++++++---------- tests/library/format-string-test.cpp | 12 +-- tests/library/meta/meta-utils-test.cpp | 13 +-- tests/library/meta/type-display-test.cpp | 45 +++++++-- 13 files changed, 153 insertions(+), 83 deletions(-) diff --git a/src/backend/engine/job.cpp b/src/backend/engine/job.cpp index 9dd53944b..b3b1c1513 100644 --- a/src/backend/engine/job.cpp +++ b/src/backend/engine/job.cpp @@ -137,7 +137,7 @@ namespace engine { JobClosure::hash_value (JobParameter parameter) const { HashVal hash = this->hashOfInstance (parameter.invoKey); - boost::hash_combine(hash, typeid(*this).name()); + boost::hash_combine(hash, typeid(*this).hash_code()); boost::hash_combine(hash, parameter.nominalTime); return hash; } diff --git a/src/lib/error-exception.cpp b/src/lib/error-exception.cpp index 3b94e7df5..2b8bf5cf9 100644 --- a/src/lib/error-exception.cpp +++ b/src/lib/error-exception.cpp @@ -33,6 +33,7 @@ #include "lib/error.hpp" +#include "lib/meta/util.hpp" #include "lib/util.hpp" #include @@ -60,7 +61,7 @@ namespace lumiera { default_usermsg (Error* exception_obj) throw() { return string("Sorry, Lumiera encountered an internal error. (") - + typeid(*exception_obj).name() + ")"; + + util::typeStr(*exception_obj) + ")"; } inline CStr diff --git a/src/lib/format-obj.cpp b/src/lib/format-obj.cpp index bbc84c24e..d9beae8b9 100644 --- a/src/lib/format-obj.cpp +++ b/src/lib/format-obj.cpp @@ -83,6 +83,7 @@ namespace meta { // pre-allocated failure indicators, which can be returned failsafe. + extern const string BOTTOM_INDICATOR = "⟂"; extern const string FAILURE_INDICATOR = "↯"; extern const string VOID_INDICATOR = "void"; extern const string FUNCTION_INDICATOR= "Function"; @@ -187,6 +188,7 @@ apologies for that." { string typeName = demangleCxx (rawType); + #define TYP_EXP "[\\w<>\\(\\):,\\s]+" static regex commonPrefixes {"std::" "|(\\w+::)+\\(anonymous namespace\\)::" @@ -206,7 +208,10 @@ apologies for that." "|lumiera::" , regex::ECMAScript | regex::optimize}; - static regex stdAllocator {"(\\w+<(\\w+)), allocator<\\2>\\s*" + static regex stdAllocator {"(\\w+<(" TYP_EXP ")), allocator<\\2>\\s*" + , regex::ECMAScript | regex::optimize}; + + static regex mapAllocator {"(map<(" TYP_EXP "), (" TYP_EXP ")),.+allocator\\s*>\\s*" , regex::ECMAScript | regex::optimize}; static regex lumieraP {"P<(\\w+), shared_ptr<\\1>\\s*" @@ -218,6 +223,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, lumieraP, "P<$1"); typeName.resize(end - typeName.begin()); @@ -276,7 +282,7 @@ apologies for that." if (end == beg) return VOID_INDICATOR; auto pos = typeStr.rfind("::", end-beg); - typeStr = (pos==string::npos? typeStr.substr(end-beg) + typeStr = (pos==string::npos? typeStr.substr(0, end-beg) : typeStr.substr(pos+2, (end-beg)-pos-2)); return typeStr; } diff --git a/src/lib/format-string.cpp b/src/lib/format-string.cpp index 769849b5e..7931833ab 100644 --- a/src/lib/format-string.cpp +++ b/src/lib/format-string.cpp @@ -115,11 +115,16 @@ namespace util { * The actual implementation is delegated to an boost::format object, * which is placement-constructed into an opaque buffer embedded into * this object. Defining the necessary size for this buffer relies - * on a implementation details of boost::format (and might break) + * on implementation details of boost::format (and might break) + * @see lib::meta::SizeTrait::BOOST_FORMAT */ _Fmt::_Fmt (string formatString) try { - BOOST_STATIC_ASSERT (sizeof(boost::format) <= FORMATTER_SIZE); + static_assert (sizeof(boost::format) <= FORMATTER_SIZE, + "opaque working buffer insufficient " + "to hold a boost::format instance. " + "Maybe boost implementation change. " + "Please verify lib/meta/size-trait.hpp"); new(formatter_) boost::format(formatString); suppressInsufficientArgumentErrors (formatter_); diff --git a/src/lib/format-string.hpp b/src/lib/format-string.hpp index 24d842be0..aad237d72 100644 --- a/src/lib/format-string.hpp +++ b/src/lib/format-string.hpp @@ -109,9 +109,8 @@ #include "lib/meta/util.hpp" #include "lib/meta/size-trait.hpp" -#include -#include #include +#include @@ -324,7 +323,7 @@ namespace util { static void dump (VAL const&, Implementation& impl) { - format (string("«")+typeid(VAL).name()+"»", impl); + format ("«"+typeStr()+"»", impl); } }; @@ -337,7 +336,7 @@ namespace util { if (pVal) Converter::dump(*pVal, impl); else - format ("", impl); + format (BOTTOM_INDICATOR, impl); } }; @@ -357,7 +356,7 @@ namespace util { static void dump (const char* cString, Implementation& impl) { - format (cString? cString : FAILURE_INDICATOR, impl); + format (cString? cString : BOTTOM_INDICATOR, impl); } }; diff --git a/src/lib/meta/size-trait.hpp b/src/lib/meta/size-trait.hpp index 1abbb046b..5a0ff6907 100644 --- a/src/lib/meta/size-trait.hpp +++ b/src/lib/meta/size-trait.hpp @@ -123,11 +123,11 @@ namespace meta { int style_; int cur_arg_; int num_args_; - mutable bool dumped_; + mutable bool dumped_; std::string prefix_; unsigned char exceptions; BasicAltstringbuf buf_; - Optional loc_; + Optional loc_; }; //-------------------------------------mimicked-definitions-- diff --git a/src/lib/meta/util.hpp b/src/lib/meta/util.hpp index 8c13b3822..15735a923 100644 --- a/src/lib/meta/util.hpp +++ b/src/lib/meta/util.hpp @@ -219,6 +219,7 @@ namespace meta { extern const std::string FUNCTION_INDICATOR; extern const std::string FAILURE_INDICATOR; + extern const std::string BOTTOM_INDICATOR; extern const std::string VOID_INDICATOR; extern const std::string BOOL_FALSE_STR; @@ -302,6 +303,7 @@ namespace util { using lib::meta::typeStr; using lib::meta::FAILURE_INDICATOR; + using lib::meta::BOTTOM_INDICATOR; /** failsafe invocation of custom string conversion. @@ -360,7 +362,7 @@ namespace util { showPtr (X* ptr =nullptr) { return ptr? showAddr(ptr) + " ↗" + StringConv::invoke(*ptr) - : "⟂ «" + typeStr(ptr) + "»"; + : BOTTOM_INDICATOR + " «" + typeStr(ptr) + "»"; } /** human readable display of boolean values diff --git a/src/lib/query-util.hpp b/src/lib/query-util.hpp index 9a1de062a..092fe5dba 100644 --- a/src/lib/query-util.hpp +++ b/src/lib/query-util.hpp @@ -26,6 +26,7 @@ #include "lib/symbol.hpp" +#include "lib/meta/util.hpp" #include #include @@ -70,7 +71,7 @@ namespace lib { const string buildTypeID() { - string typeID (typeid(TY).name()); + string typeID {util::typeStr()}; normaliseID (typeID); return typeID; } diff --git a/src/proc/asset/struct-scheme.hpp b/src/proc/asset/struct-scheme.hpp index f9abc4127..15db48dbf 100644 --- a/src/proc/asset/struct-scheme.hpp +++ b/src/proc/asset/struct-scheme.hpp @@ -39,6 +39,7 @@ #include "lib/symbol.hpp" #include "proc/asset.hpp" #include "lib/idi/entry-id.hpp" +#include "lib/meta/util.hpp" #include "lib/format-string.hpp" #include @@ -137,7 +138,7 @@ namespace asset{ /* catch-all defaults */ template - Symbol StructTraits::idSymbol() { return typeid(X).name(); } ////////////////////TICKET #583 this default works but is ugly + Symbol StructTraits::idSymbol() { return lib::meta::typeSymbol(); } template Symbol StructTraits::catFolder(){ return idSymbol(); } template diff --git a/tests/library/format-helper-test.cpp b/tests/library/format-helper-test.cpp index 1f1702b47..13ec1fbb3 100644 --- a/tests/library/format-helper-test.cpp +++ b/tests/library/format-helper-test.cpp @@ -23,12 +23,10 @@ #include "lib/test/run.hpp" #include "lib/format-util.hpp" -#include "lib/format-cout.hpp" #include "lib/format-string.hpp" #include "lib/iter-adapter-stl.hpp" #include "lib/error.hpp" -#include #include #include @@ -40,44 +38,45 @@ using util::_Fmt; using std::vector; using std::string; using std::to_string; -using std::cout; -using std::endl; namespace util { namespace test { - class Reticent - { }; - - class UnReticent - : public Reticent - { - public: - operator string() const { return "hey Joe!"; } - }; - - - - class AutoCounter - { - static uint cnt; - - uint id_; - double d_; - - public: - AutoCounter(double d) - : id_(++cnt) - , d_(d*2) - { } - - operator string() const - { - return _Fmt("Nr.%02d(%3.1f)") % id_ % d_; - } - }; - uint AutoCounter::cnt = 0; + namespace { // test fixture... + + class Reticent + { }; + + class UnReticent + : public Reticent + { + public: + operator string() const { return "hey Joe!"; } + }; + + + + class AutoCounter + { + static uint cnt; + + uint id_; + double d_; + + public: + AutoCounter(double d) + : id_(++cnt) + , d_(d*2) + { } + + operator string() const + { + return _Fmt("Nr.%02d(%3.1f)") % id_ % d_; + } + }; + uint AutoCounter::cnt = 0; + } @@ -86,7 +85,7 @@ namespace test { * - util::toString() provides a failsafe to-String conversion, preferring * an built-in conversion, falling back to just a type string. * - util::join() combines elements from arbitrary containers or iterators - * into a string, relyint on aforementioned generic string conversion + * into a string, relying on aforementioned generic string conversion * @see format-util.hpp */ class FormatHelper_test @@ -105,20 +104,23 @@ namespace test { void check2String () { - std::cout << "Displaying some types....\n"; - Reticent closeLipped; UnReticent chatterer; - cout << toString (closeLipped) << endl; - cout << toString (chatterer) << endl; + CHECK (toString (closeLipped) == "«Reticent»" ); + CHECK (toString (chatterer) == "hey Joe!" ); - cout << toString (false) << endl; - cout << toString (12.34e55) << endl; - cout << toString (short(12)) - << toString (345L) - << toString ('X') - << endl; + CHECK (toString (&chatterer) == "«UnReticent»"); // string convertible => type display + CHECK (toString (nullptr) == "↯" ); // runtime exception, caught + + CHECK (toString (true) == "true" ); // special handling for bool + CHECK (toString (2+2 == 5) == "false" ); + CHECK (toString (12.34e55) == "1.234e+56" ); + + CHECK (toString (short(12)) + +toString (345L) + +toString ("67") + +toString ('8') == "12345678" ); // these go through lexical_cast } @@ -142,9 +144,28 @@ namespace test { std::function justCount = [](double d){ return AutoCounter(d); }; - cout << join(dubious, "--+--") << endl; - cout << join(transformIterator(eachElm(dubious) - ,justCount)) << endl; + CHECK (join (dubious, "--+--") + == "0--+--" + "1.1--+--" + "2.2--+--" + "3.3--+--" + "4.4--+--" + "5.5--+--" + "6.6--+--" + "7.7--+--" + "8.8--+--" + "9.9"); + CHECK (join (transformIterator(eachElm(dubious), justCount)) + == "Nr.01(0.0), " + "Nr.02(2.2), " + "Nr.03(4.4), " + "Nr.04(6.6), " + "Nr.05(8.8), " + "Nr.06(11.0), " + "Nr.07(13.2), " + "Nr.08(15.4), " + "Nr.09(17.6), " + "Nr.10(19.8)" ); } diff --git a/tests/library/format-string-test.cpp b/tests/library/format-string-test.cpp index 4b2c58aad..74408cddc 100644 --- a/tests/library/format-string-test.cpp +++ b/tests/library/format-string-test.cpp @@ -250,11 +250,11 @@ namespace test { Verbose& rv = x; - string mangledType = _Fmt("%s") % s; - cout << mangledType << endl; - CHECK (contains (mangledType, "util")); - CHECK (contains (mangledType, "test")); - CHECK (contains (mangledType, "Silent")); + string typeDisplay = _Fmt("%s") % s; + cout << typeDisplay << endl; + CHECK (contains (typeDisplay, "test")); + CHECK (contains (typeDisplay, "FormatString_test")); + CHECK (contains (typeDisplay, "Silent")); CHECK (_Fmt("!!%s!!") % v == "!!Number-013!!"); CHECK (_Fmt("!!%s!!") % x == "!!!!"); @@ -336,7 +336,7 @@ namespace test { pv = NULL; vv = NULL; - CHECK (_Fmt("__%s__") % pv == "____"); + CHECK (_Fmt("__%s__") % pv == "__"+BOTTOM_INDICATOR+"__"); CHECK (_Fmt("__%s__") % vv == "__0__"); } }; diff --git a/tests/library/meta/meta-utils-test.cpp b/tests/library/meta/meta-utils-test.cpp index 88aa359e1..e71123f61 100644 --- a/tests/library/meta/meta-utils-test.cpp +++ b/tests/library/meta/meta-utils-test.cpp @@ -53,7 +53,7 @@ namespace test { void run (Arg) { - verify_basicAssumptions(); + verify_basicTypeProbing(); verify_genericTypeDisplay(); detect_stringConversion(); @@ -61,13 +61,14 @@ namespace test { } - /** @test demonstrate / verify the - * basic type trait detection technique: - * By investigating the return type, we can - * figure out which overload the compiler picks.. + /** @test demonstrate the basic type trait detection technique: + * - we have two overloads with differing return type + * - we form a function call expression + * - by investigating the return type, + * we can figure out which overload the compiler picks. */ void - verify_basicAssumptions() + verify_basicTypeProbing() { CHECK (sizeof(Yes_t) != sizeof (No_t)); diff --git a/tests/library/meta/type-display-test.cpp b/tests/library/meta/type-display-test.cpp index 57a3405c4..55dc4a56b 100644 --- a/tests/library/meta/type-display-test.cpp +++ b/tests/library/meta/type-display-test.cpp @@ -73,10 +73,26 @@ namespace test{ * @test verify post processing of demangled C++ type names. * The purpose of those pretty printing functions is to support diagnostics * and unit testing by making type names easier to digest. But of course - * we do not want to pick the right primary type for shortened display + * we do not want to pick the wrong primary type for shortened display * and we do not want mess up the semantic structure. + * - the first example should be passed through unaltered + * - the second example demonstrates various simplifications + * * strip some frequent namespace prefixes + * ** `std::` + * ** `lib::meta::` + * ** `proc::mobject::` + * * omit the standard allocator from STL containers + * - the third example demonstrates an embedded function signature + * * the primary type component is "`function`" + * * anything leading up to anonymous namespaces will be stripped + * * our special smart-ptr lib::P will be simplified + * + * The remainder of the test concentrates on the corner cases of + * lib::meta::primaryTypeComponent -- especially when the solution + * approach breaks down, e.g. on pure function types. * * @see format-cout.hpp + * @see FormatCOUT_test * @see FormatHelper_test */ class TypeDisplay_test @@ -108,12 +124,29 @@ namespace test{ Outer ship; auto magic = ship.cloak; - cout << typeStr(&magic) <::Inner&&)"); + CHECK (typeSymbol(&magic) == "Function"); + + CHECK (typeStr ::Inner>() == "Outer::Inner"); + CHECK (typeSymbol::Inner>() == "Inner" ); + + CHECK (primaryTypeComponent("") == "void" ); + CHECK (primaryTypeComponent("Sym&") == "Sym" ); + CHECK (primaryTypeComponent("Sym const *") == "Sym" ); + CHECK (primaryTypeComponent("Sym const * const") == "Sym" ); + CHECK (primaryTypeComponent("Sym§$<>%&/'* const") == "Sym§$<>%&/'"); // adornments stripped, but rest retained as-is + CHECK (primaryTypeComponent("Sym§$<>%&/)&* const") == "Function" ); // types ending with braces are classified as "Function" + CHECK (primaryTypeComponent("Sym <§$&ää>") == "Sym " ); // note the trailing whitespace + CHECK (primaryTypeComponent("One<§$&ää>::Two") == "Two" ); + CHECK (primaryTypeComponent("One::Two<§$&ää>") == "Two" ); + CHECK (primaryTypeComponent("One::Two<§$&ää>") == "Two" ); + CHECK (primaryTypeComponent("Sym<") == "Sym<" ); // unbalanced braces + CHECK (primaryTypeComponent("Sym<>xx>") == "void" ); // opening brace never found + CHECK (primaryTypeComponent("xx>*") == "void" ); + CHECK (primaryTypeComponent("*") == "::Inner>() <