CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
TypeDemangler.cc
Go to the documentation of this file.
1 #include <cxxabi.h>
2 #include <cctype>
3 #include <string>
4 #include <regex>
6 
7 /********************************************************************
8  TypeDemangler is used to demangle the mangled name provided by type_info into the type name.
9 
10  The conventions used (e.g. const qualifiers before identifiers, no spaces after commas)
11  are chosen to match the type names that can be used by the plug-in manager to load data dictionaries.
12  It also strips comparators from (multi) maps or sets, and always strips allocators.
13 
14  This demangler is platform dependent. This version works for gcc.
15 
16  Known limitations:
17 
18  0) It is platform dependent. See above.
19 
20  1) It does not demangle function names, only type names.
21 
22  2) If an enum value is used as a non-type template parameter, the demangled name cannot
23  be used successfully to load the dictionary. This is because the enumerator value name
24  is not available in the mangled name (on this platform).
25 
26 ********************************************************************/
27 namespace {
28  void
29  reformatter(std::string& input, char const* exp, char const* format) {
30  std::regex regexp(exp, std::regex::egrep);
31  while(std::regex_match(input, regexp)) {
32  std::string newstring = std::regex_replace(input, regexp, format);
33  input.swap(newstring);
34  }
35  }
36 
37  void
38  removeParameter(std::string& demangledName, std::string const& toRemove) {
39  std::string::size_type const asize = toRemove.size();
40  char const* const delimiters = "<>";
41  std::string::size_type index = std::string::npos;
42  while ((index = demangledName.find(toRemove)) != std::string::npos) {
43  int depth = 1;
44  std::string::size_type inx = index + asize;
45  while ((inx = demangledName.find_first_of(delimiters, inx)) != std::string::npos) {
46  if (demangledName[inx] == '<') {
47  ++depth;
48  } else {
49  --depth;
50  if (depth == 0) {
51  demangledName.erase(index, inx + 1 - index);
52  if (demangledName[index] == ' ' && (index == 0 || demangledName[index - 1] != '>')) {
53  demangledName.erase(index, 1);
54  }
55  break;
56  }
57  }
58  ++inx;
59  }
60  }
61  }
62 
63  void
64  constBeforeIdentifier(std::string& demangledName) {
65  std::string const toBeMoved(" const");
66  std::string::size_type const asize = toBeMoved.size();
67  std::string::size_type index = std::string::npos;
68  while ((index = demangledName.find(toBeMoved)) != std::string::npos) {
69  demangledName.erase(index, asize);
70  int depth = 0;
71  for (std::string::size_type inx = index - 1; inx > 0; --inx) {
72  char const c = demangledName[inx];
73  if (c == '>') {
74  ++depth;
75  } else if (depth > 0) {
76  if (c == '<') --depth;
77  } else if (c == '<' || c == ',') {
78  demangledName.insert(inx + 1, "const ");
79  break;
80  }
81  }
82  }
83  }
84 }
85 
86 namespace edm {
87  void
88  replaceString(std::string& demangledName, std::string const& from, std::string const& to) {
89  // from must not be a substring of to.
90  std::string::size_type length = from.size();
91  std::string::size_type pos = 0;
92  while((pos = demangledName.find(from, pos)) != std::string::npos) {
93  demangledName.replace(pos, length, to);
94  }
95  }
96 
98  typeDemangle(char const* mangledName) {
99  int status = 0;
100  size_t* const nullSize = 0;
101  char* const null = 0;
102 
103  // The demangled C style string is allocated with malloc, so it must be deleted with free().
104  char* demangled = abi::__cxa_demangle(mangledName, null, nullSize, &status);
105  if (status != 0) {
106  throw cms::Exception("Demangling error") << " '" << mangledName << "'\n";
107  }
108  std::string demangledName(demangled);
109  free(demangled);
110  // We must use the same conventions previously used by REFLEX.
111  // The order of these is important.
112  // No space after comma
113  replaceString(demangledName, ", ", ",");
114  // No space before opening square bracket
115  replaceString(demangledName, " [", "[");
116  // Strip default allocator
117  std::string const allocator(",std::allocator<");
118  removeParameter(demangledName, allocator);
119  // Strip default comparator
120  std::string const comparator(",std::less<");
121  removeParameter(demangledName, comparator);
122  // Put const qualifier before identifier.
123  constBeforeIdentifier(demangledName);
124  // No two consecutive '>'
125  replaceString(demangledName, ">>", "> >");
126  // No u or l qualifiers for integers.
127  reformatter(demangledName, "(.*[<,][0-9]+)[ul]l*([,>].*)", "$1$2");
128  // For ROOT 6 and beyond, replace 'unsigned long long' with 'ULong64_t'
129  replaceString(demangledName, "unsigned long long", "ULong64_t");
130  // For ROOT 6 and beyond, replace 'long long' with 'Long64_t'
131  replaceString(demangledName, "long long", "Long64_t");
132  return demangledName;
133  }
134 }
void replaceString(std::string &demangledName, std::string const &from, std::string const &to)
uint16_t size_type
static std::string const input
Definition: EdmProvDump.cc:43
std::string demangledName(const std::type_info &typeInfo)
Definition: ClassUtils.cc:159
std::string typeDemangle(char const *mangledName)
tuple status
Definition: ntuplemaker.py:245