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 <string>
4 
5 /********************************************************************
6  TypeDemangler is used to demangle the mangled name provided by type_info into the type name.
7 
8  The conventions used (e.g. const qualifiers before identifiers, no spaces after commas)
9  are chosen to match the type names that can be used by the plug-in manager to load data dictionaries.
10  It also strips comparators from (multi) maps or sets, and always strips allocators.
11 
12  This demangler is platform dependent. This version works for gcc.
13 
14  Known limitations:
15 
16  0) It is platform dependent. See above.
17 
18  1) It does not demangle function names, only type names.
19 
20  2) If an enum value is used as a non-type template parameter, the demangled name cannot
21  be used successfully to load the dictionary. This is because the enumerator value name
22  (used by Reflex) is not available in the mangled name (on this platform).
23 
24 ********************************************************************/
25 namespace {
26  void
27  noSpaceAfterComma(std::string& demangledName) {
28  char const* const commaSpace = ", ";
29  std::string::size_type index = std::string::npos;
30  while ((index = demangledName.find(commaSpace)) != std::string::npos) {
31  demangledName.erase(index + 1, 1);
32  }
33  }
34 
35  void
36  removeParameter(std::string& demangledName, std::string const& toRemove) {
37  std::string::size_type const asize = toRemove.size();
38  char const* const delimiters = "<>";
39  std::string::size_type index = std::string::npos;
40  while ((index = demangledName.find(toRemove)) != std::string::npos) {
41  int depth = 1;
42  std::string::size_type inx = index + asize;
43  while ((inx = demangledName.find_first_of(delimiters, inx)) != std::string::npos) {
44  if (demangledName[inx] == '<') {
45  ++depth;
46  } else {
47  --depth;
48  if (depth == 0) {
49  demangledName.erase(index, inx + 1 - index);
50  if (demangledName[index] == ' ') {
51  demangledName.erase(index, 1);
52  }
53  break;
54  }
55  }
56  ++inx;
57  }
58  }
59  }
60 
61  void
62  constBeforeIdentifier(std::string& demangledName) {
63  std::string const toBeMoved(" const");
64  std::string::size_type const asize = toBeMoved.size();
65  std::string::size_type index = std::string::npos;
66  while ((index = demangledName.find(toBeMoved)) != std::string::npos) {
67  demangledName.erase(index, asize);
68  int depth = 0;
69  for (std::string::size_type inx = index - 1; inx > 0; --inx) {
70  char const c = demangledName[inx];
71  if (c == '>') {
72  ++depth;
73  } else if (depth > 0) {
74  if (c == '<') --depth;
75  } else if (c == '<' || c == ',') {
76  demangledName.insert(inx + 1, "const ");
77  break;
78  }
79  }
80  }
81  }
82 }
83 
84 namespace edm {
85  void
86  typeDemangle(char const* name, std::string& demangledName) {
87  int status = 0;
88  size_t* const nullSize = 0;
89  char* const null = 0;
90  demangledName += abi::__cxa_demangle(name, null, nullSize, &status);
91  if (status != 0) {
92  throw cms::Exception("Demangling error") << " '" << name << "'\n";
93  }
94  // We must use the same conventions used by REFLEX.
95  noSpaceAfterComma(demangledName);
96  // Strip default allocator
97  std::string const allocator(",std::allocator<");
98  removeParameter(demangledName, allocator);
99  // Strip default comparator
100  std::string const comparator(",std::less<");
101  removeParameter(demangledName, comparator);
102  // Put const qualifier before identifier.
103  constBeforeIdentifier(demangledName);
104  }
105 }
uint16_t size_type
std::string demangledName(const std::type_info &typeInfo)
Definition: ClassUtils.cc:82
void typeDemangle(char const *mangledName, std::string &demangledName)
tuple status
Definition: ntuplemaker.py:245