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:
Fischlurch 2016-01-10 11:21:34 +01:00
parent b56f5a8945
commit e518a19435
13 changed files with 153 additions and 83 deletions

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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_);

View file

@ -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);
}
};

View file

@ -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--

View file

@ -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

View file

@ -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;
}

View file

@ -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>

View file

@ -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)" );
}

View file

@ -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__");
}
};

View file

@ -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));

View file

@ -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;
}
};