Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-03-17 11:03:53

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     // type aliases for Alpaka internals
0096     static std::regex const reAlpakaDevCpu("alpaka::DevCpu");                                     // alpakaDevCpu
0097     static std::regex const reAlpakaDevCudaRt("alpaka::DevUniformCudaHipRt<alpaka::ApiCudaRt>");  // alpakaDevCudaRt
0098     static std::regex const reAlpakaDevHipRt("alpaka::DevUniformCudaHipRt<alpaka::ApiHipRt>");    // alpakaDevHipRt
0099     static std::regex const reAlpakaQueueCpuBlocking(
0100         "alpaka::QueueGenericThreadsBlocking<alpaka::DevCpu>");  // alpakaQueueCpuBlocking
0101     static std::regex const reAlpakaQueueCpuNonBlocking(
0102         "alpaka::QueueGenericThreadsNonBlocking<alpaka::DevCpu>");  // alpakaQueueCpuNonBlocking
0103     static std::regex const reAlpakaQueueCudaRtBlocking(
0104         "alpaka::uniform_cuda_hip::detail::QueueUniformCudaHipRt<alpaka::ApiCudaRt,true>");  // alpakaQueueCudaRtBlocking
0105     static std::regex const reAlpakaQueueCudaRtNonBlocking(
0106         "alpaka::uniform_cuda_hip::detail::QueueUniformCudaHipRt<alpaka::ApiCudaRt,false>");  // alpakaQueueCudaRtNonBlocking
0107     static std::regex const reAlpakaQueueHipRtBlocking(
0108         "alpaka::uniform_cuda_hip::detail::QueueUniformCudaHipRt<alpaka::ApiHipRt,true>");  // alpakaQueueHipRtBlocking
0109     static std::regex const reAlpakaQueueHipRtNonBlocking(
0110         "alpaka::uniform_cuda_hip::detail::QueueUniformCudaHipRt<alpaka::ApiHipRt,false>");  // alpakaQueueHipRtNonBlocking
0111 
0112     std::string standardRenames(std::string const& iIn) {
0113       using std::regex;
0114       using std::regex_replace;
0115       std::string name = regex_replace(iIn, reWrapper, "$1");
0116       name = regex_replace(name, rePointer, "ptr");
0117       name = regex_replace(name, reArray, "As");
0118       name = regex_replace(name, reAIKR, "");
0119       name = regex_replace(name, reclangabi, "std::");
0120       name = regex_replace(name, reCXX11, "std::");
0121       name = regex_replace(name, reString, "String");
0122       name = regex_replace(name, reString2, "String");
0123       name = regex_replace(name, reString3, "String");
0124       name = regex_replace(name, reSorted, "sSorted<$1>");
0125       name = regex_replace(name, reULongLong, "ull");
0126       name = regex_replace(name, reLongLong, "ll");
0127       name = regex_replace(name, reUnsigned, "u");
0128       name = regex_replace(name, reLong, "l");
0129       name = regex_replace(name, reVector, "s");
0130       name = regex_replace(name, reSharedPtr, "SharedPtr");
0131       name = regex_replace(name, reOwnVector, "sOwned<$1>");
0132       name = regex_replace(name, reToVector, "AssociationVector<$1,To,$2>");
0133       name = regex_replace(name, reOneToOne, "Association<$1,ToOne,$2>");
0134       name = regex_replace(name, reOneToMany, "Association<$1,ToMany,$2>");
0135       name = regex_replace(name, reOneToValue, "Association<$1,ToValue,$2>");
0136       name = regex_replace(name, reOneToManyWithQuality, "Association<$1,ToMany,$2,WithQuantity,$3>");
0137       name = regex_replace(name, reToRangeMap, "RangeMap<$1,$2>");
0138       name = regex_replace(name, reToRefs1, "Refs<$1<$2>>");
0139       name = regex_replace(name, reToRefs2, "Refs<$1,$2>");
0140       name = regex_replace(name, reToRefsAssoc, "Refs<Association$1>");
0141 
0142       // Alpaka types
0143       name = regex_replace(name, reAlpakaQueueCpuBlocking, "alpakaQueueCpuBlocking");
0144       name = regex_replace(name, reAlpakaQueueCpuNonBlocking, "alpakaQueueCpuNonBlocking");
0145       name = regex_replace(name, reAlpakaQueueCudaRtBlocking, "alpakaQueueCudaRtBlocking");
0146       name = regex_replace(name, reAlpakaQueueCudaRtNonBlocking, "alpakaQueueCudaRtNonBlocking");
0147       name = regex_replace(name, reAlpakaQueueHipRtBlocking, "alpakaQueueHipRtBlocking");
0148       name = regex_replace(name, reAlpakaQueueHipRtNonBlocking, "alpakaQueueHipRtNonBlocking");
0149       // devices should be last, as they can appear as template arguments in other types
0150       name = regex_replace(name, reAlpakaDevCpu, "alpakaDevCpu");
0151       name = regex_replace(name, reAlpakaDevCudaRt, "alpakaDevCudaRt");
0152       name = regex_replace(name, reAlpakaDevHipRt, "alpakaDevHipRt");
0153 
0154       if constexpr (debug) {
0155         std::cout << prefix << "standardRenames iIn " << iIn << " result " << name << std::endl;
0156       }
0157       return name;
0158     }
0159 
0160     std::string handleTemplateArguments(std::string const&);
0161     std::string subFriendlyName(std::string const& iFullName) {
0162       using namespace std;
0163       std::string result = removeExtraSpaces(iFullName);
0164 
0165       // temporarily remove leading const
0166       std::string leadingConst;
0167       if (std::string_view{result}.substr(0, 5) == "const") {
0168         leadingConst = "const";
0169         result = removeExtraSpaces(result.substr(5));
0170       }
0171 
0172       if constexpr (debug) {
0173         std::cout << prefix << "subFriendlyName iFullName " << iFullName << " result " << result << std::endl;
0174       }
0175       // Handle unique_ptr, which may contain the deleter (but handle only std::default_delete)
0176       {
0177         auto result2 =
0178             regex_replace(result, reUniquePtrDeleter, "UniquePtr<$1>", std::regex_constants::format_first_only);
0179         if (result2 == result) {
0180           result2 = regex_replace(result, reUniquePtr, "UniquePtr", std::regex_constants::format_first_only);
0181         }
0182         result = std::move(result2);
0183       }
0184       // insert the leading const back if it was there
0185       result = leadingConst + result;
0186       // Handle unordered_set, which may contain a hash and an an equal for the key
0187       {
0188         auto result2 =
0189             regex_replace(result, reUnorderedSetHashKeyEqual, "stduset<$1>", std::regex_constants::format_first_only);
0190         if (result2 == result) {
0191           result2 = regex_replace(
0192               result, reUnorderedSetCustomHashKeyEqual, "stduset<$1, $2>", std::regex_constants::format_first_only);
0193         }
0194         if (result2 == result) {
0195           result2 = regex_replace(result, reUnorderedSetHash, "stduset<$1>", std::regex_constants::format_first_only);
0196         }
0197         if (result2 == result) {
0198           result2 = regex_replace(result, reUnorderedSet, "stduset", std::regex_constants::format_first_only);
0199         }
0200         result = std::move(result2);
0201       }
0202       // Handle unordered_map, which may contain a hash and an an equal for the key
0203       {
0204         auto result2 = regex_replace(
0205             result, reUnorderedMapHashKeyEqual, "stdumap<$1, $2>", std::regex_constants::format_first_only);
0206         if (result2 == result) {
0207           result2 = regex_replace(
0208               result, reUnorderedMapCustomHashKeyEqual, "stdumap<$1, $2, $3>", std::regex_constants::format_first_only);
0209         }
0210         if (result2 == result) {
0211           result2 =
0212               regex_replace(result, reUnorderedMapHash, "stdumap<$1, $2>", std::regex_constants::format_first_only);
0213         }
0214         if (result2 == result) {
0215           result2 = regex_replace(result, reUnorderedMap, "stdumap", std::regex_constants::format_first_only);
0216         }
0217         result = std::move(result2);
0218       }
0219       if (smatch theMatch; regex_match(result, theMatch, reTemplateArgs)) {
0220         //std::cout <<"found match \""<<theMatch.str(1) <<"\"" <<std::endl;
0221         //static regex const templateClosing(">$");
0222         //std::string aMatch = regex_replace(theMatch.str(1),templateClosing,"");
0223         std::string aMatch = theMatch.str(1);
0224         if constexpr (debug) {
0225           prefix += "  ";
0226         }
0227         std::string theSub = handleTemplateArguments(aMatch);
0228         if constexpr (debug) {
0229           prefix.pop_back();
0230           prefix.pop_back();
0231           std::cout << prefix << " aMatch " << aMatch << " theSub " << theSub << std::endl;
0232         }
0233         regex const eMatch(std::string("(^[^<]*)<") + aMatch + ">");
0234         result = regex_replace(result, eMatch, theSub + "$1");
0235       }
0236       return removeAllSpaces(result);
0237     }
0238 
0239     std::string handleTemplateArguments(std::string const& iIn) {
0240       using namespace std;
0241       std::string result = removeExtraSpaces(iIn);
0242       if constexpr (debug) {
0243         std::cout << prefix << "handleTemplateArguments " << iIn << " removeExtraSpaces " << result << std::endl;
0244       }
0245 
0246       // Trick to have every full class name to end with comma to
0247       // avoid treating the end as a special case
0248       result += ",";
0249 
0250       std::string result2;
0251       result2.reserve(iIn.size());
0252       unsigned int openTemplate = 0;
0253       bool hadTemplate = false;
0254       size_t begin = 0;
0255       for (size_t i = 0, size = result.size(); i < size; ++i) {
0256         if (result[i] == '<') {
0257           ++openTemplate;
0258           hadTemplate = true;
0259           continue;
0260         } else if (result[i] == '>') {
0261           --openTemplate;
0262         }
0263         // If we are not within the template arguments of a class template
0264         // - encountering comma means that we are within a template
0265         //   argument of some other class template, and we've reached
0266         //   a point when we should translate the argument class name
0267         // - encountering colon, but only if the class name so far
0268         //   itself was a template, we've reached a point when we
0269         //   should translate the class name
0270         if (const bool hasComma = result[i] == ',', hasColon = hadTemplate and result[i] == ':';
0271             openTemplate == 0 and (hasComma or hasColon)) {
0272           std::string templateClass = result.substr(begin, i - begin);
0273           if constexpr (debug) {
0274             std::cout << prefix << " templateClass " << templateClass << std::endl;
0275           }
0276           if (hadTemplate) {
0277             if constexpr (debug) {
0278               prefix += "  ";
0279             }
0280             std::string friendlierName = subFriendlyName(templateClass);
0281             if constexpr (debug) {
0282               prefix.pop_back();
0283               prefix.pop_back();
0284               std::cout << prefix << " friendlierName " << friendlierName << std::endl;
0285             }
0286             result2 += friendlierName;
0287           } else {
0288             result2 += templateClass;
0289           }
0290           if constexpr (debug) {
0291             std::cout << prefix << " result2 " << result2 << std::endl;
0292           }
0293           // reset counters
0294           hadTemplate = false;
0295           begin = i + 1;
0296           // With colon we need to eat the second colon as well
0297           if (hasColon) {
0298             assert(result[begin] == ':');
0299             ++begin;
0300           }
0301         }
0302       }
0303 
0304       result = regex_replace(result2, reComma, "");
0305       if constexpr (debug) {
0306         std::cout << prefix << " reComma " << result << std::endl;
0307       }
0308       return result;
0309     }
0310     std::string friendlyName(std::string const& iFullName) {
0311       if constexpr (debug) {
0312         std::cout << "\nfriendlyName for " << iFullName << std::endl;
0313         prefix = " ";
0314       }
0315       typedef oneapi::tbb::concurrent_unordered_map<std::string, std::string> Map;
0316       static Map s_fillToFriendlyName;
0317       auto itFound = s_fillToFriendlyName.find(iFullName);
0318       if (s_fillToFriendlyName.end() == itFound) {
0319         itFound = s_fillToFriendlyName
0320                       .insert(Map::value_type(iFullName, handleNamespaces(subFriendlyName(standardRenames(iFullName)))))
0321                       .first;
0322       }
0323       if constexpr (debug) {
0324         std::cout << "result " << itFound->second << std::endl;
0325       }
0326       return itFound->second;
0327     }
0328   }  // namespace friendlyname
0329 }  // namespace edm