Lumiera  0.pre.03
»edityourfreedom«
format-obj.cpp
Go to the documentation of this file.
1 /*
2  FormatObj - simple means to display an object
3 
4  Copyright (C) Lumiera.org
5  2016, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
43 #include "lib/error.hpp"
44 #include "lib/format-obj.hpp"
45 //#include "lib/format-string.hpp"
47 #include "lib/symbol.hpp"
48 #include "lib/util.hpp"
49 
50 #ifdef __GNUG__
51 #include <cxxabi.h>
52 #endif
53 
54 #include <iomanip>
55 #include <sstream>
56 #include <string>
57 #include <regex>
58 
59 //using util::_Fmt;
60 using util::removePrefix;
61 using util::removeSuffix;
62 using util::isnil;
63 using std::string;
64 
65 using std::regex;
66 using std::regex_replace;
67 
68 
69 namespace { // hard-wired configuration for debugging output....
70 
71  // precision for rendering of double values
72  const auto DIAGNOSTICS_DOUBLE_PRECISION = 8;
73  const auto DIAGNOSTICS_FLOAT_PRECISION = 5;
74 
76  const size_t DIAGNOSTICS_ADDRESS_SUFFIX_LEN = 4;
77 }
78 
79 
80 
81 namespace lib {
82 namespace meta {
83 
84  // pre-allocated failure indicators, which can be returned failsafe.
85 
86  extern const string BOTTOM_INDICATOR = "⟂";
87  extern const string FAILURE_INDICATOR = "↯";
88  extern const string VOID_INDICATOR = "void";
89  extern const string FUNCTION_INDICATOR= "Function";
90 
91  extern const string BOOL_FALSE_STR = "false";
92  extern const string BOOL_TRUE_STR = "true";
93 
94 
95 
96 #ifdef __GNUG__
97 
134  string
135  demangleCxx (Literal rawName)
136  {
137  int error = -4;
138  UniqueMallocOwner<char> demangled (abi::__cxa_demangle (rawName,
139  NULL,
140  NULL,
141  &error));
142  return 0==error? demangled.get()
143  : string(rawName);
144  }
145 
146 
147 #else
148 #warning "Lumiera was _not_ built with a GCC compatible compiler."
149 #warning "There are good chances this works without problems, but up to now, \
150 the Lumiera developers lacked the resources to investigate that option; \
151 apologies for that."
152 
156  string
158  {
159  return string (rawName);
160  }
161 #endif
162 
163 
164 
165 
166 
187  string
189  {
190  string typeName = demangleCxx (rawType);
191 
192  #define TYP_EXP "[\\w<>\\(\\):,\\s]+"
193 
194  static regex commonPrefixes {"std::"
195  "|(\\w+::)+\\(anonymous namespace\\)::"
196  "|lib::meta::"
197  "|lib::time::"
198  "|lib::test::"
199  "|lib::diff::"
200  "|lib::"
201  "|util::"
202  "|proc::(asset::|mobject::(session::)?|play::)?"
203  "|gui::model"
204  "|gui::ctrl"
205  "|lumiera::"
206  , regex::ECMAScript | regex::optimize};
207 
208  static regex stdString {"(__cxx11::)?basic_string<char, char_traits<char>, allocator<char>\\s*>\\s*"
209  , regex::ECMAScript | regex::optimize};
210 
211  static regex stdAllocator {"(\\w+<(" TYP_EXP ")), allocator<\\2>\\s*"
212  , regex::ECMAScript | regex::optimize};
213 
214  static regex mapAllocator {"(map<(" TYP_EXP "), (" TYP_EXP ")),.+allocator<pair<\\2 const, \\3>\\s*>\\s*"
215  , regex::ECMAScript | regex::optimize};
216 
217  static regex uniquePtr {"unique_ptr<(\\w+), default_delete<\\1>\\s*"
218  , regex::ECMAScript | regex::optimize};
219 
220  static regex lumieraP {"P<(\\w+), shared_ptr<\\1>\\s*"
221  , regex::ECMAScript | regex::optimize};
222 
223 
224  auto pos = typeName.begin();
225  auto end = typeName.end();
226 
227  end = regex_replace(pos, pos, end, commonPrefixes, "");
228  end = regex_replace(pos, pos, end, stdString, "string");
229  end = regex_replace(pos, pos, end, stdAllocator, "$1");
230  end = regex_replace(pos, pos, end, mapAllocator, "$1");
231  end = regex_replace(pos, pos, end, uniquePtr, "unique_ptr<$1");
232  end = regex_replace(pos, pos, end, lumieraP, "P<$1");
233 
234  typeName.resize(end - typeName.begin());
235  return typeName;
236  }
237 
238 
239 
258  string
260  {
261  string typeStr = demangleCxx (rawType);
262 
263  removeSuffix (typeStr, " const");
264  removeSuffix (typeStr, " const *");
265  removeSuffix (typeStr, "*");
266  removeSuffix (typeStr, "&");
267 
268  if (isnil (typeStr)) return VOID_INDICATOR;
269  if (')' == typeStr.back()) return FUNCTION_INDICATOR;
270 
271  auto end = typeStr.end();
272  auto beg = typeStr.begin();
273  int level=0;
274  while (--end != beg)
275  {
276  if ('>' == *end)
277  ++level;
278  else if ('<' == *end and level>0)
279  --level;
280  else
281  if (level==0)
282  {
283  ++end;
284  break;
285  }
286  }
287  if (end == beg) return VOID_INDICATOR;
288 
289  auto pos = typeStr.rfind("::", end-beg);
290  typeStr = (pos==string::npos? typeStr.substr(0, end-beg)
291  : typeStr.substr(pos+2, (end-beg)-pos-2));
292  return typeStr;
293  }
294 
295 
296  string
298  {
299  return util::sanitise (humanReadableTypeID (rawName));
300  }
301 
302 
303  string
304  sanitisedSymbol (string const& text)
305  {
306  static regex identifierChars {"[A-Za-z]\\w*", regex::ECMAScript | regex::optimize};
307 
308  return regex_replace (text, identifierChars, "$&", std::regex_constants::format_no_copy);
309  } // don't copy what does not match
310 
311 
312 
313 }}// namespace lib::meta
314 
315 
316 
317 
318 
319 /* === formatting and pretty printing support utils === */
320 
321 namespace util {
322 
323  using std::hex;
324  using std::setw;
325  using std::right;
326  using std::setfill;
327  using std::noshowbase;
328  using std::ostringstream;
329  using std::ostream;
330 
331 
339  string
340  showDouble (double val) noexcept
341  try {
342  ostringstream buffer;
343  buffer.precision (DIAGNOSTICS_DOUBLE_PRECISION);
344  buffer << val;
345  return buffer.str();
346  }
347  catch(...)
348  { return FAILURE_INDICATOR; }
349 
350 
351  string
352  showFloat (float val) noexcept
353  try {
354  ostringstream buffer;
355  buffer.precision (DIAGNOSTICS_FLOAT_PRECISION);
356  buffer << val;
357  return buffer.str();
358  }
359  catch(...)
360  { return FAILURE_INDICATOR; }
361 
362 
363  string
364  showSize (size_t val) noexcept
365  try {
366  ostringstream buffer;
367  buffer << val;
368  return buffer.str();
369  }
370  catch(...)
371  { return FAILURE_INDICATOR; }
372 
373 
375  ostream&
376  showAddr (ostream& stream, void const* addr)
377  {
378  size_t suffix_modulus = size_t(1) << DIAGNOSTICS_ADDRESS_SUFFIX_LEN * 8;
379  return stream << "╲"
380  << hex
381  << noshowbase
382  << setw (DIAGNOSTICS_ADDRESS_SUFFIX_LEN * 2) // need 2 hex digits per byte
383  << setfill('_')
384  << right
385  << size_t(addr) % suffix_modulus;
386  }
387 
388 
389  string
390  showAddr (void const* addr) noexcept
391  try {
392  ostringstream buffer;
393  showAddr (buffer, addr);
394  return buffer.str();
395  }
396  catch(...)
397  { return FAILURE_INDICATOR; }
398 
399 
400 
401 } // namespace util
#define TYP_EXP
string sanitisedSymbol(string const &text)
condense a string and retain only valid identifiers
Definition: format-obj.cpp:304
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:75
string showAddr(void const *addr) noexcept
pretty-print an address as hex-suffix
Definition: format-obj.cpp:390
string demangleCxx(Literal rawName)
Fallback type-ID:
Definition: format-obj.cpp:157
Helper to deal with C-MALLOCed memory automatically.
std::string typeStr(TY const *obj=nullptr) noexcept
failsafe human readable type display
Definition: meta/util.hpp:272
Implementation namespace for support and library code.
string sanitisedFullTypeName(lib::Literal rawName)
build a sanitised ID from full type name
Definition: format-obj.cpp:297
string showFloat(float val) noexcept
Definition: format-obj.cpp:352
return NULL
Definition: llist.h:596
Marker types to indicate a literal string and a Symbol.
string showSize(size_t val) noexcept
Definition: format-obj.cpp:364
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
string sanitise(string const &org)
produce an identifier based on the given string.
Definition: util.cpp:57
bool isnil(lib::time::Duration const &dur)
Definition: timevalue.hpp:642
Lumiera error handling (C++ interface).
string primaryTypeComponent(Literal rawType)
extract core name component from a raw type spec
Definition: format-obj.cpp:259
Simple functions to represent objects, for debugging and diagnostics.
const string BOTTOM_INDICATOR
Definition: meta/util.hpp:244
string humanReadableTypeID(Literal rawType)
pretty-print an internal C++ type representation
Definition: format-obj.cpp:188
const string FUNCTION_INDICATOR
Definition: meta/util.hpp:242
void removeSuffix(string &str, string const &suffix)
Definition: util.hpp:195
const string BOOL_FALSE_STR
Definition: meta/util.hpp:247
const string BOOL_TRUE_STR
Definition: meta/util.hpp:248
const string FAILURE_INDICATOR
Definition: meta/util.hpp:243
Ownership token for a piece of heap memory allocated in plain-C style.
const string VOID_INDICATOR
Definition: meta/util.hpp:245
void removePrefix(string &str, string const &prefix)
Definition: util.hpp:188
string showDouble(double val) noexcept
pretty-print a double in fixed-point format
Definition: format-obj.cpp:340