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
This commit is contained in:
parent
b56f5a8945
commit
e518a19435
13 changed files with 153 additions and 83 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
|
||||
#include "lib/error.hpp"
|
||||
#include "lib/meta/util.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
#include <exception>
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<pair<\\2 const, \\3>\\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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_);
|
||||
|
|
|
|||
|
|
@ -109,9 +109,8 @@
|
|||
#include "lib/meta/util.hpp"
|
||||
#include "lib/meta/size-trait.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <string>
|
||||
|
||||
|
||||
|
||||
|
|
@ -324,7 +323,7 @@ namespace util {
|
|||
static void
|
||||
dump (VAL const&, Implementation& impl)
|
||||
{
|
||||
format (string("«")+typeid(VAL).name()+"»", impl);
|
||||
format ("«"+typeStr<VAL>()+"»", impl);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -337,7 +336,7 @@ namespace util {
|
|||
if (pVal)
|
||||
Converter<VAL>::dump(*pVal, impl);
|
||||
else
|
||||
format ("<null>", 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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Locale> loc_;
|
||||
Optional<Locale> loc_;
|
||||
};
|
||||
//-------------------------------------mimicked-definitions--
|
||||
|
||||
|
|
|
|||
|
|
@ -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<X>::invoke(*ptr)
|
||||
: "⟂ «" + typeStr(ptr) + "»";
|
||||
: BOTTOM_INDICATOR + " «" + typeStr(ptr) + "»";
|
||||
}
|
||||
|
||||
/** human readable display of boolean values
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
|
||||
#include "lib/symbol.hpp"
|
||||
#include "lib/meta/util.hpp"
|
||||
|
||||
#include <typeinfo>
|
||||
#include <string>
|
||||
|
|
@ -70,7 +71,7 @@ namespace lib {
|
|||
const string
|
||||
buildTypeID()
|
||||
{
|
||||
string typeID (typeid(TY).name());
|
||||
string typeID {util::typeStr<TY>()};
|
||||
normaliseID (typeID);
|
||||
return typeID;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 <cstdlib>
|
||||
|
|
@ -137,7 +138,7 @@ namespace asset{
|
|||
|
||||
/* catch-all defaults */
|
||||
template<class X>
|
||||
Symbol StructTraits<X>::idSymbol() { return typeid(X).name(); } ////////////////////TICKET #583 this default works but is ugly
|
||||
Symbol StructTraits<X>::idSymbol() { return lib::meta::typeSymbol<X>(); }
|
||||
template<class X>
|
||||
Symbol StructTraits<X>::catFolder(){ return idSymbol(); }
|
||||
template<class X>
|
||||
|
|
|
|||
|
|
@ -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 <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
|
|
@ -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<string>
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -142,9 +144,28 @@ namespace test {
|
|||
std::function<AutoCounter(double)> 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)" );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 == "!!<string conversion failed: LUMIERA_ERROR_STATE:unforeseen state (encountered Fantomas).>!!");
|
||||
|
|
@ -336,7 +336,7 @@ namespace test {
|
|||
|
||||
pv = NULL;
|
||||
vv = NULL;
|
||||
CHECK (_Fmt("__%s__") % pv == "__<null>__");
|
||||
CHECK (_Fmt("__%s__") % pv == "__"+BOTTOM_INDICATOR+"__");
|
||||
CHECK (_Fmt("__%s__") % vv == "__0__");
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Space> ship;
|
||||
auto magic = ship.cloak;
|
||||
cout << typeStr(&magic) <<endl;
|
||||
cout << typeSymbol(&magic) <<endl;
|
||||
CHECK (typeStr(&magic) == "Space const* (*)(Outer<Space>::Inner&&)");
|
||||
CHECK (typeSymbol(&magic) == "Function");
|
||||
|
||||
CHECK (typeStr <Outer<typeof(this)>::Inner>() == "Outer<test::TypeDisplay_test*>::Inner");
|
||||
CHECK (typeSymbol<Outer<typeof(this)>::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<<xx>") == "Sym<" ); // unbalanced braces
|
||||
CHECK (primaryTypeComponent("Sym<>xx>") == "void" ); // opening brace never found
|
||||
CHECK (primaryTypeComponent("<x>xx>*") == "void" );
|
||||
CHECK (primaryTypeComponent("<x<xx>*") == "<x" );
|
||||
|
||||
CHECK (sanitisedSymbol("bäälü9a/(6f*a☹☢☀s☭el_88☠") == "blafasel_88"); // note: picking up only valid identifier fragments
|
||||
|
||||
cout << typeStr<Outer<typeof(this)>::Inner>() <<endl;
|
||||
cout << sanitisedSymbol("") <<endl;
|
||||
cout << sanitisedSymbol("bääähla7/(6sf*z") <<endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue