Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:05: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<TypeID> 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   char const* ProductResolverIndexHelper::Matches::processName(unsigned int i) const {
0141     if (i >= numberOfMatches_) {
0142       throw Exception(errors::LogicError)
0143           << "ProductResolverIndexHelper::Matches::processName - Argument is out of range.\n";
0144     }
0145     unsigned int startInProcessNames =
0146         productResolverIndexHelper_->indexAndNames_[startInIndexAndNames_ + i].startInProcessNames();
0147     return &productResolverIndexHelper_->processNames_[startInProcessNames];
0148   }
0149 
0150   char const* ProductResolverIndexHelper::Matches::productInstanceName(unsigned int i) const {
0151     if (i >= numberOfMatches_) {
0152       throw Exception(errors::LogicError)
0153           << "ProductResolverIndexHelper::Matches::productInstanceName - Argument is out of range.\n";
0154     }
0155     unsigned int start =
0156         productResolverIndexHelper_->indexAndNames_[startInIndexAndNames_ + i].startInBigNamesContainer();
0157     auto moduleLabelSize = strlen(&productResolverIndexHelper_->bigNamesContainer_[start]);
0158     return &productResolverIndexHelper_->bigNamesContainer_[start + moduleLabelSize + 1];
0159   }
0160 
0161   char const* ProductResolverIndexHelper::Matches::moduleLabel(unsigned int i) const {
0162     if (i >= numberOfMatches_) {
0163       throw Exception(errors::LogicError)
0164           << "ProductResolverIndexHelper::Matches::moduleLabel - Argument is out of range.\n";
0165     }
0166     unsigned int start =
0167         productResolverIndexHelper_->indexAndNames_[startInIndexAndNames_ + i].startInBigNamesContainer();
0168     return &productResolverIndexHelper_->bigNamesContainer_[start];
0169   }
0170 
0171   ProductResolverIndexHelper::Matches ProductResolverIndexHelper::relatedIndexes(KindOfType kindOfType,
0172                                                                                  TypeID const& typeID,
0173                                                                                  char const* moduleLabel,
0174                                                                                  char const* instance) const {
0175     unsigned int startInIndexAndNames = indexToIndexAndNames(kindOfType, typeID, moduleLabel, instance, nullptr);
0176     unsigned int numberOfMatches = 1;
0177 
0178     if (startInIndexAndNames == std::numeric_limits<unsigned int>::max()) {
0179       numberOfMatches = 0;
0180     } else {
0181       auto vSize = indexAndNames_.size();
0182       for (unsigned int j = startInIndexAndNames + 1U; j < vSize && (indexAndNames_[j].startInProcessNames() != 0U);
0183            ++j) {
0184         ++numberOfMatches;
0185       }
0186     }
0187     return Matches(this, startInIndexAndNames, numberOfMatches);
0188   }
0189 
0190   ProductResolverIndexHelper::Matches ProductResolverIndexHelper::relatedIndexes(KindOfType kindOfType,
0191                                                                                  TypeID const& typeID) const {
0192     unsigned int startInIndexAndNames = std::numeric_limits<unsigned int>::max();
0193     unsigned int numberOfMatches = 0;
0194 
0195     // Look for the type and check to see if it found it
0196     unsigned iType = indexToType(kindOfType, typeID);
0197     if (iType != std::numeric_limits<unsigned int>::max()) {
0198       // Get the range of entries with a matching TypeID
0199       Range const& range = ranges_[iType];
0200 
0201       startInIndexAndNames = range.begin();
0202       numberOfMatches = range.end() - range.begin();
0203     }
0204     return Matches(this, startInIndexAndNames, numberOfMatches);
0205   }
0206 
0207   ProductResolverIndex ProductResolverIndexHelper::insert(TypeID const& typeID,
0208                                                           char const* moduleLabel,
0209                                                           char const* instance,
0210                                                           char const* process,
0211                                                           TypeID const& containedTypeID,
0212                                                           std::vector<TypeID>* baseTypesOfContainedType) {
0213     if (!items_) {
0214       throw Exception(errors::LogicError)
0215           << "ProductResolverIndexHelper::insert - Attempt to insert more elements after frozen.\n";
0216     }
0217 
0218     if (process == nullptr || *process == '\0') {
0219       throw Exception(errors::LogicError) << "ProductResolverIndexHelper::insert - Empty process.\n";
0220     }
0221 
0222     // Throw if this has already been inserted
0223     Item item(PRODUCT_TYPE, typeID, moduleLabel, instance, process, 0);
0224     std::set<Item>::iterator iter = items_->find(item);
0225     if (iter != items_->end()) {
0226       throw Exception(errors::LogicError)
0227           << "ProductResolverIndexHelper::insert - Attempt to insert duplicate entry.\n";
0228     }
0229 
0230     // Put in an entry for the product
0231     item.setIndex(nextIndexValue_);
0232     unsigned int savedProductIndex = nextIndexValue_;
0233     ++nextIndexValue_;
0234     items_->insert(item);
0235 
0236     // Put in an entry for the product with an empty process name
0237     // if it is not already there
0238     item.clearProcess();
0239     iter = items_->find(item);
0240     if (iter == items_->end()) {
0241       item.setIndex(nextIndexValue_);
0242       ++nextIndexValue_;
0243       items_->insert(item);
0244     }
0245 
0246     // Now put in entries for a contained class if this is a
0247     // recognized container.
0248     if (containedTypeID != TypeID(typeid(void)) && containedTypeID != TypeID()) {
0249       TypeWithDict containedType(containedTypeID.typeInfo());
0250 
0251       Item containedItem(ELEMENT_TYPE, containedTypeID, moduleLabel, instance, process, savedProductIndex);
0252       iter = items_->find(containedItem);
0253       if (iter != items_->end()) {
0254         containedItem.setIndex(ProductResolverIndexAmbiguous);
0255         items_->erase(iter);
0256       }
0257       items_->insert(containedItem);
0258 
0259       containedItem.clearProcess();
0260       iter = items_->find(containedItem);
0261       if (iter == items_->end()) {
0262         containedItem.setIndex(nextIndexValue_);
0263         ++nextIndexValue_;
0264         items_->insert(containedItem);
0265       }
0266 
0267       // Repeat this for all public base classes of the contained type
0268       if (baseTypesOfContainedType) {
0269         for (TypeID const& baseTypeID : *baseTypesOfContainedType) {
0270           Item baseItem(ELEMENT_TYPE, baseTypeID, moduleLabel, instance, process, savedProductIndex);
0271           iter = items_->find(baseItem);
0272           if (iter != items_->end()) {
0273             baseItem.setIndex(ProductResolverIndexAmbiguous);
0274             items_->erase(iter);
0275           }
0276           items_->insert(baseItem);
0277 
0278           baseItem.clearProcess();
0279           iter = items_->find(baseItem);
0280           if (iter == items_->end()) {
0281             baseItem.setIndex(nextIndexValue_);
0282             ++nextIndexValue_;
0283             items_->insert(baseItem);
0284           }
0285         }
0286       }
0287     }
0288     return savedProductIndex;
0289   }
0290 
0291   ProductResolverIndex ProductResolverIndexHelper::insert(TypeID const& typeID,
0292                                                           char const* moduleLabel,
0293                                                           char const* instance,
0294                                                           char const* process) {
0295     TypeID containedTypeID = productholderindexhelper::getContainedType(typeID);
0296     bool hasContainedType = (containedTypeID != TypeID(typeid(void)) && containedTypeID != TypeID());
0297     std::vector<TypeID> baseTypes;
0298     std::vector<TypeID>* baseTypesOfContainedType = &baseTypes;
0299     if (hasContainedType) {
0300       std::vector<std::string> missingDictionaries;
0301       public_base_classes(missingDictionaries, containedTypeID, baseTypes);
0302     }
0303     return insert(typeID, moduleLabel, instance, process, containedTypeID, baseTypesOfContainedType);
0304   }
0305 
0306   void ProductResolverIndexHelper::setFrozen() {
0307     if (!items_)
0308       return;
0309 
0310     // Make a first pass and count things so we
0311     // can reserve memory in the vectors. Also
0312     // fill processItems_ on the first pass.
0313     bool iFirstThisType = true;
0314     bool beginElementsWasSet = false;
0315     TypeID previousTypeID;
0316     KindOfType previousKindOfType = PRODUCT_TYPE;
0317     std::string previousModuleLabel;
0318     std::string previousInstance;
0319     unsigned int iCountTypes = 0;
0320     unsigned int iCountCharacters = 0;
0321     for (auto const& item : *items_) {
0322       if (iFirstThisType || item.typeID() != previousTypeID || item.kindOfType() != previousKindOfType) {
0323         ++iCountTypes;
0324         iFirstThisType = true;
0325 
0326         if (!beginElementsWasSet) {
0327           if (item.kindOfType() == ELEMENT_TYPE) {
0328             beginElementsWasSet = true;
0329           } else {
0330             beginElements_ = iCountTypes;
0331           }
0332         }
0333       }
0334 
0335       processItems_->insert(item.process());
0336 
0337       if (iFirstThisType || item.moduleLabel() != previousModuleLabel || item.instance() != previousInstance) {
0338         iCountCharacters += item.moduleLabel().size();
0339         iCountCharacters += item.instance().size();
0340         iCountCharacters += 2;
0341       }
0342 
0343       iFirstThisType = false;
0344       previousTypeID = item.typeID();
0345       previousKindOfType = item.kindOfType();
0346       previousModuleLabel = item.moduleLabel();
0347       previousInstance = item.instance();
0348     }
0349 
0350     // Size and fill the process name vector
0351     unsigned int processNamesSize = 0;
0352     for (auto const& processItem : *processItems_) {
0353       processNamesSize += processItem.size();
0354       ++processNamesSize;
0355     }
0356     processNames_.reserve(processNamesSize);
0357     for (auto const& processItem : *processItems_) {
0358       for (auto const& c : processItem) {
0359         processNames_.push_back(c);
0360       }
0361       processNames_.push_back('\0');
0362       lookupProcessNames_.push_back(processItem);
0363     }
0364 
0365     // Reserve memory in the vectors
0366     sortedTypeIDs_.reserve(iCountTypes);
0367     ranges_.reserve(iCountTypes);
0368     indexAndNames_.reserve(items_->size());
0369     bigNamesContainer_.reserve(iCountCharacters);
0370 
0371     // Second pass. Really fill the vectors this time.
0372     bool iFirstType = true;
0373     iFirstThisType = true;
0374     previousTypeID = TypeID();
0375     unsigned int iCount = 0;
0376     unsigned int iBeginning = 0;
0377     iCountCharacters = 0;
0378     unsigned int previousCharacterCount = 0;
0379     if (!items_->empty()) {
0380       for (auto const& item : *items_) {
0381         if (iFirstThisType || item.typeID() != previousTypeID || item.kindOfType() != previousKindOfType) {
0382           iFirstThisType = true;
0383           sortedTypeIDs_.push_back(item.typeID());
0384           if (iFirstType) {
0385             iFirstType = false;
0386           } else {
0387             ranges_.push_back(Range(iBeginning, iCount));
0388           }
0389           iBeginning = iCount;
0390         }
0391         ++iCount;
0392 
0393         if (iFirstThisType || item.moduleLabel() != previousModuleLabel || item.instance() != previousInstance) {
0394           unsigned int labelSize = item.moduleLabel().size();
0395           for (unsigned int j = 0; j < labelSize; ++j) {
0396             bigNamesContainer_.push_back(item.moduleLabel()[j]);
0397           }
0398           bigNamesContainer_.push_back('\0');
0399 
0400           unsigned int instanceSize = item.instance().size();
0401           for (unsigned int j = 0; j < instanceSize; ++j) {
0402             bigNamesContainer_.push_back(item.instance()[j]);
0403           }
0404           bigNamesContainer_.push_back('\0');
0405 
0406           previousCharacterCount = iCountCharacters;
0407 
0408           iCountCharacters += labelSize;
0409           iCountCharacters += instanceSize;
0410           iCountCharacters += 2;
0411         }
0412 
0413         unsigned int processStart = processIndex(item.process().c_str());
0414         if (processStart == std::numeric_limits<unsigned int>::max()) {
0415           throw Exception(errors::LogicError)
0416               << "ProductResolverIndexHelper::setFrozen - Process not found in processNames_.\n";
0417         }
0418         indexAndNames_.emplace_back(item.index(), previousCharacterCount, processStart);
0419 
0420         iFirstThisType = false;
0421         previousTypeID = item.typeID();
0422         previousKindOfType = item.kindOfType();
0423         previousModuleLabel = item.moduleLabel();
0424         previousInstance = item.instance();
0425       }
0426       ranges_.push_back(Range(iBeginning, iCount));
0427     }
0428 
0429     // Some sanity checks to protect against out of bounds vector accesses
0430     // These should only fail if there is a bug. If profiling ever shows
0431     // them to be expensive one might delete them.
0432     sanityCheck();
0433 
0434     // Cleanup, do not need the temporary containers anymore
0435     // propagate_const<T> has no reset() function
0436     items_ = nullptr;
0437     processItems_ = nullptr;
0438   }
0439 
0440   std::vector<std::string> const& ProductResolverIndexHelper::lookupProcessNames() const {
0441     if (items_) {
0442       throw Exception(errors::LogicError)
0443           << "ProductResolverIndexHelper::lookupProcessNames - Attempt to access names before frozen.\n";
0444     }
0445     return lookupProcessNames_;
0446   }
0447 
0448   unsigned int ProductResolverIndexHelper::indexToIndexAndNames(KindOfType kindOfType,
0449                                                                 TypeID const& typeID,
0450                                                                 char const* moduleLabel,
0451                                                                 char const* instance,
0452                                                                 char const* process) const {
0453     // Look for the type and check to see if it found it
0454     unsigned iType = indexToType(kindOfType, typeID);
0455     if (iType != std::numeric_limits<unsigned int>::max()) {
0456       unsigned startProcess = 0;
0457       if (process) {
0458         startProcess = processIndex(process);
0459         if (startProcess == std::numeric_limits<unsigned int>::max()) {
0460           return std::numeric_limits<unsigned int>::max();
0461         }
0462       }
0463 
0464       ProductResolverIndexHelper::Range const& range = ranges_[iType];
0465       unsigned int begin = range.begin();
0466       unsigned int end = range.end();
0467 
0468       while (begin < end) {
0469         unsigned int midpoint = begin + ((end - begin) / 2);
0470         char const* namePtr = &bigNamesContainer_[indexAndNames_[midpoint].startInBigNamesContainer()];
0471 
0472         // Compare the module label
0473         char const* label = moduleLabel;
0474         while (*namePtr && (*namePtr == *label)) {
0475           ++namePtr;
0476           ++label;
0477         }
0478         if (*namePtr == *label) {  // true only if both are at the '\0' at the end of the C string
0479           ++namePtr;               // move to the next C string
0480 
0481           // Compare the instance name
0482           char const* instanceName = instance;
0483           while (*namePtr && (*namePtr == *instanceName)) {
0484             ++namePtr;
0485             ++instanceName;
0486           }
0487           if (*namePtr == *instanceName) {
0488             // Compare the process name
0489             if (startProcess == indexAndNames_[midpoint].startInProcessNames()) {
0490               return midpoint;
0491             } else {
0492               if (indexAndNames_[midpoint].startInProcessNames() > startProcess) {
0493                 while (true) {
0494                   --midpoint;
0495                   if (indexAndNames_[midpoint].startInProcessNames() == startProcess) {
0496                     return midpoint;
0497                   }
0498                   if (indexAndNames_[midpoint].startInProcessNames() == 0)
0499                     break;
0500                 }
0501               } else {
0502                 while (true) {
0503                   ++midpoint;
0504                   if (midpoint == indexAndNames_.size())
0505                     break;
0506                   if (indexAndNames_[midpoint].startInProcessNames() == 0)
0507                     break;
0508                   if (indexAndNames_[midpoint].startInProcessNames() == startProcess) {
0509                     return midpoint;
0510                   }
0511                 }
0512               }
0513               break;
0514             }
0515           } else if (*namePtr < *instanceName) {
0516             if (begin == midpoint)
0517               break;
0518             begin = midpoint;
0519           } else {
0520             end = midpoint;
0521           }
0522         } else if (*namePtr < *label) {
0523           if (begin == midpoint)
0524             break;
0525           begin = midpoint;
0526         } else {
0527           end = midpoint;
0528         }
0529       }  // end while (begin < end)
0530     }
0531     return std::numeric_limits<unsigned int>::max();
0532   }
0533 
0534   unsigned int ProductResolverIndexHelper::indexToType(KindOfType kindOfType, TypeID const& typeID) const {
0535     unsigned int beginType = 0;
0536     unsigned int endType = beginElements_;
0537     if (kindOfType == ELEMENT_TYPE) {
0538       beginType = beginElements_;
0539       endType = sortedTypeIDs_.size();
0540     }
0541 
0542     while (beginType < endType) {
0543       unsigned int midpointType = beginType + ((endType - beginType) / 2);
0544       if (sortedTypeIDs_[midpointType] == typeID) {
0545         return midpointType;  // Found it
0546       } else if (sortedTypeIDs_[midpointType] < typeID) {
0547         if (beginType == midpointType)
0548           break;
0549         beginType = midpointType;
0550       } else {
0551         endType = midpointType;
0552       }
0553     }
0554     return std::numeric_limits<unsigned int>::max();  // Failed to find it
0555   }
0556 
0557   unsigned int ProductResolverIndexHelper::processIndex(char const* process) const {
0558     char const* ptr = &processNames_[0];
0559     char const* begin = ptr;
0560     while (true) {
0561       char const* p = process;
0562       char const* beginName = ptr;
0563       while (*ptr && (*ptr == *p)) {
0564         ++ptr;
0565         ++p;
0566       }
0567       if (*ptr == *p) {
0568         return beginName - begin;
0569       }
0570       while (*ptr) {
0571         ++ptr;
0572       }
0573       ++ptr;
0574       if (static_cast<unsigned>(ptr - begin) >= processNames_.size()) {
0575         return std::numeric_limits<unsigned int>::max();
0576       }
0577     }
0578     return 0;
0579   }
0580 
0581   ProductResolverIndexHelper::ModulesToIndiciesMap ProductResolverIndexHelper::indiciesForModulesInProcess(
0582       const std::string& iProcessName) const {
0583     ModulesToIndiciesMap result;
0584     for (unsigned int i = 0; i < beginElements_; ++i) {
0585       auto const& range = ranges_[i];
0586       for (unsigned int j = range.begin(); j < range.end(); ++j) {
0587         auto const& indexAndNames = indexAndNames_[j];
0588         if (0 == strcmp(&processNames_[indexAndNames.startInProcessNames()], iProcessName.c_str())) {
0589           //The first null terminated string is the module label
0590           auto pModLabel = &bigNamesContainer_[indexAndNames.startInBigNamesContainer()];
0591           auto l = strlen(pModLabel);
0592           auto pInstance = pModLabel + l + 1;
0593           result.emplace(pModLabel, std::make_tuple(&sortedTypeIDs_[i], pInstance, indexAndNames.index()));
0594         }
0595       }
0596     }
0597     return result;
0598   }
0599 
0600   void ProductResolverIndexHelper::sanityCheck() const {
0601     bool sanityChecksPass = true;
0602     if (sortedTypeIDs_.size() != ranges_.size())
0603       sanityChecksPass = false;
0604 
0605     unsigned int previousEnd = 0;
0606     for (auto const& range : ranges_) {
0607       if (range.begin() != previousEnd)
0608         sanityChecksPass = false;
0609       if (range.begin() >= range.end())
0610         sanityChecksPass = false;
0611       previousEnd = range.end();
0612     }
0613     if (previousEnd != indexAndNames_.size())
0614       sanityChecksPass = false;
0615 
0616     unsigned maxStart = 0;
0617     unsigned maxStartProcess = 0;
0618     for (auto const& indexAndName : indexAndNames_) {
0619       if (indexAndName.index() >= nextIndexValue_ && indexAndName.index() != ProductResolverIndexAmbiguous)
0620         sanityChecksPass = false;
0621 
0622       if (indexAndName.startInBigNamesContainer() >= bigNamesContainer_.size())
0623         sanityChecksPass = false;
0624       if (indexAndName.startInProcessNames() >= processNames_.size())
0625         sanityChecksPass = false;
0626 
0627       if (indexAndName.startInBigNamesContainer() > maxStart)
0628         maxStart = indexAndName.startInBigNamesContainer();
0629       if (indexAndName.startInProcessNames() > maxStartProcess)
0630         maxStartProcess = indexAndName.startInProcessNames();
0631     }
0632 
0633     if (!indexAndNames_.empty()) {
0634       if (bigNamesContainer_.back() != '\0')
0635         sanityChecksPass = false;
0636       if (processNames_.back() != '\0')
0637         sanityChecksPass = false;
0638       if (maxStart >= bigNamesContainer_.size())
0639         sanityChecksPass = false;
0640       unsigned int countZeroes = 0;
0641       for (unsigned j = maxStart; j < bigNamesContainer_.size(); ++j) {
0642         if (bigNamesContainer_[j] == '\0') {
0643           ++countZeroes;
0644         }
0645       }
0646       if (countZeroes != 2)
0647         sanityChecksPass = false;
0648       if (maxStartProcess >= processNames_.size())
0649         sanityChecksPass = false;
0650       countZeroes = 0;
0651       for (unsigned j = maxStartProcess; j < processNames_.size(); ++j) {
0652         if (processNames_[j] == '\0') {
0653           ++countZeroes;
0654         }
0655       }
0656       if (countZeroes != 1)
0657         sanityChecksPass = false;
0658     }
0659 
0660     if (!sanityChecksPass) {
0661       throw Exception(errors::LogicError) << "ProductResolverIndexHelper::setFrozen - Detected illegal state.\n";
0662     }
0663   }
0664 
0665   ProductResolverIndexHelper::Item::Item(KindOfType kindOfType,
0666                                          TypeID const& typeID,
0667                                          std::string const& moduleLabel,
0668                                          std::string const& instance,
0669                                          std::string const& process,
0670                                          ProductResolverIndex index)
0671       : kindOfType_(kindOfType),
0672         typeID_(typeID),
0673         moduleLabel_(moduleLabel),
0674         instance_(instance),
0675         process_(process),
0676         index_(index) {}
0677 
0678   bool ProductResolverIndexHelper::Item::operator<(Item const& right) const {
0679     if (kindOfType_ < right.kindOfType_)
0680       return true;
0681     if (kindOfType_ > right.kindOfType_)
0682       return false;
0683     if (typeID_ < right.typeID_)
0684       return true;
0685     if (typeID_ > right.typeID_)
0686       return false;
0687     if (moduleLabel_ < right.moduleLabel_)
0688       return true;
0689     if (moduleLabel_ > right.moduleLabel_)
0690       return false;
0691     if (instance_ < right.instance_)
0692       return true;
0693     if (instance_ > right.instance_)
0694       return false;
0695     return process_ < right.process_;
0696   }
0697 
0698   void ProductResolverIndexHelper::print(std::ostream& os) const {
0699     os << "\n******* Dump ProductResolverIndexHelper *************************\n";
0700 
0701     os << "\nnextIndexValue_ = " << nextIndexValue_ << "\n";
0702     os << "beginElements_ = " << beginElements_ << "\n";
0703 
0704     os << "\n******* sortedTypeIDs_ \n";
0705     for (auto const& i : sortedTypeIDs_) {
0706       os << i << "\n";
0707     }
0708     os << "******* ranges_ \n";
0709     for (auto const& i : ranges_) {
0710       os << i.begin() << " " << i.end() << "\n";
0711     }
0712     os << "******* indexAndNames_ \n";
0713     for (auto const& i : indexAndNames_) {
0714       os << i.index() << " " << i.startInBigNamesContainer() << " ";
0715       char const* ptr = &bigNamesContainer_[i.startInBigNamesContainer()];
0716       while (*ptr) {
0717         os << *ptr;
0718         ++ptr;
0719       }
0720       ++ptr;
0721       os << " ";
0722       while (*ptr) {
0723         os << *ptr;
0724         ++ptr;
0725       }
0726       os << " " << i.startInProcessNames() << " ";
0727       ptr = &processNames_[i.startInProcessNames()];
0728       while (*ptr) {
0729         os << *ptr;
0730         ++ptr;
0731       }
0732       os << "\n";
0733     }
0734     os << "******* bigNamesContainer_ \n";
0735     for (auto i : bigNamesContainer_) {
0736       if (i == '\0')
0737         os << '\\' << '0';
0738       else
0739         os << i;
0740     }
0741     if (!bigNamesContainer_.empty())
0742       os << "\n";
0743     os << "******* processNames_ \n";
0744     for (auto i : processNames_) {
0745       if (i == '\0')
0746         os << '\\' << '0';
0747       else
0748         os << i;
0749     }
0750     if (!processNames_.empty())
0751       os << "\n";
0752     if (items_) {
0753       os << "******* items_ \n";
0754       for (auto const& item : *items_) {
0755         std::cout << item.kindOfType() << " " << item.moduleLabel() << " " << item.instance() << " " << item.process()
0756                   << " " << item.index() << " " << item.typeID() << "\n";
0757       }
0758     }
0759     if (processItems_) {
0760       os << "******* processItems_ \n";
0761       for (auto const& item : *processItems_) {
0762         os << item << "\n";
0763       }
0764     }
0765     os << "sortedTypeIDs_.size() = " << sortedTypeIDs_.size() << "\n";
0766     os << "indexAndNames_.size() = " << indexAndNames_.size() << "\n";
0767     os << "bigNamesContainer_.size() = " << bigNamesContainer_.size() << "\n";
0768     os << "processNames_.size() = " << processNames_.size() << "\n";
0769     os << "\n";
0770   }
0771 }  // namespace edm