Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
format-obj.cpp
Go to the documentation of this file.
1/*
2 FormatObj - simple means to display an object
3
4 Copyright (C)
5 2016, Hermann Vosseler <Ichthyostega@web.de>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11
12* *****************************************************************/
13
34#include "lib/error.hpp"
35#include "lib/format-obj.hpp"
36#include "lib/ios-savepoint.hpp"
37//#include "lib/format-string.hpp"
39#include "lib/symbol.hpp"
40#include "lib/util.hpp"
41
42#ifdef __GNUG__
43#include <cxxabi.h>
44#endif
45
46#include <limits>
47#include <iomanip>
48#include <sstream>
49#include <string>
50#include <regex>
51
52//using util::_Fmt;
55using util::isnil;
56using std::string;
57
58using std::regex;
59using std::regex_replace;
60
61
62namespace { // hard-wired configuration for debugging output....
63
64 // precision for rendering of double values
67
70
71
73 template<typename F>
74 constexpr size_t PRECISION_DECIMAL = std::numeric_limits<F>::digits10;
75
77 template<typename F>
78 constexpr size_t PRECISION_COMPLETE = std::numeric_limits<F>::max_digits10;
79}
80
81
82
83namespace lib {
84namespace meta {
85
86 // pre-allocated failure indicators, which can be returned failsafe.
87
88 extern const string BOTTOM_INDICATOR = "⟂";
89 extern const string FAILURE_INDICATOR = "↯";
90 extern const string VOID_INDICATOR = "void";
91 extern const string FUNCTION_INDICATOR= "Function";
92
93 extern const string BOOL_FALSE_STR = "false";
94 extern const string BOOL_TRUE_STR = "true";
95
96
97
98#ifdef __GNUG__
136 string
137 demangleCxx (Literal rawName)
138 {
139 int error = -4;
140 UniqueMallocOwner<char> demangled (abi::__cxa_demangle (rawName,
141 NULL,
142 NULL,
143 &error));
144 return 0==error? demangled.get()
145 : string(rawName);
146 }
147
148
149#else
150#warning "Lumiera was _not_ built with a GCC compatible compiler."
151#warning "There are good chances this works without problems, but up to now, \
152the Lumiera developers lacked the resources to investigate that option; \
153apologies for that."
154
158 string
160 {
161 return string (rawName);
162 }
163#endif
164
165
166
167
168
189 string
191 {
192 string typeName = demangleCxx (rawType);
193
194 #define TYP_EXP "[\\w<>\\(\\):,\\s]+"
195
196 static regex commonPrefixes {"std::"
197 "|(\\w+::)+\\(anonymous namespace\\)::"
198 "|lib::meta::"
199 "|lib::time::"
200 "|lib::test::"
201 "|lib::diff::"
202 "|lib::"
203 "|util::"
204 "|steam::(asset::|mobject::(session::)?|play::)?"
205 "|stage::model"
206 "|stage::ctrl"
207 "|lumiera::"
208 , regex::ECMAScript | regex::optimize};
209
210 static regex lolong {"long long"
211 , regex::ECMAScript | regex::optimize};
212 static regex unSigned {"unsigned (\\w+)"
213 , regex::ECMAScript | regex::optimize};
214
215 static regex stdString {"(__cxx11::)?basic_string<char, char_traits<char>, allocator<char>\\s*>(\\s+\\B)?"
216 , regex::ECMAScript | regex::optimize};
217
218 static regex stdAllocator {"(\\w+<(" TYP_EXP ")), allocator<\\2>\\s*"
219 , regex::ECMAScript | regex::optimize};
220
221 static regex mapAllocator {"(map<(" TYP_EXP "), (" TYP_EXP ")),.+allocator<pair<\\2 const, \\3>\\s*>\\s*"
222 , regex::ECMAScript | regex::optimize};
223
224 static regex uniquePtr {"unique_ptr<(\\w+), default_delete<\\1>\\s*"
225 , regex::ECMAScript | regex::optimize};
226
227 static regex lumieraP {"P<(\\w+), shared_ptr<\\1>\\s*"
228 , regex::ECMAScript | regex::optimize};
229
230
231 auto pos = typeName.begin();
232 auto end = typeName.end();
233
234 end = regex_replace(pos, pos, end, commonPrefixes, "");
235 end = regex_replace(pos, pos, end, lolong, "llong");
236 end = regex_replace(pos, pos, end, unSigned, "u$1");
237 end = regex_replace(pos, pos, end, stdString, "string");
238 end = regex_replace(pos, pos, end, stdAllocator, "$1");
239 end = regex_replace(pos, pos, end, mapAllocator, "$1");
240 end = regex_replace(pos, pos, end, uniquePtr, "unique_ptr<$1");
241 end = regex_replace(pos, pos, end, lumieraP, "P<$1");
242
243 typeName.resize(end - typeName.begin());
244 return typeName;
245 }
246
247
248
267 string
269 {
270 string typeStr = demangleCxx (rawType);
271
272 removeSuffix (typeStr, " const");
273 removeSuffix (typeStr, " const *");
274 removeSuffix (typeStr, "*");
275 removeSuffix (typeStr, "&");
276
277 if (isnil (typeStr)) return VOID_INDICATOR;
278 if (')' == typeStr.back()) return FUNCTION_INDICATOR;
279
280 auto end = typeStr.end();
281 auto beg = typeStr.begin();
282 int level=0;
283 while (--end != beg)
284 {
285 if ('>' == *end)
286 ++level;
287 else if ('<' == *end and level>0)
288 --level;
289 else
290 if (level==0)
291 {
292 ++end;
293 break;
294 }
295 }
296 if (end == beg) return VOID_INDICATOR;
297
298 auto pos = typeStr.rfind("::", end-beg);
299 typeStr = (pos==string::npos? typeStr.substr(0, end-beg)
300 : typeStr.substr(pos+2, (end-beg)-pos-2));
301 return typeStr;
302 }
303
304
305 string
310
311
312 string
313 sanitisedSymbol (string const& text)
314 {
315 static regex identifierChars {"[A-Za-z]\\w*", regex::ECMAScript | regex::optimize};
316
317 return regex_replace (text, identifierChars, "$&", std::regex_constants::format_no_copy);
318 } // don't copy what does not match
319
320
321
322}}// namespace lib::meta
323
324
325
326
327
328/* === formatting and pretty printing support utils === */
329
330namespace util {
331
332 using std::hex;
333 using std::setw;
334 using std::right;
335 using std::setfill;
336 using std::uppercase;
337 using std::noshowbase;
338 using std::ostringstream;
339 using std::ostream;
340
341 template<typename F>
342 string
343 showFloatingPoint (F val, size_t precision) noexcept
344 try {
345 ostringstream buffer;
346 buffer.precision (precision);
347 buffer << val;
348 return buffer.str();
349 }
350 catch(...)
351 { return FAILURE_INDICATOR; }
352
360 string showDouble (double val) noexcept { return showFloatingPoint (val, DIAGNOSTICS_DOUBLE_PRECISION); }
361 string showFloat (float val) noexcept { return showFloatingPoint (val, DIAGNOSTICS_FLOAT_PRECISION); }
362
363 string showDecimal (double val) noexcept { return showFloatingPoint (val, PRECISION_DECIMAL<double>); }
364 string showDecimal (float val) noexcept { return showFloatingPoint (val, PRECISION_DECIMAL<float>); }
365 string showDecimal (f128 val) noexcept { return showFloatingPoint (val, PRECISION_DECIMAL<f128>); }
366
367 string showComplete (double val) noexcept { return showFloatingPoint (val, PRECISION_COMPLETE<double>); }
368 string showComplete (float val) noexcept { return showFloatingPoint (val, PRECISION_COMPLETE<float>); }
369 string showComplete (f128 val) noexcept { return showFloatingPoint (val, PRECISION_COMPLETE<f128>); }
370
371
372 string
373 showSize (size_t val) noexcept
374 try {
375 ostringstream buffer;
376 buffer << val;
377 return buffer.str();
378 }
379 catch(...)
380 { return FAILURE_INDICATOR; }
381
382
384 ostream&
385 showAdr (ostream& stream, void const* addr)
386 {
387 IosSavepoint save{stream};
388 size_t suffix_modulus = size_t(1) << DIAGNOSTICS_ADDRESS_SUFFIX_LEN * 8;
389 return stream << "╲"
390 << hex
391 << noshowbase
392 << setw (DIAGNOSTICS_ADDRESS_SUFFIX_LEN * 2) // need 2 hex digits per byte
393 << setfill('_')
394 << right
395 << size_t(addr) % suffix_modulus;
396 }
397
398
399 string
400 showAdr (void const* addr) noexcept
401 try {
402 ostringstream buffer;
403 showAdr (buffer, addr);
404 return buffer.str();
405 }
406 catch(...)
407 { return FAILURE_INDICATOR; }
408
409
410 string
411 showHash (size_t hash, uint showBytes) noexcept
412 try {
413 showBytes = util::limited (1u, showBytes, 8u);
414 size_t suffix_modulus = size_t(1) << showBytes * 8;
415 ostringstream buffer;
416 buffer << hex
417 << uppercase
418 << noshowbase
419 << setw (showBytes * 2) // need 2 hex digits per byte
420 << setfill('0')
421 << right
422 << (showBytes==8? hash : hash % suffix_modulus);
423 return buffer.str();
424 }
425 catch(...)
426 { return FAILURE_INDICATOR; }
427
428
429
430} // namespace util
Inline string literal.
Definition symbol.hpp:78
RAII helper to capture and restore output stream format settings.
Lumiera error handling (C++ interface).
#define TYP_EXP
Simple functions to represent objects, for debugging and diagnostics.
#define hash
unsigned int uint
Definition integral.hpp:29
long double f128
Definition integral.hpp:36
Capture previous settings of an std::ostream and restore them when leaving scope.
return NULL
Definition llist.h:586
const size_t DIAGNOSTICS_ADDRESS_SUFFIX_LEN
show only this amount of trailing bytes from an address
constexpr size_t PRECISION_DECIMAL
maximum decimal digits able to pass through a round trip without value change
constexpr size_t PRECISION_COMPLETE
decimal digits required to represent each different floating-point value completely
string sanitisedFullTypeName(lib::Literal rawName)
build a sanitised ID from full type name
std::string typeStr(TY const *obj=nullptr) noexcept
failsafe human readable type display
const string FUNCTION_INDICATOR
const string BOOL_TRUE_STR
string humanReadableTypeID(Literal rawType)
pretty-print an internal C++ type representation
string primaryTypeComponent(Literal rawType)
extract core name component from a raw type spec
enable_if_c< Cond::value, T >::type enable_if
SFINAE helper to control the visibility of specialisations and overloads.
Definition meta/util.hpp:87
string sanitisedSymbol(string const &text)
condense a string and retain only valid identifiers
string demangleCxx(Literal rawName)
Fallback type-ID:
const string VOID_INDICATOR
const string BOTTOM_INDICATOR
const string BOOL_FALSE_STR
const string FAILURE_INDICATOR
Implementation namespace for support and library code.
basic_ostream< char, char_traits< char > > ostream
string showComplete(double val) noexcept
show enough decimal digits to represent every distinct value
string showDouble(double val) noexcept
pretty-print a double in (rounded) fixed-point format
string showFloatingPoint(F val, size_t precision) noexcept
std::string sanitise(std::string const &)
produce an identifier based on the given string.
Definition util.cpp:57
string showHash(size_t hash, uint showBytes) noexcept
renders the size_t in hex, optionally only trailing bytes
ostream & showAdr(ostream &stream, void const *addr)
preconfigured format for pretty-printing of addresses
string showSize(size_t val) noexcept
string showDecimal(double val) noexcept
show maximum reproducible decimal representation
void removeSuffix(string &str, string const &suffix)
Definition util.hpp:220
constexpr NUM limited(NB lowerBound, NUM val, NB upperBound)
force a numeric to be within bounds, inclusively
Definition util.hpp:91
string showFloat(float val) noexcept
void removePrefix(string &str, string const &prefix)
Definition util.hpp:213
bool isnil(lib::time::Duration const &dur)
Marker types to indicate a literal string and a Symbol.
Helper to deal with C-MALLOCed memory automatically.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...