Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-04-08 00:35:05

0001 
0002 #include "DataFormats/Provenance/interface/ProductResolverIndexHelper.h"
0003 #include "DataFormats/Provenance/interface/ViewTypeChecker.h"
0004 #include "FWCore/Reflection/interface/DictionaryTools.h"
0005 #include "FWCore/Utilities/interface/EDMException.h"
0006 #include "FWCore/Reflection/interface/TypeWithDict.h"
0007 #include "FWCore/Utilities/interface/WrappedClassName.h"
0008 #include "FWCore/Utilities/interface/getAnyPtr.h"
0009 
0010 #include <TClass.h>
0011 
0012 #include <cassert>
0013 #include <iostream>
0014 #include <limits>
0015 
0016 namespace edm {
0017 
0018   namespace productholderindexhelper {
0019     TypeID getContainedTypeFromWrapper(TypeID const& wrappedTypeID, std::string const& className) {
0020       static int const vtcOffset =
0021           TClass::GetClass("edm::WrapperBase")->GetBaseClassOffset(TClass::GetClass("edm::ViewTypeChecker"));
0022       static TClass const* const wbClass = TClass::GetClass("edm::WrapperBase");
0023       static std::string const refVector("edm::RefVector<");
0024       static std::string const refToBaseVector("edm::RefToBaseVector<");
0025       static std::string const ptrVector("edm::PtrVector<");
0026       static std::string const vectorPtr("std::vector<edm::Ptr<");
0027       static std::string const vectorUniquePtr("std::vector<std::unique_ptr<");
0028       static std::string const associationMap("edm::AssociationMap<");
0029       static std::string const newDetSetVector("edmNew::DetSetVector<");
0030       static size_t const rvsize = refVector.size();
0031       static size_t const rtbvsize = refToBaseVector.size();
0032       static size_t const pvsize = ptrVector.size();
0033       static size_t const vpsize = vectorPtr.size();
0034       static size_t const vupsize = vectorUniquePtr.size();
0035       static size_t const amsize = associationMap.size();
0036       static size_t const ndsize = newDetSetVector.size();
0037       bool mayBeRefVector = (className.substr(0, rvsize) == refVector) ||
0038                             (className.substr(0, rtbvsize) == refToBaseVector) ||
0039                             (className.substr(0, pvsize) == ptrVector) || (className.substr(0, vpsize) == vectorPtr) ||
0040                             (className.substr(0, vupsize) == vectorUniquePtr);
0041       // AssociationMap and edmNew::DetSetVector do not support View and
0042       // this function is used to get a contained type that can be accessed
0043       // using a View. So return the void type in these cases.
0044       // In practice, they were the only types causing a problem, but any
0045       // type with a typedef named value_type that does not support
0046       // View might also cause problems and might need to be added here in
0047       // the future.
0048       if (className.substr(0, amsize) == associationMap || className.substr(0, ndsize) == newDetSetVector) {
0049         return TypeID(typeid(void));
0050       }
0051       TClass* cl = TClass::GetClass(wrappedTypeID.className().c_str());
0052       if (cl == nullptr) {
0053         return TypeID(typeid(void));
0054       }
0055       void* p = cl->New();
0056       int offset = cl->GetBaseClassOffset(wbClass) + vtcOffset;
0057       std::unique_ptr<ViewTypeChecker> checker = getAnyPtr<ViewTypeChecker>(p, offset);
0058       if (mayBeRefVector) {
0059         std::type_info const& ti = checker->memberTypeInfo();
0060         if (ti != typeid(void)) {
0061           return TypeID(ti);
0062         }
0063       }
0064       return TypeID(checker->valueTypeInfo());
0065     }
0066 
0067     TypeID getContainedType(TypeID const& typeID) {
0068       const std::string& className = typeID.className();
0069       TypeWithDict const wrappedType = TypeWithDict::byName(wrappedClassName(className));
0070       TypeID const wrappedTypeID = TypeID(wrappedType.typeInfo());
0071       return getContainedTypeFromWrapper(wrappedTypeID, className);
0072     }
0073 
0074     bool typeIsViewCompatible(TypeID const& requestedViewType,
0075                               TypeID const& wrappedtypeID,
0076                               std::string const& className) {
0077       auto elementType = getContainedTypeFromWrapper(wrappedtypeID, className);
0078       if (elementType == TypeID(typeid(void)) or elementType == TypeID()) {
0079         //the wrapped type is not a container
0080         return false;
0081       }
0082       if (elementType == requestedViewType) {
0083         return true;
0084       }
0085       //need to check for inheritance match
0086       std::vector<std::string> missingDictionaries;
0087       std::vector<TypeWithDict> baseTypes;
0088       if (!public_base_classes(missingDictionaries, elementType, baseTypes)) {
0089         return false;
0090       }
0091       for (auto const& base : baseTypes) {
0092         if (TypeID(base.typeInfo()) == requestedViewType) {
0093           return true;
0094         }
0095       }
0096       return false;
0097     }
0098 
0099   }  // namespace productholderindexhelper
0100 
0101   ProductResolverIndexHelper::ProductResolverIndexHelper()
0102       : nextIndexValue_(0),
0103         beginElements_(0),
0104         items_(new std::set<ProductResolverIndexHelper::Item>),
0105         processItems_(new std::set<std::string>) {}
0106 
0107   ProductResolverIndex ProductResolverIndexHelper::index(KindOfType kindOfType,
0108                                                          TypeID const& typeID,
0109                                                          char const* moduleLabel,
0110                                                          char const* instance,
0111                                                          char const* process) const {
0112     unsigned int iToIndexAndNames = indexToIndexAndNames(kindOfType, typeID, moduleLabel, instance, process);
0113 
0114     if (iToIndexAndNames == std::numeric_limits<unsigned int>::max()) {
0115       return ProductResolverIndexInvalid;
0116     }
0117     return indexAndNames_[iToIndexAndNames].index();
0118   }
0119 
0120   ProductResolverIndexHelper::Matches::Matches(ProductResolverIndexHelper const* productResolverIndexHelper,
0121                                                unsigned int startInIndexAndNames,
0122                                                unsigned int numberOfMatches)
0123       : productResolverIndexHelper_(productResolverIndexHelper),
0124         startInIndexAndNames_(startInIndexAndNames),
0125         numberOfMatches_(numberOfMatches) {
0126     if (numberOfMatches != 0 &&
0127         startInIndexAndNames_ + numberOfMatches_ > productResolverIndexHelper_->indexAndNames_.size()) {
0128       throw Exception(errors::LogicError)
0129           << "ProductResolverIndexHelper::Matches::Matches - Arguments exceed vector bounds.\n";
0130     }
0131   }
0132 
0133   ProductResolverIndex ProductResolverIndexHelper::Matches::index(unsigned int i) const {
0134     if (i >= numberOfMatches_) {
0135       throw Exception(errors::LogicError) << "ProductResolverIndexHelper::Matches::index - Argument is out of range.\n";
0136     }
0137     return productResolverIndexHelper_->indexAndNames_[startInIndexAndNames_ + i].index();
0138   }
0139 
0140   bool ProductResolverIndexHelper::Matches::isFullyResolved(unsigned int i) const {
0141     if (i >= numberOfMatches_) {
0142       throw Exception(errors::LogicError)
0143           << "ProductResolverIndexHelper::Matches::isFullyResolved - Argument is out of range.\n";
0144     }
0145     return (productResolverIndexHelper_->indexAndNames_[startInIndexAndNames_ + i].startInProcessNames() != 0U);
0146   }
0147 
0148   char const* ProductResolverIndexHelper::Matches::processName(unsigned int i) const {
0149     if (i >= numberOfMatches_) {
0150       throw Exception(errors::LogicError)
0151           << "ProductResolverIndexHelper::Matches::processName - Argument is out of range.\n";
0152     }
0153     unsigned int startInProcessNames =
0154         productResolverIndexHelper_->indexAndNames_[startInIndexAndNames_ + i].startInProcessNames();
0155     return &productResolverIndexHelper_->processNames_[startInProcessNames];
0156   }
0157 
0158   char const* ProductResolverIndexHelper::Matches::productInstanceName(unsigned int i) const {
0159     if (i >= numberOfMatches_) {
0160       throw Exception(errors::LogicError)
0161           << "ProductResolverIndexHelper::Matches::productInstanceName - Argument is out of range.\n";
0162     }
0163     unsigned int start =
0164         productResolverIndexHelper_->indexAndNames_[startInIndexAndNames_ + i].startInBigNamesContainer();
0165     auto moduleLabelSize = strlen(&productResolverIndexHelper_->bigNamesContainer_[start]);
0166     return &productResolverIndexHelper_->bigNamesContainer_[start + moduleLabelSize + 1];
0167   }
0168 
0169   char const* ProductResolverIndexHelper::Matches::moduleLabel(unsigned int i) const {
0170     if (i >= numberOfMatches_) {
0171       throw Exception(errors::LogicError)
0172           << "ProductResolverIndexHelper::Matches::moduleLabel - Argument is out of range.\n";
0173     }
0174     unsigned int start =
0175         productResolverIndexHelper_->indexAndNames_[startInIndexAndNames_ + i].startInBigNamesContainer();
0176     return &productResolverIndexHelper_->bigNamesContainer_[start];
0177   }
0178 
0179   ProductResolverIndexHelper::Matches ProductResolverIndexHelper::relatedIndexes(KindOfType kindOfType,
0180                                                                                  TypeID const& typeID,
0181                                                                                  char const* moduleLabel,
0182                                                                                  char const* instance) const {
0183     unsigned int startInIndexAndNames = indexToIndexAndNames(kindOfType, typeID, moduleLabel, instance, nullptr);
0184     unsigned int numberOfMatches = 1;
0185 
0186     if (startInIndexAndNames == std::numeric_limits<unsigned int>::max()) {
0187       numberOfMatches = 0;
0188     } else {
0189       auto vSize = indexAndNames_.size();
0190       for (unsigned int j = startInIndexAndNames + 1U; j < vSize && (indexAndNames_[j].startInProcessNames() != 0U);
0191            ++j) {
0192         ++numberOfMatches;
0193       }
0194     }
0195     return Matches(this, startInIndexAndNames, numberOfMatches);
0196   }
0197 
0198   ProductResolverIndexHelper::Matches ProductResolverIndexHelper::relatedIndexes(KindOfType kindOfType,
0199                                                                                  TypeID const& typeID) const {
0200     unsigned int startInIndexAndNames = std::numeric_limits<unsigned int>::max();
0201     unsigned int numberOfMatches = 0;
0202 
0203     // Look for the type and check to see if it found it
0204     unsigned iType = indexToType(kindOfType, typeID);
0205     if (iType != std::numeric_limits<unsigned int>::max()) {
0206       // Get the range of entries with a matching TypeID
0207       Range const& range = ranges_[iType];
0208 
0209       startInIndexAndNames = range.begin();
0210       numberOfMatches = range.end() - range.begin();
0211     }
0212     return Matches(this, startInIndexAndNames, numberOfMatches);
0213   }
0214 
0215   ProductResolverIndex ProductResolverIndexHelper::insert(TypeID const& typeID,
0216                                                           char const* moduleLabel,
0217                                                           char const* instance,
0218                                                           char const* process,
0219                                                           TypeID const& containedTypeID,
0220                                                           std::vector<TypeWithDict>* baseTypesOfContainedType) {
0221     if (!items_) {
0222       throw Exception(errors::LogicError)
0223           << "ProductResolverIndexHelper::insert - Attempt to insert more elements after frozen.\n";
0224     }
0225 
0226     if (process == nullptr || *process == '\0') {
0227       throw Exception(errors::LogicError) << "ProductResolverIndexHelper::insert - Empty process.\n";
0228     }
0229 
0230     // Throw if this has already been inserted
0231     Item item(PRODUCT_TYPE, typeID, moduleLabel, instance, process, 0);
0232     std::set<Item>::iterator iter = items_->find(item);
0233     if (iter != items_->end()) {
0234       throw Exception(errors::LogicError)
0235           << "ProductResolverIndexHelper::insert - Attempt to insert duplicate entry.\n";
0236     }
0237 
0238     // Put in an entry for the product
0239     item.setIndex(nextIndexValue_);
0240     unsigned int savedProductIndex = nextIndexValue_;
0241     ++nextIndexValue_;
0242     items_->insert(item);
0243 
0244     // Put in an entry for the product with an empty process name
0245     // if it is not already there
0246     item.clearProcess();
0247     iter = items_->find(item);
0248     if (iter == items_->end()) {
0249       item.setIndex(nextIndexValue_);
0250       ++nextIndexValue_;
0251       items_->insert(item);
0252     }
0253 
0254     // Now put in entries for a contained class if this is a
0255     // recognized container.
0256     if (containedTypeID != TypeID(typeid(void)) && containedTypeID != TypeID()) {
0257       TypeWithDict containedType(containedTypeID.typeInfo());
0258 
0259       Item containedItem(ELEMENT_TYPE, containedTypeID, moduleLabel, instance, process, savedProductIndex);
0260       iter = items_->find(containedItem);
0261       if (iter != items_->end()) {
0262         containedItem.setIndex(ProductResolverIndexAmbiguous);
0263         items_->erase(iter);
0264       }
0265       items_->insert(containedItem);
0266 
0267       containedItem.clearProcess();
0268       iter = items_->find(containedItem);
0269       if (iter == items_->end()) {
0270         containedItem.setIndex(nextIndexValue_);
0271         ++nextIndexValue_;
0272         items_->insert(containedItem);
0273       }
0274 
0275       // Repeat this for all public base classes of the contained type
0276       if (baseTypesOfContainedType) {
0277         for (TypeWithDict const& baseType : *baseTypesOfContainedType) {
0278           TypeID baseTypeID(baseType.typeInfo());
0279           Item baseItem(ELEMENT_TYPE, baseTypeID, moduleLabel, instance, process, savedProductIndex);
0280           iter = items_->find(baseItem);
0281           if (iter != items_->end()) {
0282             baseItem.setIndex(ProductResolverIndexAmbiguous);
0283             items_->erase(iter);
0284           }
0285           items_->insert(baseItem);
0286 
0287           baseItem.clearProcess();
0288           iter = items_->find(baseItem);
0289           if (iter == items_->end()) {
0290             baseItem.setIndex(nextIndexValue_);
0291             ++nextIndexValue_;
0292             items_->insert(baseItem);
0293           }
0294         }
0295       }
0296     }
0297     return savedProductIndex;
0298   }
0299 
0300   ProductResolverIndex ProductResolverIndexHelper::insert(TypeID const& typeID,
0301                                                           char const* moduleLabel,
0302                                                           char const* instance,
0303                                                           char const* process) {
0304     TypeID containedTypeID = productholderindexhelper::getContainedType(typeID);
0305     bool hasContainedType = (containedTypeID != TypeID(typeid(void)) && containedTypeID != TypeID());
0306     std::vector<TypeWithDict> baseTypes;
0307     std::vector<TypeWithDict>* baseTypesOfContainedType = &baseTypes;
0308     if (hasContainedType) {
0309       std::vector<std::string> missingDictionaries;
0310       public_base_classes(missingDictionaries, containedTypeID, baseTypes);
0311     }
0312     return insert(typeID, moduleLabel, instance, process, containedTypeID, baseTypesOfContainedType);
0313   }
0314 
0315   void ProductResolverIndexHelper::setFrozen() {
0316     if (!items_)
0317       return;
0318 
0319     // Make a first pass and count things so we
0320     // can reserve memory in the vectors. Also
0321     // fill processItems_ on the first pass.
0322     bool iFirstThisType = true;
0323     bool beginElementsWasSet = false;
0324     TypeID previousTypeID;
0325     KindOfType previousKindOfType = PRODUCT_TYPE;
0326     std::string previousModuleLabel;
0327     std::string previousInstance;
0328     unsigned int iCountTypes = 0;
0329     unsigned int iCountCharacters = 0;
0330     for (auto const& item : *items_) {
0331       if (iFirstThisType || item.typeID() != previousTypeID || item.kindOfType() != previousKindOfType) {
0332         ++iCountTypes;
0333         iFirstThisType = true;
0334 
0335         if (!beginElementsWasSet) {
0336           if (item.kindOfType() == ELEMENT_TYPE) {
0337             beginElementsWasSet = true;
0338           } else {
0339             beginElements_ = iCountTypes;
0340           }
0341         }
0342       }
0343 
0344       processItems_->insert(item.process());
0345 
0346       if (iFirstThisType || item.moduleLabel() != previousModuleLabel || item.instance() != previousInstance) {
0347         iCountCharacters += item.moduleLabel().size();
0348         iCountCharacters += item.instance().size();
0349         iCountCharacters += 2;
0350       }
0351 
0352       iFirstThisType = false;
0353       previousTypeID = item.typeID();
0354       previousKindOfType = item.kindOfType();
0355       previousModuleLabel = item.moduleLabel();
0356       previousInstance = item.instance();
0357     }
0358 
0359     // Size and fill the process name vector
0360     unsigned int processNamesSize = 0;
0361     for (auto const& processItem : *processItems_) {
0362       processNamesSize += processItem.size();
0363       ++processNamesSize;
0364     }
0365     processNames_.reserve(processNamesSize);
0366     for (auto const& processItem : *processItems_) {
0367       for (auto const& c : processItem) {
0368         processNames_.push_back(c);
0369       }
0370       processNames_.push_back('\0');
0371       lookupProcessNames_.push_back(processItem);
0372     }
0373 
0374     // Reserve memory in the vectors
0375     sortedTypeIDs_.reserve(iCountTypes);
0376     ranges_.reserve(iCountTypes);
0377     indexAndNames_.reserve(items_->size());
0378     bigNamesContainer_.reserve(iCountCharacters);
0379 
0380     // Second pass. Really fill the vectors this time.
0381     bool iFirstType = true;
0382     iFirstThisType = true;
0383     previousTypeID = TypeID();
0384     unsigned int iCount = 0;
0385     unsigned int iBeginning = 0;
0386     iCountCharacters = 0;
0387     unsigned int previousCharacterCount = 0;
0388     if (!items_->empty()) {
0389       for (auto const& item : *items_) {
0390         if (iFirstThisType || item.typeID() != previousTypeID || item.kindOfType() != previousKindOfType) {
0391           iFirstThisType = true;
0392           sortedTypeIDs_.push_back(item.typeID());
0393           if (iFirstType) {
0394             iFirstType = false;
0395           } else {
0396             ranges_.push_back(Range(iBeginning, iCount));
0397           }
0398           iBeginning = iCount;
0399         }
0400         ++iCount;
0401 
0402         if (iFirstThisType || item.moduleLabel() != previousModuleLabel || item.instance() != previousInstance) {
0403           unsigned int labelSize = item.moduleLabel().size();
0404           for (unsigned int j = 0; j < labelSize; ++j) {
0405             bigNamesContainer_.push_back(item.moduleLabel()[j]);
0406           }
0407           bigNamesContainer_.push_back('\0');
0408 
0409           unsigned int instanceSize = item.instance().size();
0410           for (unsigned int j = 0; j < instanceSize; ++j) {
0411             bigNamesContainer_.push_back(item.instance()[j]);
0412           }
0413           bigNamesContainer_.push_back('\0');
0414 
0415           previousCharacterCount = iCountCharacters;
0416 
0417           iCountCharacters += labelSize;
0418           iCountCharacters += instanceSize;
0419           iCountCharacters += 2;
0420         }
0421 
0422         unsigned int processStart = processIndex(item.process().c_str());
0423         if (processStart == std::numeric_limits<unsigned int>::max()) {
0424           throw Exception(errors::LogicError)
0425               << "ProductResolverIndexHelper::setFrozen - Process not found in processNames_.\n";
0426         }
0427         indexAndNames_.emplace_back(item.index(), previousCharacterCount, processStart);
0428 
0429         iFirstThisType = false;
0430         previousTypeID = item.typeID();
0431         previousKindOfType = item.kindOfType();
0432         previousModuleLabel = item.moduleLabel();
0433         previousInstance = item.instance();
0434       }
0435       ranges_.push_back(Range(iBeginning, iCount));
0436     }
0437 
0438     // Some sanity checks to protect against out of bounds vector accesses
0439     // These should only fail if there is a bug. If profiling ever shows
0440     // them to be expensive one might delete them.
0441     sanityCheck();
0442 
0443     // Cleanup, do not need the temporary containers anymore
0444     // propagate_const<T> has no reset() function
0445     items_ = nullptr;
0446     processItems_ = nullptr;
0447   }
0448 
0449   std::vector<std::string> const& ProductResolverIndexHelper::lookupProcessNames() const {
0450     if (items_) {
0451       throw Exception(errors::LogicError)
0452           << "ProductResolverIndexHelper::lookupProcessNames - Attempt to access names before frozen.\n";
0453     }
0454     return lookupProcessNames_;
0455   }
0456 
0457   unsigned int ProductResolverIndexHelper::indexToIndexAndNames(KindOfType kindOfType,
0458                                                                 TypeID const& typeID,
0459                                                                 char const* moduleLabel,
0460                                                                 char const* instance,
0461                                                                 char const* process) const {
0462     // Look for the type and check to see if it found it
0463     unsigned iType = indexToType(kindOfType, typeID);
0464     if (iType != std::numeric_limits<unsigned int>::max()) {
0465       unsigned startProcess = 0;
0466       if (process) {
0467         startProcess = processIndex(process);
0468         if (startProcess == std::numeric_limits<unsigned int>::max()) {
0469           return std::numeric_limits<unsigned int>::max();
0470         }
0471       }
0472 
0473       ProductResolverIndexHelper::Range const& range = ranges_[iType];
0474       unsigned int begin = range.begin();
0475       unsigned int end = range.end();
0476 
0477       while (begin < end) {
0478         unsigned int midpoint = begin + ((end - begin) / 2);
0479         char const* namePtr = &bigNamesContainer_[indexAndNames_[midpoint].startInBigNamesContainer()];
0480 
0481         // Compare the module label
0482         char const* label = moduleLabel;
0483         while (*namePtr && (*namePtr == *label)) {
0484           ++namePtr;
0485           ++label;
0486         }
0487         if (*namePtr == *label) {  // true only if both are at the '\0' at the end of the C string
0488           ++namePtr;               // move to the next C string
0489 
0490           // Compare the instance name
0491           char const* instanceName = instance;
0492           while (*namePtr && (*namePtr == *instanceName)) {
0493             ++namePtr;
0494             ++instanceName;
0495           }
0496           if (*namePtr == *instanceName) {
0497             // Compare the process name
0498             if (startProcess == indexAndNames_[midpoint].startInProcessNames()) {
0499               return midpoint;
0500             } else {
0501               if (indexAndNames_[midpoint].startInProcessNames() > startProcess) {
0502                 while (true) {
0503                   --midpoint;
0504                   if (indexAndNames_[midpoint].startInProcessNames() == startProcess) {
0505                     return midpoint;
0506                   }
0507                   if (indexAndNames_[midpoint].startInProcessNames() == 0)
0508                     break;
0509                 }
0510               } else {
0511                 while (true) {
0512                   ++midpoint;
0513                   if (midpoint == indexAndNames_.size())
0514                     break;
0515                   if (indexAndNames_[midpoint].startInProcessNames() == 0)
0516                     break;
0517                   if (indexAndNames_[midpoint].startInProcessNames() == startProcess) {
0518                     return midpoint;
0519                   }
0520                 }
0521               }
0522               break;
0523             }
0524           } else if (*namePtr < *instanceName) {
0525             if (begin == midpoint)
0526               break;
0527             begin = midpoint;
0528           } else {
0529             end = midpoint;
0530           }
0531         } else if (*namePtr < *label) {
0532           if (begin == midpoint)
0533             break;
0534           begin = midpoint;
0535         } else {
0536           end = midpoint;
0537         }
0538       }  // end while (begin < end)
0539     }
0540     return std::numeric_limits<unsigned int>::max();
0541   }
0542 
0543   unsigned int ProductResolverIndexHelper::indexToType(KindOfType kindOfType, TypeID const& typeID) const {
0544     unsigned int beginType = 0;
0545     unsigned int endType = beginElements_;
0546     if (kindOfType == ELEMENT_TYPE) {
0547       beginType = beginElements_;
0548       endType = sortedTypeIDs_.size();
0549     }
0550 
0551     while (beginType < endType) {
0552       unsigned int midpointType = beginType + ((endType - beginType) / 2);
0553       if (sortedTypeIDs_[midpointType] == typeID) {
0554         return midpointType;  // Found it
0555       } else if (sortedTypeIDs_[midpointType] < typeID) {
0556         if (beginType == midpointType)
0557           break;
0558         beginType = midpointType;
0559       } else {
0560         endType = midpointType;
0561       }
0562     }
0563     return std::numeric_limits<unsigned int>::max();  // Failed to find it
0564   }
0565 
0566   unsigned int ProductResolverIndexHelper::processIndex(char const* process) const {
0567     char const* ptr = &processNames_[0];
0568     char const* begin = ptr;
0569     while (true) {
0570       char const* p = process;
0571       char const* beginName = ptr;
0572       while (*ptr && (*ptr == *p)) {
0573         ++ptr;
0574         ++p;
0575       }
0576       if (*ptr == *p) {
0577         return beginName - begin;
0578       }
0579       while (*ptr) {
0580         ++ptr;
0581       }
0582       ++ptr;
0583       if (static_cast<unsigned>(ptr - begin) >= processNames_.size()) {
0584         return std::numeric_limits<unsigned int>::max();
0585       }
0586     }
0587     return 0;
0588   }
0589 
0590   ProductResolverIndexHelper::ModulesToIndiciesMap ProductResolverIndexHelper::indiciesForModulesInProcess(
0591       const std::string& iProcessName) const {
0592     ModulesToIndiciesMap result;
0593     for (unsigned int i = 0; i < beginElements_; ++i) {
0594       auto const& range = ranges_[i];
0595       for (unsigned int j = range.begin(); j < range.end(); ++j) {
0596         auto const& indexAndNames = indexAndNames_[j];
0597         if (0 == strcmp(&processNames_[indexAndNames.startInProcessNames()], iProcessName.c_str())) {
0598           //The first null terminated string is the module label
0599           auto pModLabel = &bigNamesContainer_[indexAndNames.startInBigNamesContainer()];
0600           auto l = strlen(pModLabel);
0601           auto pInstance = pModLabel + l + 1;
0602           result.emplace(pModLabel, std::make_tuple(&sortedTypeIDs_[i], pInstance, indexAndNames.index()));
0603         }
0604       }
0605     }
0606     return result;
0607   }
0608 
0609   void ProductResolverIndexHelper::sanityCheck() const {
0610     bool sanityChecksPass = true;
0611     if (sortedTypeIDs_.size() != ranges_.size())
0612       sanityChecksPass = false;
0613 
0614     unsigned int previousEnd = 0;
0615     for (auto const& range : ranges_) {
0616       if (range.begin() != previousEnd)
0617         sanityChecksPass = false;
0618       if (range.begin() >= range.end())
0619         sanityChecksPass = false;
0620       previousEnd = range.end();
0621     }
0622     if (previousEnd != indexAndNames_.size())
0623       sanityChecksPass = false;
0624 
0625     unsigned maxStart = 0;
0626     unsigned maxStartProcess = 0;
0627     for (auto const& indexAndName : indexAndNames_) {
0628       if (indexAndName.index() >= nextIndexValue_ && indexAndName.index() != ProductResolverIndexAmbiguous)
0629         sanityChecksPass = false;
0630 
0631       if (indexAndName.startInBigNamesContainer() >= bigNamesContainer_.size())
0632         sanityChecksPass = false;
0633       if (indexAndName.startInProcessNames() >= processNames_.size())
0634         sanityChecksPass = false;
0635 
0636       if (indexAndName.startInBigNamesContainer() > maxStart)
0637         maxStart = indexAndName.startInBigNamesContainer();
0638       if (indexAndName.startInProcessNames() > maxStartProcess)
0639         maxStartProcess = indexAndName.startInProcessNames();
0640     }
0641 
0642     if (!indexAndNames_.empty()) {
0643       if (bigNamesContainer_.back() != '\0')
0644         sanityChecksPass = false;
0645       if (processNames_.back() != '\0')
0646         sanityChecksPass = false;
0647       if (maxStart >= bigNamesContainer_.size())
0648         sanityChecksPass = false;
0649       unsigned int countZeroes = 0;
0650       for (unsigned j = maxStart; j < bigNamesContainer_.size(); ++j) {
0651         if (bigNamesContainer_[j] == '\0') {
0652           ++countZeroes;
0653         }
0654       }
0655       if (countZeroes != 2)
0656         sanityChecksPass = false;
0657       if (maxStartProcess >= processNames_.size())
0658         sanityChecksPass = false;
0659       countZeroes = 0;
0660       for (unsigned j = maxStartProcess; j < processNames_.size(); ++j) {
0661         if (processNames_[j] == '\0') {
0662           ++countZeroes;
0663         }
0664       }
0665       if (countZeroes != 1)
0666         sanityChecksPass = false;
0667     }
0668 
0669     if (!sanityChecksPass) {
0670       throw Exception(errors::LogicError) << "ProductResolverIndexHelper::setFrozen - Detected illegal state.\n";
0671     }
0672   }
0673 
0674   ProductResolverIndexHelper::Item::Item(KindOfType kindOfType,
0675                                          TypeID const& typeID,
0676                                          std::string const& moduleLabel,
0677                                          std::string const& instance,
0678                                          std::string const& process,
0679                                          ProductResolverIndex index)
0680       : kindOfType_(kindOfType),
0681         typeID_(typeID),
0682         moduleLabel_(moduleLabel),
0683         instance_(instance),
0684         process_(process),
0685         index_(index) {}
0686 
0687   bool ProductResolverIndexHelper::Item::operator<(Item const& right) const {
0688     if (kindOfType_ < right.kindOfType_)
0689       return true;
0690     if (kindOfType_ > right.kindOfType_)
0691       return false;
0692     if (typeID_ < right.typeID_)
0693       return true;
0694     if (typeID_ > right.typeID_)
0695       return false;
0696     if (moduleLabel_ < right.moduleLabel_)
0697       return true;
0698     if (moduleLabel_ > right.moduleLabel_)
0699       return false;
0700     if (instance_ < right.instance_)
0701       return true;
0702     if (instance_ > right.instance_)
0703       return false;
0704     return process_ < right.process_;
0705   }
0706 
0707   void ProductResolverIndexHelper::print(std::ostream& os) const {
0708     os << "\n******* Dump ProductResolverIndexHelper *************************\n";
0709 
0710     os << "\nnextIndexValue_ = " << nextIndexValue_ << "\n";
0711     os << "beginElements_ = " << beginElements_ << "\n";
0712 
0713     os << "\n******* sortedTypeIDs_ \n";
0714     for (auto const& i : sortedTypeIDs_) {
0715       os << i << "\n";
0716     }
0717     os << "******* ranges_ \n";
0718     for (auto const& i : ranges_) {
0719       os << i.begin() << " " << i.end() << "\n";
0720     }
0721     os << "******* indexAndNames_ \n";
0722     for (auto const& i : indexAndNames_) {
0723       os << i.index() << " " << i.startInBigNamesContainer() << " ";
0724       char const* ptr = &bigNamesContainer_[i.startInBigNamesContainer()];
0725       while (*ptr) {
0726         os << *ptr;
0727         ++ptr;
0728       }
0729       ++ptr;
0730       os << " ";
0731       while (*ptr) {
0732         os << *ptr;
0733         ++ptr;
0734       }
0735       os << " " << i.startInProcessNames() << " ";
0736       ptr = &processNames_[i.startInProcessNames()];
0737       while (*ptr) {
0738         os << *ptr;
0739         ++ptr;
0740       }
0741       os << "\n";
0742     }
0743     os << "******* bigNamesContainer_ \n";
0744     for (auto i : bigNamesContainer_) {
0745       if (i == '\0')
0746         os << '\\' << '0';
0747       else
0748         os << i;
0749     }
0750     if (!bigNamesContainer_.empty())
0751       os << "\n";
0752     os << "******* processNames_ \n";
0753     for (auto i : processNames_) {
0754       if (i == '\0')
0755         os << '\\' << '0';
0756       else
0757         os << i;
0758     }
0759     if (!processNames_.empty())
0760       os << "\n";
0761     if (items_) {
0762       os << "******* items_ \n";
0763       for (auto const& item : *items_) {
0764         std::cout << item.kindOfType() << " " << item.moduleLabel() << " " << item.instance() << " " << item.process()
0765                   << " " << item.index() << " " << item.typeID() << "\n";
0766       }
0767     }
0768     if (processItems_) {
0769       os << "******* processItems_ \n";
0770       for (auto const& item : *processItems_) {
0771         os << item << "\n";
0772       }
0773     }
0774     os << "sortedTypeIDs_.size() = " << sortedTypeIDs_.size() << "\n";
0775     os << "indexAndNames_.size() = " << indexAndNames_.size() << "\n";
0776     os << "bigNamesContainer_.size() = " << bigNamesContainer_.size() << "\n";
0777     os << "processNames_.size() = " << processNames_.size() << "\n";
0778     os << "\n";
0779   }
0780 }  // namespace edm