LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
FriendlyName.cc
Go to the documentation of this file.
3 #include "tbb/concurrent_unordered_map.h"
4 
5 #include <regex>
6 #include <string>
7 
8 // NOTE: This should probably be rewritten so that we break the class
9 // name into a tree where the template arguments are the node. On the
10 // way down the tree we look for '<' or ',' and on the way up (caused by
11 // finding a '>') we can apply the transformation to the output string
12 // based on the class name for the templated class. Up front we'd
13 // register a class name to a transformation function (which would
14 // probably take a std::vector<std::string> which holds the results of
15 // the node transformations).
16 
17 namespace {
18  std::regex const reAllSpaces{" +"};
19  std::regex const reAssns{"art::Assns"};
20  std::regex const reBeginSpace{"^ +"};
21  std::regex const reComma{","};
22  std::regex const reEndSpace{" +$"};
23  std::regex const reParens{"(\\(|\\))"};
24  std::regex const reFirstTwoArgs{"^([^,]+),([^,]+)"};
25  std::regex const reLong{"long "};
26  std::regex const reLongLong{"Long64_t"};
27  std::regex const reMapVector{"cet::map_vector"};
28  std::regex const reMapVectorKey{"cet::map_vector_key"};
29  std::regex const reString{"(?:std::basic_string<char>|std::string)"};
30  std::regex const reTemplateArgs{"([^<]*)<(.*)>$"};
31  std::regex const reTemplateClass{"([^<>,]+<[^<>]*>)"};
32  std::regex const reULongLong{"ULong64_t"};
33  std::regex const reUnsigned{"unsigned "};
34  std::regex const reVector{"std::vector"};
35  std::regex const reWrapper{"art::Wrapper<(.*)>"};
36 
37  std::string const emptyString{};
38 
39  std::string
40  removeExtraSpaces(std::string const& in)
41  {
42  return std::regex_replace(std::regex_replace(in, reBeginSpace, emptyString),
43  reEndSpace,
44  emptyString);
45  }
46 
47  std::string
48  removeAllSpaces(std::string const& in)
49  {
50  return std::regex_replace(in, reAllSpaces, emptyString);
51  }
52 
53  std::string
54  escapeParens(std::string const& in)
55  {
56  return std::regex_replace(in, reParens, "\\$1");
57  }
58 
59  std::string
60  standardRenames(std::string const& in)
61  {
62  std::string name{std::regex_replace(in, reWrapper, "$1")};
63  name = std::regex_replace(name, reString, "String");
64  name = std::regex_replace(name, reUnsigned, "u");
65  name = std::regex_replace(name, reLong, "l");
66  name = std::regex_replace(name, reULongLong, "ull");
67  name = std::regex_replace(name, reLongLong, "ll");
68  name = std::regex_replace(name, reVector, "s");
69  name = std::regex_replace(name, reMapVectorKey, "mvk");
70  name = std::regex_replace(name, reMapVector, "mv");
71  return name;
72  }
73 
74  // Declaration required here because handleTemplateArguments and
75  // subFriendlyName call each other.
76  std::string handleTemplateArguments(std::string const&, std::string const&);
77  std::string
78  subFriendlyName(std::string const& iFullName)
79  {
80  std::string result{removeExtraSpaces(iFullName)};
81 
82  std::smatch theMatch;
83  if (std::regex_match(result, theMatch, reTemplateArgs)) {
84  std::string const cMatch{theMatch.str(1)};
85  std::string const aMatch{theMatch.str(2)};
86  std::string const theSub{handleTemplateArguments(cMatch, aMatch)};
87  // If a type (e.g.) A was declared in an anonymous namespace,
88  // the demangled typename can be (anonymous namespace)::A. The
89  // parentheses must be escaped so that they do not interfere
90  // with the regex library.
91  std::regex const eMatch{std::string{"^"} + escapeParens(cMatch) + '<' +
92  escapeParens(aMatch) + '>'};
93  result = std::regex_replace(result, eMatch, theSub + cMatch);
94  }
95  return result;
96  }
97 
98  void
99  maybeSwapFirstTwoArgs(std::string& result)
100  {
101  std::smatch theMatch;
102  if (std::regex_search(result, theMatch, reFirstTwoArgs) &&
103  (theMatch.str(1) > theMatch.str(2))) {
104  result = std::regex_replace(result, reFirstTwoArgs, "$2,$1");
105  }
106  }
107 
108  std::string
109  handleTemplateArguments(std::string const& cName, std::string const& tArgs)
110  {
111  std::string result{removeExtraSpaces(tArgs)};
112  bool shouldStop{false};
113  while (!shouldStop) {
114  if (std::string::npos != result.find_first_of("<")) {
115  std::smatch theMatch;
116  if (std::regex_search(result, theMatch, reTemplateClass)) {
117  std::string const templateClass{theMatch.str(1)};
118  std::string const friendlierName{
119  removeAllSpaces(subFriendlyName(templateClass))};
120  result = std::regex_replace(
121  result, std::regex(templateClass), friendlierName);
122  } else {
124  << "No template match for \"" << result << '"';
125  }
126  } else {
127  shouldStop = true;
128  }
129  }
130  if (std::regex_match(cName, reAssns)) {
131  maybeSwapFirstTwoArgs(result);
132  }
133  result = std::regex_replace(result, reComma, emptyString);
134  return result;
135  }
136 }
137 
138 std::string
139 art::friendlyname::friendlyName(std::string const& iFullName)
140 {
141  static tbb::concurrent_unordered_map<std::string, std::string> s_nameMap;
142  auto entry = s_nameMap.find(iFullName);
143  if (s_nameMap.end() == entry) {
144  entry =
145  s_nameMap.emplace(iFullName, subFriendlyName(standardRenames(iFullName)))
146  .first;
147  }
148  return entry->second;
149 }
std::string friendlyName(std::string const &iFullName)
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
ifstream in
Definition: comparison.C:7