ATLAS Offline Software
Loading...
Searching...
No Matches
IdDictGroup Class Reference

#include <IdDictGroup.h>

Collaboration diagram for IdDictGroup:

Classes

struct  IdDictRegionTreeNode
 Tree structure for fast unpacking. More...

Public Member Functions

 IdDictGroup ()
 IdDictGroup (const std::string &name)
 ~IdDictGroup ()
 IdDictGroup (const IdDictGroup &)=delete
IdDictGroupoperator= (const IdDictGroup &)=delete
const std::string & name () const
size_t n_regions () const
const IdDictRegionregion (size_t index) const
const std::vector< IdDictRegion * > & regions ()
 Non-const access to regions.
MultiRange build_multirange () const
 Get MultiRange for this group.
void add_dictentry (std::unique_ptr< IdDictDictEntry > entry)
void resolve_references (IdDictMgr &idd, IdDictDictionary &dictionary, size_t &index)
void generate_implementation (const IdDictMgr &idd, IdDictDictionary &dictionary, const std::string &tag="")
void reset_implementation ()
bool verify () const
void sort ()
 Sort:
void clear ()
int unpack (const Identifier &id, const ExpandedIdentifier &prefix, size_t index2, ExpandedIdentifier &unpackedId, std::vector< const IdDictFieldImplementation * > *impls=nullptr) const
 Unpack the value_type id to an expanded Identifier, considering the provided prefix (result will include the prefix) and up to index2 - (index1 is assumed to be 0, i.e.
void build_region_tree ()
 Take the list of regions and build a tree structure for fast unpacking.
void dump () const
 Dump regions and tree for this group.
void dump_regions () const
 Dump the list of regions for this group.
void dump_tree () const
 Dump the tree structure built from the regions for fast unpacking.

Private Member Functions

void add_tree_field (const IdDictRegion &re, unsigned ifield, unsigned inode)
 Recursively add new nodes to the tree structure.

Private Attributes

std::string m_name
std::vector< std::unique_ptr< IdDictDictEntry > > m_entries
std::vector< IdDictRegion * > m_regions
bool m_generated_implementation
std::vector< IdDictRegionTreeNodem_region_tree
 The list of region nodes.

Detailed Description

Definition at line 25 of file IdDictGroup.h.

Constructor & Destructor Documentation

◆ IdDictGroup() [1/3]

IdDictGroup::IdDictGroup ( )

Definition at line 22 of file IdDictGroup.cxx.

23 :
25}
bool m_generated_implementation

◆ IdDictGroup() [2/3]

IdDictGroup::IdDictGroup ( const std::string & name)

Definition at line 27 of file IdDictGroup.cxx.

28 :
29 m_name(name),
31}
std::string m_name
const std::string & name() const

◆ ~IdDictGroup()

IdDictGroup::~IdDictGroup ( )

Definition at line 33 of file IdDictGroup.cxx.

33 {
34}

◆ IdDictGroup() [3/3]

IdDictGroup::IdDictGroup ( const IdDictGroup & )
delete

Member Function Documentation

◆ add_dictentry()

void IdDictGroup::add_dictentry ( std::unique_ptr< IdDictDictEntry > entry)

Definition at line 62 of file IdDictGroup.cxx.

62 {
63 m_entries.push_back(std::move(region));
64}
std::vector< std::unique_ptr< IdDictDictEntry > > m_entries
const IdDictRegion & region(size_t index) const

◆ add_tree_field()

void IdDictGroup::add_tree_field ( const IdDictRegion & re,
unsigned ifield,
unsigned inode )
private

Recursively add new nodes to the tree structure.

Parameters
reThe region we're processing.
ifieldThe index of the next field to add.
inodeThe index of the node to which to add.

Definition at line 326 of file IdDictGroup.cxx.

329{
330 using element_type = IdentifierField::element_type;
331 using element_vector = IdentifierField::element_vector;
332 using size_type = IdentifierField::size_type;
333 using index_vector = IdentifierField::index_vector;
334
335 // Helper to retrieve the indices that may actually be used by a field.
336 // n is the node we're looking for. We use the ored_field referenced there
337 // to know what can actually be stored in the field.
338 // impl gives the field that we're trying to match.
339 // So we return the indices for the ored_field corresponding
340 // to valid values for impl.
341 auto get_field_indices = [] (const IdDictRegionTreeNode& n,
342 const IdDictFieldImplementation& impl)
343 {
344 index_vector indices;
345 const Range::field& ored_field = n.m_impl.ored_field();
346 if (impl.field().isEnumerated()) {
347 const element_vector& vals = impl.field().get_values();
348 indices.reserve (vals.size());
349 for (element_type v : vals) {
350 indices.push_back (ored_field.get_value_index (v));
351 }
352 }
353 else if (impl.field().isBounded()) {
354 auto [minval, maxval] = impl.field().get_minmax();
355 size_type minidx = ored_field.get_value_index (minval);
356 size_type maxidx = ored_field.get_value_index (maxval);
357 indices.resize (maxidx - minidx + 1);
358 std::iota (indices.begin(), indices.end(), minidx);
359 }
360 else {
361 std::abort();
362 }
363 return indices;
364 };
365
366 // This will be the field we're matching.
367 const IdDictFieldImplementation& prev_impl = re.implementation(ifield-1);
368
369 {
370 // Get the children for the current node.
372 auto& children = std::get<0> (n.m_children);
373
374 // If we're looking at the last field, fill in the node pointersj
375 // with END; then we're done.
376 if (ifield == re.n_implementation()) {
377 index_vector indices = get_field_indices (n, prev_impl);
378 for (size_t idx : indices) {
380 }
381 return;
382 }
383
384 // Verify consistency of the field with what's stored in the node.
385 if (prev_impl.bits() != n.m_impl.bits() ||
386 prev_impl.bits_offset() != n.m_impl.bits_offset() ||
387 prev_impl.ored_field() != n.m_impl.ored_field())
388 {
389 dump();
390 std::abort();
391 }
392
393 // If this implementation has a field that is not equivalent with what
394 // we saved in the node, then save it in m_other_impls.
395 if (n.m_impl.field() != prev_impl.field()) {
396 if (!n.m_other_impls) {
397 n.m_other_impls = std::make_unique<std::vector<const IdDictFieldImplementation*> > (1, &prev_impl);
398 }
399 else {
400 if (std::ranges::find_if (*n.m_other_impls,
401 [&](const IdDictFieldImplementation* a)
402 { return a->field() == prev_impl.field(); })
403 == n.m_other_impls->end())
404 {
405 n.m_other_impls->push_back (&prev_impl);
406 }
407 }
408 }
409 }
410
411 // Indices we want to store.
412 index_vector indices = get_field_indices (m_region_tree[inode], prev_impl);
413 const IdDictFieldImplementation& impl = re.implementation(ifield);
414
415 // Children for the node.
416 auto children = [&]() -> std::vector<unsigned>& { return std::get<0> (m_region_tree[inode].m_children); };
417
418 unsigned new_node = 0;
419 std::vector<unsigned> nodes_seen;
420
421 // Loop over indices that we want to add.
422 for (size_t idx : indices) {
423
424 // If we've already recorded this index as END, fail.
425 unsigned next_node = children().at (idx);
426 if (next_node == IdDictRegionTreeNode::END) {
427 dump();
428 std::abort();
429 }
430
431 if (next_node != 0) {
432 // There is an existing node. Process it recursively; but we only
433 // need to this once for each unique node.
434 if (std::ranges::find (nodes_seen, next_node) == nodes_seen.end()) {
435 add_tree_field (re, ifield+1, next_node);
436 nodes_seen.push_back (next_node);
437 }
438 }
439 else {
440 // No node had been recorded for this index.
441 if (new_node != 0) {
442 // We've already made a new node. So just record it.
443 children().at(idx) = new_node;
444 }
445 else {
446 // Need to make a new node.
447 new_node = m_region_tree.size();
448 if (new_node == IdDictRegionTreeNode::END) {
449 std::abort();
450 }
451 // Careful --- this will invalidate references to nodes.
452 m_region_tree.emplace_back (impl);
453 children().at(idx) = new_node;
454 add_tree_field (re, ifield+1, new_node);
455 }
456 }
457 }
458}
const boost::regex re(r_e)
static Double_t a
const Range::field & ored_field() const
const Range::field & field() const
std::vector< IdDictRegionTreeNode > m_region_tree
The list of region nodes.
void add_tree_field(const IdDictRegion &re, unsigned ifield, unsigned inode)
Recursively add new nodes to the tree structure.
void dump() const
Dump regions and tree for this group.
ExpandedIdentifier::size_type size_type
std::vector< element_type > element_vector
size_type get_value_index(element_type value) const
ExpandedIdentifier::element_type element_type
std::vector< size_type > index_vector
std::pair< long int, long int > indices
Tree structure for fast unpacking.
static constexpr unsigned END
Special value used to indicate that we've reached the end.

◆ build_multirange()

MultiRange IdDictGroup::build_multirange ( ) const

Get MultiRange for this group.

Definition at line 42 of file IdDictGroup.cxx.

42 {
43 MultiRange result;
44
45 for (const IdDictRegion* region : m_regions) {
46
47 // skip regions created from parents
48 if ("dummy" == region->name()) continue;
49
50 // skip empty regions - may arise from alternate_regions
51 // where a tag selects an empty region
52 if (region->is_empty()) continue;
53
54 Range r = region->build_range();
55 result.add(std::move(r));
56 }
57
58 return(result);
59}
std::vector< IdDictRegion * > m_regions
int r
Definition globals.cxx:22

◆ build_region_tree()

void IdDictGroup::build_region_tree ( )

Take the list of regions and build a tree structure for fast unpacking.

Definition at line 465 of file IdDictGroup.cxx.

466{
467 // Loop through regions.
468 [[maybe_unused]] unsigned iregion = 0; // Region index, really only for debugging.
469 for (const IdDictRegion* re : m_regions) {
470 // Skip dummy/empty regions.
471 if (re->fieldSize() == 0 || re->name() == "dummy") {
472 ++iregion;
473 continue;
474 }
475
476 // Add an initial node if we haven't done so already.
477 if (m_region_tree.empty()) {
478 m_region_tree.emplace_back (re->implementation(0));
479 }
480
481 // Add nodes for the current region, starting at field 1.
482 add_tree_field (*re, 1, 0);
483
484 ++iregion;
485 }
486
487 // Compress child vectors if possible.
489 n.optimize();
490 }
491}

◆ clear()

void IdDictGroup::clear ( )

Definition at line 168 of file IdDictGroup.cxx.

168 {
169 m_entries.clear();
170 m_regions.clear();
171 m_region_tree.clear();
172}

◆ dump()

void IdDictGroup::dump ( ) const

Dump regions and tree for this group.

Definition at line 497 of file IdDictGroup.cxx.

498{
499 std::cout << "===== IdDictGroup " << m_name << "\n";
500 dump_regions();
501 dump_tree();
502}
void dump_tree() const
Dump the tree structure built from the regions for fast unpacking.
void dump_regions() const
Dump the list of regions for this group.

◆ dump_regions()

void IdDictGroup::dump_regions ( ) const

Dump the list of regions for this group.

Definition at line 508 of file IdDictGroup.cxx.

509{
510 std::cout << "Regions:\n";
511 for (unsigned iregion = 0; const IdDictRegion* re : m_regions) {
512 std::cout << " " << iregion++ << " " << re->name() << " " << re->group_name() << " " << re->tag() << "\n";
513 size_t nimpl = re->n_implementation();
514 bool first = true;
515 for (size_t i = 0; i < nimpl; ++i) {
516 const IdDictFieldImplementation& impl = re->implementation(i);
517 std::cout << (first ? " " : "; ") << impl.field() << " " << impl.ored_field() << " " << impl.bits() << "/" << impl.bits_offset();
518 first = false;
519 }
520 std::cout << "\n";
521 }
522}
bool first
Definition DeMoScan.py:534

◆ dump_tree()

void IdDictGroup::dump_tree ( ) const

Dump the tree structure built from the regions for fast unpacking.

Definition at line 528 of file IdDictGroup.cxx.

529{
530 size_t sz = 0;
531 for (const auto& n : m_region_tree) {
532 if (n.m_children.index() == 0) {
533 sz += std::get<0>(n.m_children).size();
534 }
535 }
536 std::cout << "Region Tree totsize " << sz << "\n";
537 for (unsigned inode = 0; const auto& n : m_region_tree) {
538 std::cout << " " << inode++ << " " << n.m_impl.field()
539 << " " << n.m_impl.ored_field() << " -- ";
540
541 if (n.m_children.index() == 0) {
542 const auto& children = std::get<0> (n.m_children);
543 unsigned istart = 0;
544 unsigned ichild = 0;
545 bool first = true;
546 for (size_t i = 0; uint64_t c : children) {
547 if (c != ichild) {
548 if (ichild != 0) {
549 if (!first) std::cout << " ";
550 first = false;
551 if (istart != i-1) {
552 std::cout << istart << "-";
553 }
554 std::cout << i-1 << ":";
555 if (ichild == IdDictRegionTreeNode::END) {
556 std::cout << "END";
557 }
558 else {
559 std::cout << ichild;
560 }
561 }
562 ichild = c;
563 istart = i;
564 }
565 ++i;
566 }
567 if (ichild != 0) {
568 if (!first) std::cout << " ";
569 if (istart != children.size()-1) {
570 std::cout << istart << "-";
571 }
572 std::cout << children.size()-1 << ":";
573 if (ichild == IdDictRegionTreeNode::END) {
574 std::cout << "END";
575 }
576 else {
577 std::cout << ichild;
578 }
579 }
580 }
581 else {
582 const auto& children = std::get<1> (n.m_children);
583 if (children.first == 1) {
584 std::cout << "0:";
585 }
586 else {
587 std::cout << "0-" << children.first-1 << ":";
588 }
589 if (children.second == IdDictRegionTreeNode::END) {
590 std::cout << "END";
591 }
592 else {
593 std::cout << children.second;
594 }
595 }
596 if (n.m_other_impls) {
597 std::cout << " [";
598 bool first = true;
599 for (const IdDictFieldImplementation* ii : *n.m_other_impls) {
600 if (!first)
601 std::cout << "; ";
602 else
603 first = false;
604 std::cout << ii->field();
605 }
606 std::cout << "]";
607 }
608 std::cout << "\n";
609 }
610 std::cout.flush();
611}
static Double_t sz

◆ generate_implementation()

void IdDictGroup::generate_implementation ( const IdDictMgr & idd,
IdDictDictionary & dictionary,
const std::string & tag = "" )

Definition at line 79 of file IdDictGroup.cxx.

81 {
82 if (Debugger::debug()) {
83 std::cout << "IdDictGroup::generate_implementation>" << std::endl;
84 }
85
87 // Loop over entries and fill regions vec with selected region
88 // (AltRegions have a selection)
89 for (auto& ent : m_entries) {
90 ent->generate_implementation(idd, dictionary, tag);
91 // Get region and save in m_regions
92 IdDictRegion* region = dynamic_cast<IdDictRegion*> (ent.get());
93 if (region) {
94 m_regions.push_back(region);
95 } else {
96 IdDictAltRegions* altregions = dynamic_cast<IdDictAltRegions*> (ent.get());
97 if (altregions) {
98 m_regions.push_back(altregions->selected_region());
99 }
100 }
101 }
102
103 if (m_regions.size() != m_entries.size()) {
104 std::cout << "IdDictGroup::generate_implementation - mismatch of sizes: regions/entries "
105 << m_regions.size() << " " << m_entries.size()
106 << std::endl;
107 }
108
110 }
111}
static bool debug()
Definition Debugger.h:18
IdDictRegion * selected_region()
Currently selected region.

◆ n_regions()

size_t IdDictGroup::n_regions ( ) const
inline

Definition at line 231 of file IdDictGroup.h.

232{
233 return m_regions.size();
234}

◆ name()

const std::string & IdDictGroup::name ( ) const
inline

Definition at line 225 of file IdDictGroup.h.

225 {
226 return m_name;
227}

◆ operator=()

IdDictGroup & IdDictGroup::operator= ( const IdDictGroup & )
delete

◆ region()

const IdDictRegion & IdDictGroup::region ( size_t index) const
inline

Definition at line 238 of file IdDictGroup.h.

239{
240 return *m_regions.at(index);
241}

◆ regions()

const std::vector< IdDictRegion * > & IdDictGroup::regions ( )

Non-const access to regions.

Definition at line 37 of file IdDictGroup.cxx.

37 {
38 return(m_regions);
39}

◆ reset_implementation()

void IdDictGroup::reset_implementation ( )

Definition at line 114 of file IdDictGroup.cxx.

114 {
116 m_regions.clear();
117 for (auto& ent : m_entries) {
118 ent->reset_implementation();
119 }
121 }
122}

◆ resolve_references()

void IdDictGroup::resolve_references ( IdDictMgr & idd,
IdDictDictionary & dictionary,
size_t & index )

Definition at line 67 of file IdDictGroup.cxx.

69 {
70 for (auto& ent : m_entries) {
71 ent->set_index(index);
72 index++;
73
74 ent->resolve_references(idd, dictionary);
75 }
76}
str index
Definition DeMoScan.py:362

◆ sort()

void IdDictGroup::sort ( )

Sort:

Loop over regions and sort according to their first identifier

Definition at line 139 of file IdDictGroup.cxx.

139 {
140 std::map< ExpandedIdentifier, std::unique_ptr<IdDictDictEntry> > regions;
141
142 assert (m_regions.size() == m_entries.size());
143 for (size_t ientry = 0; IdDictRegion* region : m_regions) {
144 Range range = region->build_range();
145 RangeIterator itr(range);
146 auto first = itr.begin();
147 auto last = itr.end();
148 if (first != last) {
149 regions[*first] = std::move(m_entries[ientry++]);
150 } else {
151 std::cout << "IdDictDictionary::sort - WARNING empty region cannot sort "
152 << std::endl;
153 }
154 }
155 if (regions.size() != m_regions.size()) {
156 std::cout << "IdDictGroup::sort - WARNING region map size is NOT the same as the vector size. Map size "
157 << regions.size() << " vector size " << m_regions.size()
158 << std::endl;
159 }
160 // Reorder the regions
161 m_entries.resize (regions.size());
162 for (size_t vecIt = 0; auto& p : regions) {
163 m_entries[vecIt++] = std::move(p.second);
164 }
165}
const std::vector< IdDictRegion * > & regions()
Non-const access to regions.

◆ unpack()

int IdDictGroup::unpack ( const Identifier & id,
const ExpandedIdentifier & prefix,
size_t index2,
ExpandedIdentifier & unpackedId,
std::vector< const IdDictFieldImplementation * > * impls = nullptr ) const

Unpack the value_type id to an expanded Identifier, considering the provided prefix (result will include the prefix) and up to index2 - (index1 is assumed to be 0, i.e.

part of prefix). If impls is provided, then fill it with pointers to the implementations for each unpacked field.

Returns 0 on success, nonzero on error.

Definition at line 217 of file IdDictGroup.cxx.

222{
223 using element_type = ExpandedIdentifier::element_type;
224 using size_type = IdentifierField::size_type;
225
226 // Give up if the tree representation hasn't been built.
227 if (m_region_tree.empty()) std::abort();
228
229 // Clear output.
230 unpackedId.clear();
231 if (impls) {
232 impls->clear();
233 impls->reserve (12);
234 }
235
236 // Start at the first node, and assume success.
237 unsigned inode = 0;
238 int ret = 0;
239
240 // Loop over fields.
241 for (size_t index = 0; index <= index2; ++index) {
242
243 // Fetch the node.
244 const IdDictRegionTreeNode& n = m_region_tree.at(inode);
245
246 // Find the index+value for this field. If we're looking at a prefix,
247 // get it from there; otherwise, unpack from the input identifier.
248 element_type val;
249 size_type validx;
250 if (index < prefix.fields()) {
251 val = prefix[index];
252 validx = n.m_impl.ored_field().get_value_index (val);
253 }
254 else {
255 validx = n.m_impl.unpackToIndex (id);
256 try {
257 val = n.m_impl.ored_field().get_value_at (validx);
258 } catch (const std::out_of_range&) {
259 ret = 1;
260 break;
261 }
262 }
263
264 // Find the next node.
265 if (n.m_children.index() == 0) {
266 // Children stored as a vector.
267 const auto& children = std::get<0> (n.m_children);
268 if (validx < children.size()) {
269 inode = children[validx];
270 }
271 else {
272 inode = 0;
273 }
274 }
275 else {
276 // Children stored as a size,node-number field.
277 const auto& children = std::get<1> (n.m_children);
278 if (validx < children.first) {
279 inode = children.second;
280 }
281 else {
282 inode = 0;
283 }
284 }
285
286 // Give up if no regions match the identifier.
287 if (!inode) {
288 break;
289 }
290
291 // Record this field in the output.
292 unpackedId.add (val);
293
294 // Also return the implementation, if requested.
295 // But we need to be sure that we return an implementation that actually
296 // matches the field value.
297 if (impls) {
298 if (n.m_impl.field().match (val)) {
299 impls->push_back (&n.m_impl);
300 }
301 else if (n.m_other_impls) {
302 for (const IdDictFieldImplementation* ii : *n.m_other_impls) {
303 if (ii->field().match (val)) {
304 impls->push_back (ii);
305 break;
306 }
307 }
308 }
309 if (unpackedId.fields() != impls->size()) std::abort();
310 }
311
312 // Stop if we've reached the end of the identifier.
313 if (inode == IdDictRegionTreeNode::END) break;
314 }
315
316 return ret;
317}
size_type fields() const
void add(element_type value)
Append a value into a new field.
void clear()
Erase all fields.
bool match(element_type value) const
The basic match operation Given a value, test to see if it satisfies the constraints for this field.

◆ verify()

bool IdDictGroup::verify ( ) const

Definition at line 125 of file IdDictGroup.cxx.

125 {
126 // Should check that all regions have the same number of levels,
127 // which is part of the definition of a group
128 return(true);
129}

Member Data Documentation

◆ m_entries

std::vector<std::unique_ptr<IdDictDictEntry> > IdDictGroup::m_entries
private

Definition at line 123 of file IdDictGroup.h.

◆ m_generated_implementation

bool IdDictGroup::m_generated_implementation
private

Definition at line 125 of file IdDictGroup.h.

◆ m_name

std::string IdDictGroup::m_name
private

Definition at line 122 of file IdDictGroup.h.

◆ m_region_tree

std::vector<IdDictRegionTreeNode> IdDictGroup::m_region_tree
private

The list of region nodes.

Definition at line 220 of file IdDictGroup.h.

◆ m_regions

std::vector<IdDictRegion*> IdDictGroup::m_regions
private

Definition at line 124 of file IdDictGroup.h.


The documentation for this class was generated from the following files: