Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-12-24 02:18:58

0001 /*
0002  *  friendlyName.cpp
0003  *  CMSSW
0004  *
0005  *  Created by Chris Jones on 2/24/06.
0006  *
0007  */
0008 #include <string>
0009 #include <regex>
0010 #include <iostream>
0011 #include <cassert>
0012 #include "oneapi/tbb/concurrent_unordered_map.h"
0013 
0014 //NOTE:  This should probably be rewritten so that we break the class name into a tree where the template arguments are the node.  On the way down the tree
0015 // we look for '<' or ',' and on the way up (caused by finding a '>') we can apply the transformation to the output string based on the class name for the
0016 // templated class.  Up front we'd register a class name to a transformation function (which would probably take a std::vector<std::string> which holds
0017 // the results of the node transformations)
0018 
0019 namespace {
0020   constexpr bool debug = false;
0021   std::string prefix;  // used only if debug == true
0022 }  // namespace
0023 
0024 namespace edm {
0025   namespace friendlyname {
0026     static std::regex const reBeginSpace("^ +");
0027     static std::regex const reEndSpace(" +$");
0028     static std::regex const reAllSpaces(" +");
0029     static std::regex const reColons("::");
0030     static std::regex const reComma(",");
0031     static std::regex const reTemplateArgs("[^<]*<(.*)>$");
0032     static std::regex const rePointer("\\*");
0033     static std::regex const reArray("\\[\\]");
0034     static std::regex const reUniquePtrDeleter("^std::unique_ptr< *(.*), *std::default_delete<\\1> *>");
0035     static std::regex const reUniquePtr("^std::unique_ptr");
0036     static std::string const emptyString("");
0037 
0038     std::string handleNamespaces(std::string const& iIn) { return std::regex_replace(iIn, reColons, emptyString); }
0039 
0040     std::string removeExtraSpaces(std::string const& iIn) {
0041       return std::regex_replace(std::regex_replace(iIn, reBeginSpace, emptyString), reEndSpace, emptyString);
0042     }
0043 
0044     std::string removeAllSpaces(std::string const& iIn) { return std::regex_replace(iIn, reAllSpaces, emptyString); }
0045     static std::regex const reWrapper("edm::Wrapper<(.*)>");
0046     static std::regex const reString("std::basic_string<char>");
0047     static std::regex const reString2("std::string");
0048     static std::regex const reString3("std::basic_string<char,std::char_traits<char> >");
0049     //The c++11 abi for gcc internally uses a different namespace for standard classes
0050     static std::regex const reCXX11("std::__cxx11::");
0051     static std::regex const reSorted("edm::SortedCollection<(.*), *edm::StrictWeakOrdering<\\1 *> >");
0052     static std::regex const reclangabi("std::__1::");
0053     static std::regex const reULongLong("ULong64_t");
0054     static std::regex const reLongLong("Long64_t");
0055     static std::regex const reUnsigned("unsigned ");
0056     static std::regex const reLong("long ");
0057     static std::regex const reVector("std::vector");
0058     static std::regex const reUnorderedSetHashKeyEqual(
0059         "std::unordered_set< *(.*), *std::hash<\\1> *, *std::equal_to<\\1> *>");
0060     static std::regex const reUnorderedSetCustomHashKeyEqual(
0061         "std::unordered_set< *(.*), *(.*) *, *std::equal_to<\\1> *>");
0062     static std::regex const reUnorderedSetHash("std::unordered_set< *(.*), *std::hash<\\1> *>");
0063     static std::regex const reUnorderedSet("std::unordered_set");
0064     static std::regex const reUnorderedMapHashKeyEqual(
0065         "std::unordered_map< *(.*), *(.*), *std::hash<\\1> *, *std::equal_to<\\1> *>");
0066     static std::regex const reUnorderedMapCustomHashKeyEqual(
0067         "std::unordered_map< *(.*), *(.*), *(.*) *, *std::equal_to<\\1> *>");
0068     static std::regex const reUnorderedMapHash("std::unordered_map< *(.*), *(.*), *std::hash<\\1> *>");
0069     static std::regex const reUnorderedMap("std::unordered_map");
0070     static std::regex const reSharedPtr("std::shared_ptr");
0071     static std::regex const reAIKR(
0072         ", *edm::helper::AssociationIdenticalKeyReference");  //this is a default so can replaced with empty
0073     //force first argument to also be the argument to edm::ClonePolicy so that if OwnVector is within
0074     // a template it will not eat all the remaining '>'s
0075     static std::regex const reOwnVector("edm::OwnVector<(.*), *edm::ClonePolicy<\\1 *> >");
0076 
0077     //NOTE: the '?' means make the smallest match. This may lead to problems where the template arguments themselves have commas
0078     // but we are using it in the cases where edm::AssociationMap appears multiple times in template arguments
0079     static std::regex const reOneToOne("edm::AssociationMap< *edm::OneToOne<(.*?),(.*?), *u[a-z]*> >");
0080     static std::regex const reOneToMany("edm::AssociationMap< *edm::OneToMany<(.*?),(.*?), *u[a-z]*> >");
0081     static std::regex const reOneToValue("edm::AssociationMap< *edm::OneToValue<(.*?),(.*?), *u[a-z]*> >");
0082     static std::regex const reOneToManyWithQuality(
0083         "edm::AssociationMap<edm::OneToManyWithQuality<(.*?), *(.*?), *(.*?), *u[a-z]*> >");
0084     static std::regex const reToVector("edm::AssociationVector<(.*), *(.*), *edm::Ref.*,.*>");
0085     //NOTE: if the item within a clone policy is a template, this substitution will probably fail
0086     static std::regex const reToRangeMap("edm::RangeMap< *(.*), *(.*), *edm::ClonePolicy<([^>]*)> >");
0087     //NOTE: If container is a template with one argument which is its 'type' then can simplify name
0088     static std::regex const reToRefs1(
0089         "edm::RefVector< *(.*)< *(.*) *>, *\\2 *, *edm::refhelper::FindUsingAdvance< *\\1< *\\2 *> *, *\\2 *> *>");
0090     static std::regex const reToRefs2(
0091         "edm::RefVector< *(.*) *, *(.*) *, *edm::refhelper::FindUsingAdvance< *\\1, *\\2 *> *>");
0092     static std::regex const reToRefsAssoc(
0093         "edm::RefVector< *Association(.*) *, *edm::helper(.*), *Association(.*)::Find>");
0094 
0095     std::string standardRenames(std::string const& iIn) {
0096       using std::regex;
0097       using std::regex_replace;
0098       std::string name = regex_replace(iIn, reWrapper, "$1");
0099       name = regex_replace(name, rePointer, "ptr");
0100       name = regex_replace(name, reArray, "As");
0101       name = regex_replace(name, reAIKR, "");
0102       name = regex_replace(name, reclangabi, "std::");
0103       name = regex_replace(name, reCXX11, "std::");
0104       name = regex_replace(name, reString, "String");
0105       name = regex_replace(name, reString2, "String");
0106       name = regex_replace(name, reString3, "String");
0107       name = regex_replace(name, reSorted, "sSorted<$1>");
0108       name = regex_replace(name, reULongLong, "ull");
0109       name = regex_replace(name, reLongLong, "ll");
0110       name = regex_replace(name, reUnsigned, "u");
0111       name = regex_replace(name, reLong, "l");
0112       name = regex_replace(name, reVector, "s");
0113       name = regex_replace(name, reSharedPtr, "SharedPtr");
0114       name = regex_replace(name, reOwnVector, "sOwned<$1>");
0115       name = regex_replace(name, reToVector, "AssociationVector<$1,To,$2>");
0116       name = regex_replace(name, reOneToOne, "Association<$1,ToOne,$2>");
0117       name = regex_replace(name, reOneToMany, "Association<$1,ToMany,$2>");
0118       name = regex_replace(name, reOneToValue, "Association<$1,ToValue,$2>");
0119       name = regex_replace(name, reOneToManyWithQuality, "Association<$1,ToMany,$2,WithQuantity,$3>");
0120       name = regex_replace(name, reToRangeMap, "RangeMap<$1,$2>");
0121       name = regex_replace(name, reToRefs1, "Refs<$1<$2>>");
0122       name = regex_replace(name, reToRefs2, "Refs<$1,$2>");
0123       name = regex_replace(name, reToRefsAssoc, "Refs<Association$1>");
0124       //std::cout <<"standardRenames '"<<name<<"'"<<std::endl;
0125       return name;
0126     }
0127 
0128     std::string handleTemplateArguments(std::string const&);
0129     std::string subFriendlyName(std::string const& iFullName) {
0130       using namespace std;
0131       std::string result = removeExtraSpaces(iFullName);
0132 
0133       // temporarily remove leading const
0134       std::string leadingConst;
0135       if (std::string_view{result}.substr(0, 5) == "const") {
0136         leadingConst = "const";
0137         result = removeExtraSpaces(result.substr(5));
0138       }
0139 
0140       if constexpr (debug) {
0141         std::cout << prefix << "subFriendlyName iFullName " << iFullName << " result " << result << std::endl;
0142       }
0143       // Handle unique_ptr, which may contain the deleter (but handle only std::default_delete)
0144       {
0145         auto result2 =
0146             regex_replace(result, reUniquePtrDeleter, "UniquePtr<$1>", std::regex_constants::format_first_only);
0147         if (result2 == result) {
0148           result2 = regex_replace(result, reUniquePtr, "UniquePtr", std::regex_constants::format_first_only);
0149         }
0150         result = std::move(result2);
0151       }
0152       // insert the leading const back if it was there
0153       result = leadingConst + result;
0154       // Handle unordered_set, which may contain a hash and an an equal for the key
0155       {
0156         auto result2 =
0157             regex_replace(result, reUnorderedSetHashKeyEqual, "stduset<$1>", std::regex_constants::format_first_only);
0158         if (result2 == result) {
0159           result2 = regex_replace(
0160               result, reUnorderedSetCustomHashKeyEqual, "stduset<$1, $2>", std::regex_constants::format_first_only);
0161         }
0162         if (result2 == result) {
0163           result2 = regex_replace(result, reUnorderedSetHash, "stduset<$1>", std::regex_constants::format_first_only);
0164         }
0165         if (result2 == result) {
0166           result2 = regex_replace(result, reUnorderedSet, "stduset", std::regex_constants::format_first_only);
0167         }
0168         result = std::move(result2);
0169       }
0170       // Handle unordered_map, which may contain a hash and an an equal for the key
0171       {
0172         auto result2 = regex_replace(
0173             result, reUnorderedMapHashKeyEqual, "stdumap<$1, $2>", std::regex_constants::format_first_only);
0174         if (result2 == result) {
0175           result2 = regex_replace(
0176               result, reUnorderedMapCustomHashKeyEqual, "stdumap<$1, $2, $3>", std::regex_constants::format_first_only);
0177         }
0178         if (result2 == result) {
0179           result2 =
0180               regex_replace(result, reUnorderedMapHash, "stdumap<$1, $2>", std::regex_constants::format_first_only);
0181         }
0182         if (result2 == result) {
0183           result2 = regex_replace(result, reUnorderedMap, "stdumap", std::regex_constants::format_first_only);
0184         }
0185         result = std::move(result2);
0186       }
0187       if (smatch theMatch; regex_match(result, theMatch, reTemplateArgs)) {
0188         //std::cout <<"found match \""<<theMatch.str(1) <<"\"" <<std::endl;
0189         //static regex const templateClosing(">$");
0190         //std::string aMatch = regex_replace(theMatch.str(1),templateClosing,"");
0191         std::string aMatch = theMatch.str(1);
0192         if constexpr (debug) {
0193           prefix += "  ";
0194         }
0195         std::string theSub = handleTemplateArguments(aMatch);
0196         if constexpr (debug) {
0197           prefix.pop_back();
0198           prefix.pop_back();
0199           std::cout << prefix << " aMatch " << aMatch << " theSub " << theSub << std::endl;
0200         }
0201         regex const eMatch(std::string("(^[^<]*)<") + aMatch + ">");
0202         result = regex_replace(result, eMatch, theSub + "$1");
0203       }
0204       return removeAllSpaces(result);
0205     }
0206 
0207     std::string handleTemplateArguments(std::string const& iIn) {
0208       using namespace std;
0209       std::string result = removeExtraSpaces(iIn);
0210       if constexpr (debug) {
0211         std::cout << prefix << "handleTemplateArguments " << iIn << " removeExtraSpaces " << result << std::endl;
0212       }
0213 
0214       // Trick to have every full class name to end with comma to
0215       // avoid treating the end as a special case
0216       result += ",";
0217 
0218       std::string result2;
0219       result2.reserve(iIn.size());
0220       unsigned int openTemplate = 0;
0221       bool hadTemplate = false;
0222       size_t begin = 0;
0223       for (size_t i = 0, size = result.size(); i < size; ++i) {
0224         if (result[i] == '<') {
0225           ++openTemplate;
0226           hadTemplate = true;
0227           continue;
0228         } else if (result[i] == '>') {
0229           --openTemplate;
0230         }
0231         // If we are not within the template arguments of a class template
0232         // - encountering comma means that we are within a template
0233         //   argument of some other class template, and we've reached
0234         //   a point when we should translate the argument class name
0235         // - encountering colon, but only if the class name so far
0236         //   itself was a template, we've reached a point when we
0237         //   should translate the class name
0238         if (const bool hasComma = result[i] == ',', hasColon = hadTemplate and result[i] == ':';
0239             openTemplate == 0 and (hasComma or hasColon)) {
0240           std::string templateClass = result.substr(begin, i - begin);
0241           if constexpr (debug) {
0242             std::cout << prefix << " templateClass " << templateClass << std::endl;
0243           }
0244           if (hadTemplate) {
0245             if constexpr (debug) {
0246               prefix += "  ";
0247             }
0248             std::string friendlierName = subFriendlyName(templateClass);
0249             if constexpr (debug) {
0250               prefix.pop_back();
0251               prefix.pop_back();
0252               std::cout << prefix << " friendlierName " << friendlierName << std::endl;
0253             }
0254             result2 += friendlierName;
0255           } else {
0256             result2 += templateClass;
0257           }
0258           if constexpr (debug) {
0259             std::cout << prefix << " result2 " << result2 << std::endl;
0260           }
0261           // reset counters
0262           hadTemplate = false;
0263           begin = i + 1;
0264           // With colon we need to eat the second colon as well
0265           if (hasColon) {
0266             assert(result[begin] == ':');
0267             ++begin;
0268           }
0269         }
0270       }
0271 
0272       result = regex_replace(result2, reComma, "");
0273       if constexpr (debug) {
0274         std::cout << prefix << " reComma " << result << std::endl;
0275       }
0276       return result;
0277     }
0278     std::string friendlyName(std::string const& iFullName) {
0279       if constexpr (debug) {
0280         std::cout << "\nfriendlyName for " << iFullName << std::endl;
0281         prefix = " ";
0282       }
0283       typedef oneapi::tbb::concurrent_unordered_map<std::string, std::string> Map;
0284       static Map s_fillToFriendlyName;
0285       auto itFound = s_fillToFriendlyName.find(iFullName);
0286       if (s_fillToFriendlyName.end() == itFound) {
0287         itFound = s_fillToFriendlyName
0288                       .insert(Map::value_type(iFullName, handleNamespaces(subFriendlyName(standardRenames(iFullName)))))
0289                       .first;
0290       }
0291       if constexpr (debug) {
0292         std::cout << "result " << itFound->second << std::endl;
0293       }
0294       return itFound->second;
0295     }
0296   }  // namespace friendlyname
0297 }  // namespace edm