Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 /*----------------------------------------------------------------------
0002 
0003 ----------------------------------------------------------------------*/
0004 #include <cassert>
0005 #include <ostream>
0006 #include "oneapi/tbb/concurrent_unordered_map.h"
0007 #include "FWCore/Utilities/interface/TypeID.h"
0008 #include "FWCore/Utilities/interface/FriendlyName.h"
0009 #include "FWCore/Utilities/interface/Exception.h"
0010 #include "FWCore/Utilities/interface/TypeDemangler.h"
0011 
0012 namespace edm {
0013   void TypeID::print(std::ostream& os) const {
0014     try {
0015       os << className();
0016     } catch (cms::Exception const&) {
0017       os << typeInfo().name();
0018     }
0019   }
0020 
0021   namespace {
0022 
0023     TypeID const nullTypeID;
0024 
0025     std::string typeToClassName(std::type_info const& iType) {
0026       try {
0027         return typeDemangle(iType.name());
0028       } catch (cms::Exception const& e) {
0029         cms::Exception theError("Name Demangling Error");
0030         theError << "TypeID::typeToClassName: can't demangle " << iType.name() << '\n';
0031         theError.append(e);
0032         throw theError;
0033       }
0034     }
0035   }  // namespace
0036   struct TypeIDHasher {
0037     size_t operator()(TypeID const& tid) const { return std::hash<std::string>{}(std::string(tid.name())); }
0038   };
0039 
0040   std::string const& TypeID::className() const {
0041     typedef oneapi::tbb::concurrent_unordered_map<edm::TypeID, std::string, TypeIDHasher> Map;
0042     static Map s_typeToName;
0043 
0044     auto itFound = s_typeToName.find(*this);
0045     if (s_typeToName.end() == itFound) {
0046       itFound = s_typeToName.insert(Map::value_type(*this, typeToClassName(typeInfo()))).first;
0047     }
0048     return itFound->second;
0049   }
0050 
0051   std::string TypeID::userClassName() const {
0052     std::string theName = className();
0053     if (theName.find("edm::Wrapper") == 0) {
0054       stripTemplate(theName);
0055     }
0056     return theName;
0057   }
0058 
0059   std::string TypeID::friendlyClassName() const { return friendlyname::friendlyName(className()); }
0060 
0061   bool stripTemplate(std::string& theName) {
0062     std::string const spec("<,>");
0063     char const space = ' ';
0064     std::string::size_type idx = theName.find_first_of(spec);
0065     if (idx == std::string::npos) {
0066       return false;
0067     }
0068     std::string::size_type first = 0;
0069     std::string::size_type after = idx;
0070     if (theName[idx] == '<') {
0071       after = theName.rfind('>');
0072       assert(after != std::string::npos);
0073       first = ++idx;
0074     } else {
0075       theName = theName.substr(0, idx);
0076     }
0077     std::string::size_type idxa = after;
0078     while (space == theName[--idxa])
0079       --after;
0080     std::string::size_type idxf = first;
0081     while (space == theName[idxf++])
0082       ++first;
0083     theName = theName.substr(first, after - first);
0084     return true;
0085   }
0086 
0087   std::string stripNamespace(std::string const& theName) {
0088     // Find last colon
0089     std::string::size_type colonIndex = theName.rfind(':');
0090     if (colonIndex == std::string::npos) {
0091       // No colons, so no namespace to strip
0092       return theName;
0093     }
0094     std::string::size_type bracketIndex = theName.rfind('>');
0095     if (bracketIndex == std::string::npos || bracketIndex < colonIndex) {
0096       // No '>' after last colon.  Strip up to and including last colon.
0097       return theName.substr(colonIndex + 1);
0098     }
0099     // There is a '>' after the last colon.
0100     int depth = 1;
0101     for (size_t index = bracketIndex; index != 0; --index) {
0102       char c = theName[index - 1];
0103       if (c == '>') {
0104         ++depth;
0105       } else if (c == '<') {
0106         --depth;
0107         assert(depth >= 0);
0108       } else if (depth == 0 && c == ':') {
0109         return theName.substr(index);
0110       }
0111     }
0112     return theName;
0113   }
0114 
0115   TypeID::operator bool() const { return !(*this == nullTypeID); }
0116 
0117   std::ostream& operator<<(std::ostream& os, TypeID const& id) {
0118     id.print(os);
0119     return os;
0120   }
0121 }  // namespace edm