Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-09-12 10:01:35

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