CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ProductHolderIndexHelper.cc
Go to the documentation of this file.
1 
6 
7 #include <iostream>
8 #include <limits>
9 
10 namespace edm {
11 
13  nextIndexValue_(0),
14  beginElements_(0),
15  items_(new std::set<ProductHolderIndexHelper::Item>),
16  processItems_(new std::set<std::string>) {
17  }
18 
21  TypeID const& typeID,
22  char const* moduleLabel,
23  char const* instance,
24  char const* process) const {
25 
26  unsigned int iToIndexAndNames = indexToIndexAndNames(kindOfType,
27  typeID,
28  moduleLabel,
29  instance,
30  process);
31 
32  if (iToIndexAndNames == std::numeric_limits<unsigned int>::max()) {
34  }
35  return indexAndNames_[iToIndexAndNames].index();
36  }
37 
39  unsigned int startInIndexAndNames,
40  unsigned int numberOfMatches) :
41  productHolderIndexHelper_(productHolderIndexHelper),
42  startInIndexAndNames_(startInIndexAndNames),
43  numberOfMatches_(numberOfMatches) {
44  if (numberOfMatches != 0 && startInIndexAndNames_ + numberOfMatches_ > productHolderIndexHelper_->indexAndNames_.size()) {
46  << "ProductHolderIndexHelper::Matches::Matches - Arguments exceed vector bounds.\n";
47  }
48  }
49 
52  if (i >= numberOfMatches_) {
54  << "ProductHolderIndexHelper::Matches::index - Argument is out of range.\n";
55  }
56  return productHolderIndexHelper_->indexAndNames_[startInIndexAndNames_ + i].index();
57  }
58 
59  bool
61  if (i >= numberOfMatches_) {
63  << "ProductHolderIndexHelper::Matches::isFullyResolved - Argument is out of range.\n";
64  }
65  return (productHolderIndexHelper_->indexAndNames_[startInIndexAndNames_ + i].startInProcessNames() != 0U);
66  }
67 
70  TypeID const& typeID,
71  char const* moduleLabel,
72  char const* instance) const {
73 
74  unsigned int startInIndexAndNames = indexToIndexAndNames(kindOfType,
75  typeID,
76  moduleLabel,
77  instance,
78  0);
79  unsigned int numberOfMatches = 1;
80 
81  if (startInIndexAndNames == std::numeric_limits<unsigned int>::max()) {
82  numberOfMatches = 0;
83  } else {
84  auto vSize = indexAndNames_.size();
85  for (unsigned int j = startInIndexAndNames + 1U;
86  j < vSize && (indexAndNames_[j].startInProcessNames() != 0U);
87  ++j) {
88  ++numberOfMatches;
89  }
90  }
91  return Matches(this, startInIndexAndNames, numberOfMatches);
92  }
93 
96  TypeID const& typeID) const {
97 
98  unsigned int startInIndexAndNames = std::numeric_limits<unsigned int>::max();
99  unsigned int numberOfMatches = 0;
100 
101  // Look for the type and check to see if it found it
102  unsigned iType = indexToType(kindOfType, typeID);
104 
105  // Get the range of entries with a matching TypeID
106  Range const& range = ranges_[iType];
107 
108  startInIndexAndNames = range.begin();
109  numberOfMatches = range.end() - range.begin();
110  }
111  return Matches(this, startInIndexAndNames, numberOfMatches);
112  }
113 
116  char const* moduleLabel,
117  char const* instance,
118  char const* process) {
119  if (!items_) {
121  << "ProductHolderIndexHelper::insert - Attempt to insert more elements after frozen.\n";
122  }
123 
124  if (process == 0 || *process == '\0') {
126  << "ProductHolderIndexHelper::insert - Empty process.\n";
127  }
128 
129  TypeID typeID(typeWithDict.typeInfo());
130 
131  // Throw if this has already been inserted
132  Item item(PRODUCT_TYPE, typeID, moduleLabel, instance, process, 0);
133  std::set<Item>::iterator iter = items_->find(item);
134  if (iter != items_->end()) {
136  << "ProductHolderIndexHelper::insert - Attempt to insert duplicate entry.\n";
137  }
138 
139  // Put in an entry for the product
140  item.setIndex(nextIndexValue_);
141  unsigned int savedProductIndex = nextIndexValue_;
142  ++nextIndexValue_;
143  items_->insert(item);
144 
145  // Put in an entry for the product with an empty process name
146  // if it is not already there
147  item.clearProcess();
148  iter = items_->find(item);
149  if (iter == items_->end()) {
150  item.setIndex(nextIndexValue_);
151  ++nextIndexValue_;
152  items_->insert(item);
153  }
154 
155  // Now put in entries for a contained class if this is a
156  // recognized container.
157  TypeWithDict containedType;
158  if((is_RefVector(typeWithDict, containedType) ||
159  is_PtrVector(typeWithDict, containedType) ||
160  is_RefToBaseVector(typeWithDict, containedType) ||
161  value_type_of(typeWithDict, containedType))
162  && bool(containedType)) {
163 
164  TypeID containedTypeID(containedType.typeInfo());
165  Item containedItem(ELEMENT_TYPE, containedTypeID, moduleLabel, instance, process, savedProductIndex);
166  iter = items_->find(containedItem);
167  if (iter != items_->end()) {
168  containedItem.setIndex(ProductHolderIndexAmbiguous);
169  items_->erase(iter);
170  }
171  items_->insert(containedItem);
172 
173  containedItem.clearProcess();
174  iter = items_->find(containedItem);
175  if (iter == items_->end()) {
176  containedItem.setIndex(nextIndexValue_);
177  ++nextIndexValue_;
178  items_->insert(containedItem);
179  }
180 
181  // Repeat this for all public base classes of the contained type
182  std::vector<TypeWithDict> baseTypes;
183  public_base_classes(containedType, baseTypes);
184 
185  for(TypeWithDict const& baseType : baseTypes) {
186 
187  TypeID baseTypeID(baseType.typeInfo());
188  Item baseItem(ELEMENT_TYPE, baseTypeID, moduleLabel, instance, process, savedProductIndex);
189  iter = items_->find(baseItem);
190  if (iter != items_->end()) {
191  baseItem.setIndex(ProductHolderIndexAmbiguous);
192  items_->erase(iter);
193  }
194  items_->insert(baseItem);
195 
196  baseItem.clearProcess();
197  iter = items_->find(baseItem);
198  if (iter == items_->end()) {
199  baseItem.setIndex(nextIndexValue_);
200  ++nextIndexValue_;
201  items_->insert(baseItem);
202  }
203  }
204  }
205  return savedProductIndex;
206  }
207 
209 
210  if (!items_) return;
211 
212  // Make a first pass and count things so we
213  // can reserve memory in the vectors. Also
214  // fill processItems_ on the first pass.
215  bool iFirstThisType = true;
216  bool beginElementsWasSet = false;
217  TypeID previousTypeID;
218  KindOfType previousKindOfType = PRODUCT_TYPE;
219  std::string previousModuleLabel;
220  std::string previousInstance;
221  unsigned int iCountTypes = 0;
222  unsigned int iCountCharacters = 0;
223  for (auto const& item : *items_) {
224 
225  if (iFirstThisType || item.typeID() != previousTypeID || item.kindOfType() != previousKindOfType) {
226  ++iCountTypes;
227  iFirstThisType = true;
228 
229  if (!beginElementsWasSet) {
230  if (item.kindOfType() == ELEMENT_TYPE) {
231  beginElementsWasSet = true;
232  } else {
233  beginElements_ = iCountTypes;
234  }
235  }
236  }
237 
238  processItems_->insert(item.process());
239 
240  if (iFirstThisType ||
241  item.moduleLabel() != previousModuleLabel ||
242  item.instance() != previousInstance) {
243  iCountCharacters += item.moduleLabel().size();
244  iCountCharacters += item.instance().size();
245  iCountCharacters += 2;
246  }
247 
248  iFirstThisType = false;
249  previousTypeID = item.typeID();
250  previousKindOfType = item.kindOfType();
251  previousModuleLabel = item.moduleLabel();
252  previousInstance = item.instance();
253  }
254 
255  // Size and fill the process name vector
256  unsigned int processNamesSize = 0;
257  for (auto const& processItem : *processItems_) {
258  processNamesSize += processItem.size();
259  ++processNamesSize;
260  }
261  processNames_.reserve(processNamesSize);
262  for (auto const& processItem : *processItems_) {
263  for (auto const& c : processItem) {
264  processNames_.push_back(c);
265  }
266  processNames_.push_back('\0');
267  lookupProcessNames_.push_back(processItem);
268  }
269 
270  // Reserve memory in the vectors
271  sortedTypeIDs_.reserve(iCountTypes);
272  ranges_.reserve(iCountTypes);
273  indexAndNames_.reserve(items_->size());
274  bigNamesContainer_.reserve(iCountCharacters);
275 
276  // Second pass. Really fill the vectors this time.
277  bool iFirstType = true;
278  iFirstThisType = true;
279  previousTypeID = TypeID();
280  unsigned int iCount = 0;
281  unsigned int iBeginning = 0;
282  iCountCharacters = 0;
283  unsigned int previousCharacterCount = 0;
284  if (!items_->empty()) {
285  for (auto const& item : *items_) {
286 
287  if (iFirstThisType || item.typeID() != previousTypeID || item.kindOfType() != previousKindOfType) {
288  iFirstThisType = true;
289  sortedTypeIDs_.push_back(item.typeID());
290  if (iFirstType) {
291  iFirstType = false;
292  } else {
293  ranges_.push_back(Range(iBeginning, iCount));
294  }
295  iBeginning = iCount;
296  }
297  ++iCount;
298 
299  if (iFirstThisType ||
300  item.moduleLabel() != previousModuleLabel ||
301  item.instance() != previousInstance) {
302 
303  unsigned int labelSize = item.moduleLabel().size();
304  for (unsigned int j = 0; j < labelSize; ++j) {
305  bigNamesContainer_.push_back(item.moduleLabel()[j]);
306  }
307  bigNamesContainer_.push_back('\0');
308 
309  unsigned int instanceSize = item.instance().size();
310  for (unsigned int j = 0; j < instanceSize; ++j) {
311  bigNamesContainer_.push_back(item.instance()[j]);
312  }
313  bigNamesContainer_.push_back('\0');
314 
315  previousCharacterCount = iCountCharacters;
316 
317  iCountCharacters += labelSize;
318  iCountCharacters += instanceSize;
319  iCountCharacters += 2;
320  }
321 
322  unsigned int processStart = processIndex(item.process().c_str());
323  if (processStart == std::numeric_limits<unsigned int>::max()) {
325  << "ProductHolderIndexHelper::setFrozen - Process not found in processNames_.\n";
326  }
327  indexAndNames_.emplace_back(item.index(), previousCharacterCount, processStart);
328 
329  iFirstThisType = false;
330  previousTypeID = item.typeID();
331  previousKindOfType = item.kindOfType();
332  previousModuleLabel = item.moduleLabel();
333  previousInstance = item.instance();
334  }
335  ranges_.push_back(Range(iBeginning, iCount));
336  }
337 
338  // Some sanity checks to protect against out of bounds vector accesses
339  // These should only fail if there is a bug. If profiling ever shows
340  // them to be expensive one might delete them.
341  sanityCheck();
342 
343  // Cleanup, do not need the temporary containers anymore
344  items_.reset();
345  processItems_.reset();
346  }
347 
348  std::vector<std::string> const& ProductHolderIndexHelper::lookupProcessNames() const {
349  if (items_) {
351  << "ProductHolderIndexHelper::lookupProcessNames - Attempt to access names before frozen.\n";
352  }
353  return lookupProcessNames_;
354  }
355 
356  unsigned int
358  TypeID const& typeID,
359  char const* moduleLabel,
360  char const* instance,
361  char const* process) const {
362 
363  // Look for the type and check to see if it found it
364  unsigned iType = indexToType(kindOfType, typeID);
366 
367  unsigned startProcess = 0;
368  if (process) {
369  startProcess = processIndex(process);
370  if (startProcess == std::numeric_limits<unsigned int>::max()) {
372  }
373  }
374 
375  ProductHolderIndexHelper::Range const& range = ranges_[iType];
376  unsigned int begin = range.begin();
377  unsigned int end = range.end();
378 
379  while (begin < end) {
380 
381  unsigned int midpoint = begin + ((end - begin) / 2);
382  char const* namePtr = &bigNamesContainer_[indexAndNames_[midpoint].startInBigNamesContainer()];
383 
384  // Compare the module label
385  char const* label = moduleLabel;
386  while (*namePtr && (*namePtr == *label)) {
387  ++namePtr; ++label;
388  }
389  if (*namePtr == *label) { // true only if both are at the '\0' at the end of the C string
390  ++namePtr; // move to the next C string
391 
392  // Compare the instance name
393  char const* instanceName = instance;
394  while (*namePtr && (*namePtr == *instanceName)) {
395  ++namePtr; ++instanceName;
396  }
397  if (*namePtr == *instanceName) {
398 
399  // Compare the process name
400  if (startProcess == indexAndNames_[midpoint].startInProcessNames()) {
401  return midpoint;
402  } else {
403  if (indexAndNames_[midpoint].startInProcessNames() > startProcess) {
404  while (true) {
405  --midpoint;
406  if (indexAndNames_[midpoint].startInProcessNames() == startProcess) {
407  return midpoint;
408  }
409  if (indexAndNames_[midpoint].startInProcessNames() == 0) break;
410  }
411  } else {
412  while (true) {
413  ++midpoint;
414  if (midpoint == indexAndNames_.size()) break;
415  if (indexAndNames_[midpoint].startInProcessNames() == 0) break;
416  if (indexAndNames_[midpoint].startInProcessNames() == startProcess) {
417  return midpoint;
418  }
419  }
420  }
421  break;
422  }
423  } else if (*namePtr < *instanceName) {
424  if (begin == midpoint) break;
425  begin = midpoint;
426  } else {
427  end = midpoint;
428  }
429  } else if (*namePtr < *label) {
430  if (begin == midpoint) break;
431  begin = midpoint;
432  } else {
433  end = midpoint;
434  }
435  } // end while (begin < end)
436  }
438  }
439 
440  unsigned int
442  TypeID const& typeID) const {
443 
444  unsigned int beginType = 0;
445  unsigned int endType = beginElements_;
446  if (kindOfType == ELEMENT_TYPE) {
447  beginType = beginElements_;
448  endType = sortedTypeIDs_.size();
449  }
450 
451  while (beginType < endType) {
452  unsigned int midpointType = beginType + ((endType - beginType) / 2);
453  if (sortedTypeIDs_[midpointType] == typeID) {
454  return midpointType; // Found it
455  } else if (sortedTypeIDs_[midpointType] < typeID) {
456  if (beginType == midpointType) break;
457  beginType = midpointType;
458  } else {
459  endType = midpointType;
460  }
461  }
462  return std::numeric_limits<unsigned int>::max(); // Failed to find it
463  }
464 
465  unsigned int ProductHolderIndexHelper::processIndex(char const* process) const {
466 
467  char const* ptr = &processNames_[0];
468  char const* begin = ptr;
469  while (true) {
470  char const* p = process;
471  char const* beginName = ptr;
472  while (*ptr && (*ptr == *p)) {
473  ++ptr; ++p;
474  }
475  if (*ptr == *p) {
476  return beginName - begin;
477  }
478  while (*ptr) {
479  ++ptr;
480  }
481  ++ptr;
482  if (static_cast<unsigned>(ptr - begin) >= processNames_.size()) {
484  }
485  }
486  return 0;
487  }
488 
490  bool sanityChecksPass = true;
491  if (sortedTypeIDs_.size() != ranges_.size()) sanityChecksPass = false;
492 
493  unsigned int previousEnd = 0;
494  for ( auto const& range : ranges_) {
495  if (range.begin() != previousEnd) sanityChecksPass = false;
496  if (range.begin() >= range.end()) sanityChecksPass = false;
497  previousEnd = range.end();
498  }
499  if (previousEnd != indexAndNames_.size()) sanityChecksPass = false;
500 
501 
502  unsigned maxStart = 0;
503  unsigned maxStartProcess = 0;
504  for (auto const& indexAndName : indexAndNames_) {
505  if (indexAndName.index() >= nextIndexValue_ && indexAndName.index() != ProductHolderIndexAmbiguous) sanityChecksPass = false;
506 
507  if (indexAndName.startInBigNamesContainer() >= bigNamesContainer_.size()) sanityChecksPass = false;
508  if (indexAndName.startInProcessNames() >= processNames_.size()) sanityChecksPass = false;
509 
510  if (indexAndName.startInBigNamesContainer() > maxStart) maxStart = indexAndName.startInBigNamesContainer();
511  if (indexAndName.startInProcessNames() > maxStartProcess) maxStartProcess = indexAndName.startInProcessNames();
512  }
513 
514  if (!indexAndNames_.empty()) {
515  if (bigNamesContainer_.back() != '\0') sanityChecksPass = false;
516  if (processNames_.back() != '\0') sanityChecksPass = false;
517  if (maxStart >= bigNamesContainer_.size()) sanityChecksPass = false;
518  unsigned int countZeroes = 0;
519  for (unsigned j = maxStart; j < bigNamesContainer_.size(); ++j) {
520  if (bigNamesContainer_[j] == '\0') {
521  ++countZeroes;
522  }
523  }
524  if (countZeroes != 2) sanityChecksPass = false;
525  if (maxStartProcess >= processNames_.size()) sanityChecksPass = false;
526  countZeroes = 0;
527  for (unsigned j = maxStartProcess; j < processNames_.size(); ++j) {
528  if (processNames_[j] == '\0') {
529  ++countZeroes;
530  }
531  }
532  if (countZeroes != 1) sanityChecksPass = false;
533  }
534 
535  if (!sanityChecksPass) {
537  << "ProductHolderIndexHelper::setFrozen - Detected illegal state.\n";
538  }
539  }
540 
542  TypeID const& typeID,
543  std::string const& moduleLabel,
544  std::string const& instance,
545  std::string const& process,
547  kindOfType_(kindOfType),
548  typeID_(typeID),
549  moduleLabel_(moduleLabel),
550  instance_(instance),
551  process_(process),
552  index_(index) {
553  }
554 
555  bool
557  if (kindOfType_ < right.kindOfType_) return true;
558  if (kindOfType_ > right.kindOfType_) return false;
559  if (typeID_ < right.typeID_) return true;
560  if (typeID_ > right.typeID_) return false;
561  if (moduleLabel_ < right.moduleLabel_) return true;
562  if (moduleLabel_ > right.moduleLabel_) return false;
563  if (instance_ < right.instance_) return true;
564  if (instance_ > right.instance_) return false;
565  return process_ < right.process_;
566  }
567 
568  void ProductHolderIndexHelper::print(std::ostream& os) const {
569 
570  os << "\n******* Dump ProductHolderIndexHelper *************************\n";
571 
572  os << "\nnextIndexValue_ = " << nextIndexValue_ << "\n";
573  os << "beginElements_ = " << beginElements_ << "\n";
574 
575  os << "\n******* sortedTypeIDs_ \n";
576  for (auto const& i : sortedTypeIDs_) {
577  os << i << "\n";
578  }
579  os << "******* ranges_ \n";
580  for (auto const& i : ranges_) {
581  os << i.begin() << " " << i.end() << "\n";
582  }
583  os << "******* indexAndNames_ \n";
584  for (auto const& i : indexAndNames_) {
585  os << i.index() << " " << i.startInBigNamesContainer() << " ";
586  char const* ptr = &bigNamesContainer_[i.startInBigNamesContainer()];
587  while (*ptr) {
588  os << *ptr;
589  ++ptr;
590  }
591  ++ptr;
592  os << " ";
593  while (*ptr) {
594  os << *ptr;
595  ++ptr;
596  }
597  os << " " << i.startInProcessNames() << " ";
598  ptr = &processNames_[i.startInProcessNames()];
599  while (*ptr) {
600  os << *ptr;
601  ++ptr;
602  }
603  os << "\n";
604  }
605  os << "******* bigNamesContainer_ \n";
606  for (auto i : bigNamesContainer_) {
607  if (i == '\0') os << '\\' << '0';
608  else os << i;
609  }
610  if (!bigNamesContainer_.empty()) os << "\n";
611  os << "******* processNames_ \n";
612  for (auto i : processNames_) {
613  if (i == '\0') os << '\\' << '0';
614  else os << i;
615  }
616  if (!processNames_.empty()) os << "\n";
617  if (items_) {
618  os << "******* items_ \n";
619  for (auto const& item : *items_) {
620  std:: cout << item.kindOfType() << " " << item.moduleLabel() << " " << item.instance() << " " << item.process() << " " << item.index() << " " << item.typeID() << "\n";
621  }
622  }
623  if (processItems_) {
624  os << "******* processItems_ \n";
625  for (auto const& item : *processItems_) {
626  os << item << "\n";
627  }
628  }
629  os << "sortedTypeIDs_.size() = " << sortedTypeIDs_.size() << "\n";
630  os << "indexAndNames_.size() = " << indexAndNames_.size() << "\n";
631  os << "bigNamesContainer_.size() = " << bigNamesContainer_.size() << "\n";
632  os << "processNames_.size() = " << processNames_.size() << "\n";
633  os << "\n";
634  }
635 }
Matches relatedIndexes(KindOfType kindOfType, TypeID const &typeID, char const *moduleLabel, char const *instance) const
bool is_RefToBaseVector(TypeWithDict const &possible_ref_vector, TypeWithDict &value_type)
int i
Definition: DBlmapReader.cc:9
std::unique_ptr< std::set< std::string > > processItems_
static PFTauRenderPlugin instance
ProductHolderIndexHelper const * productHolderIndexHelper_
ProductHolderIndex index(KindOfType kindOfType, TypeID const &typeID, char const *moduleLabel, char const *instance, char const *process=0) const
std::vector< IndexAndNames > indexAndNames_
ProductHolderIndex insert(TypeWithDict const &typeWithDict, char const *moduleLabel, char const *instance, char const *process)
void print(std::ostream &os) const
unsigned int ProductHolderIndex
std::vector< std::string > lookupProcessNames_
void public_base_classes(TypeWithDict const &type, std::vector< TypeWithDict > &baseTypes)
bool is_RefVector(TypeWithDict const &possible_ref_vector, TypeWithDict &value_type)
Matches(ProductHolderIndexHelper const *productHolderIndexHelper, unsigned int startInIndexAndNames, unsigned int numberOfMatches)
std::unique_ptr< std::set< Item > > items_
bool operator<(Item const &right) const
int j
Definition: DBlmapReader.cc:9
unsigned int indexToType(KindOfType kindOfType, TypeID const &typeID) const
ProductHolderIndex index(unsigned int i) const
std::type_info const & typeInfo() const
unsigned int processIndex(char const *process) const
#define end
Definition: vmac.h:37
PixelRecoRange< float > Range
#define begin
Definition: vmac.h:30
std::vector< std::string > const & lookupProcessNames() const
tuple cout
Definition: gather_cfg.py:121
Item(KindOfType kindOfType, TypeID const &typeID, std::string const &moduleLabel, std::string const &instance, std::string const &process, ProductHolderIndex index)
tuple process
Definition: LaserDQM_cfg.py:3
moduleLabel_(iConfig.getParameter< string >("@module_label"))
bool is_PtrVector(TypeWithDict const &possible_ref_vector, TypeWithDict &value_type)
unsigned int indexToIndexAndNames(KindOfType kindOfType, TypeID const &typeID, char const *moduleLabel, char const *instance, char const *process) const
bool value_type_of(TypeWithDict const &t, TypeWithDict &found_type)