SST 16.0.0
Structural Simulation Toolkit
objectMap.h
1// Copyright 2009-2026 NTESS. Under the terms
2// of Contract DE-NA0003525 with NTESS, the U.S.
3// Government retains certain rights in this software.
4//
5// Copyright (c) 2009-2026, NTESS
6// All rights reserved.
7//
8// This file is part of the SST software package. For license
9// information, see the LICENSE file in the top level directory of the
10// distribution.
11
12#ifndef SST_CORE_SERIALIZATION_OBJECTMAP_H
13#define SST_CORE_SERIALIZATION_OBJECTMAP_H
14
15#include "sst/core/from_string.h"
16#include "sst/core/warnmacros.h"
17
18#include <cassert>
19#include <cctype>
20#include <cerrno>
21#include <cstddef>
22#include <cstdint>
23#include <cstdio>
24#include <cstdlib>
25#include <cstring>
26#include <exception>
27#include <functional>
28#include <iostream>
29#include <iterator>
30#include <map>
31#include <memory>
32#include <ostream>
33#include <sstream>
34#include <stdexcept>
35#include <string>
36#include <type_traits>
37#include <typeinfo>
38#include <utility>
39#include <vector>
40
41// #define _OBJMAP_DEBUG_
42
43namespace SST::Core::Serialization {
44
45// Comparison of two keys: If both keys are integers, use numeric comparison, else lexicographic
47{
48 bool operator()(const std::string& a, const std::string& b) const
49 {
50 // If the first characters of a and b are digits, attempt to convert them to unsigned long long
51 // *ea and *eb are `\0` after strtoull() if there are no invalid characters for integers left in the string
52 // errno is nonzero if a value is out of range; we fall back on string comparison then
53 if ( isdigit(a[0]) && isdigit(b[0]) ) {
54 errno = 0;
55 char* ea;
56 unsigned long long na = strtoull(a.c_str(), &ea, 10);
57 if ( *ea == '\0' && errno == 0 ) {
58 char* eb;
59 unsigned long long nb = strtoull(b.c_str(), &eb, 10);
60 if ( *eb == '\0' && errno == 0 ) return na < nb;
61 }
62 }
63 return std::less<>()(a, b);
64 }
65};
66
67class ObjectMap;
68class TraceBuffer;
69class ObjectBuffer;
70
71using ObjectMultimap = std::multimap<std::string, ObjectMap*, ObjectMultimapCmp>;
72
73/**
74 Metadata object that each ObjectMap has a pointer to in order to
75 track the hierarchy information while traversing the data
76 structures. This is used because a given object can be pointed to
77 by multiple other objects, so we need to track the "path" through
78 which we got to the object so we can traverse back up the object
79 hierarchy.
80*/
82{
83 /**
84 Parent object that contained this object and through which it
85 was selected.
86 */
88
89 /**
90 Name of this object in the context of the currently set parent
91 */
92 std::string name;
93
94 /**
95 Constructor for intializing data memebers
96 */
97 ObjectMapMetaData(ObjectMap* parent, const std::string& name) :
99 name(name)
100 {}
101
102 ObjectMapMetaData(const ObjectMapMetaData&) = delete;
103 ObjectMapMetaData& operator=(const ObjectMapMetaData&) = delete;
104};
105
106/**
107 Base class for interacting with data from ObjectMap. This includes
108 the ability to keep a history of values and compare the value
109 against specified criteria (i.e., value >= 15, value == 6,
110 etc). Because this class is type agnostic, interactions will be
111 through strings, just as with the ObjectMapClass.
112
113 The implementations of the virtual functions needs to be done in
114 templated child clases so that the type of the data is known.
115 */
116class ObjectMapComparison
117{
118public:
119 enum class Op : std::uint8_t { LT, LTE, GT, GTE, EQ, NEQ, CHANGED, INVALID };
120
121 static Op getOperationFromString(const std::string& op)
122 {
123 if ( op == "<" ) return Op::LT;
124 if ( op == "<=" ) return Op::LTE;
125 if ( op == ">" ) return Op::GT;
126 if ( op == ">=" ) return Op::GTE;
127 if ( op == "==" ) return Op::EQ;
128 if ( op == "!=" ) return Op::NEQ;
129 if ( op == "changed" ) return Op::CHANGED; // Could also use <>
130 return Op::INVALID;
131 }
132
133 static std::string getStringFromOp(Op op)
134 {
135 switch ( op ) {
136 case Op::LT:
137 return "<";
138 case Op::LTE:
139 return "<+";
140 case Op::GT:
141 return ">";
142 case Op::GTE:
143 return ">=";
144 case Op::EQ:
145 return "==";
146 case Op::NEQ:
147 return "!=";
148 case Op::CHANGED:
149 return "CHANGED";
150 case Op::INVALID:
151 return "INVALID";
152 default:
153 return "Invalid Op";
154 }
155 }
156
157 ObjectMapComparison() = default;
158
159 explicit ObjectMapComparison(const std::string& name) :
160 name_(name)
161 {}
162
163 ObjectMapComparison(const std::string& name, ObjectMap* obj) :
164 name_(name),
165 obj_(obj)
166 {}
167
168 virtual ~ObjectMapComparison() = default;
169 virtual bool compare() = 0;
170 virtual std::string getCurrentValue() const = 0;
171 virtual void print(std::ostream& stream) const = 0;
172 virtual void* getVar() const = 0;
173 const std::string& getName() const { return name_; }
174
175protected:
176 std::string name_ = "";
177 ObjectMap* obj_ = nullptr;
178};
179
180/**
181 Base class for objects created by the serializer mapping mode used
182 to map the variables for objects. This allows access to read and
183 write the mapped variables. ObjectMaps for fundamental types are
184 templated because they need the type information embedded in the
185 code so they can read and print the values.
186 */
188{
189protected:
190 /**
191 Metadata object for walking the object hierarchy. When this
192 object is selected by a parent object, a metadata object will
193 be added. The metadata contains a pointer to the parent and
194 the name of this object in the context of the parent. When the
195 object selects its parent, then this field is set to nullptr.
196 If this object is selected and the metadata is not a nullptr,
197 then we have hit a loop in the data structure.
198
199 Under normal circumstances, the metadata allows you to get the
200 full path of the object according to how you walked the
201 hierarchy, and allows you to return to the parent object. If a
202 loop is detected on select, then the full path of the object
203 will return to the highest level path and the metadata from
204 that path to the current path will be erased.
205 */
207
208 /**
209 Indicates whether or not the variable is read-only
210 */
211 bool read_only_ = false;
212
213 /**
214 Function implemented by derived classes to implement set(). No
215 need to check for read-only, that is done in set().
216
217 @param value Value to set the object to expressed as a string
218 */
219 virtual void set_impl(const std::string& UNUSED(value)) {}
220
221 /**
222 Function that will get called when this object is selected
223 */
224 virtual void activate_callback() {}
225
226 /**
227 Function that will get called when this object is deactivated
228 (i.e selectParent() is called)
229 */
230 virtual void deactivate_callback() {}
231
232private:
233 /**
234 Reference counter so the object knows when to delete itself.
235 ObjectMaps should not be deleted directly, rather the
236 decRefCount() function should be called when the object is no
237 longer needed and the object will delete itself if refCount_
238 reaches 0.
239 */
240 size_t refCount_ = 1;
241
242public:
243 /**
244 Default constructor primarily used for the "top" object in the hierarchy
245 */
246 ObjectMap() = default;
247
248 /**
249 Check to see if this object is read-only
250
251 @return true if ObjectMap is read-only, false otherwise
252 */
253 bool isReadOnly() const { return read_only_; }
254
255 /**
256 Set the read-only state of the object. NOTE: If the ObjectMap
257 is created as read-only, setting the state back to false could
258 lead to unexpected results. Setting the state to false should
259 only be done by the same object that set it to true.
260
261 @param state Read-only state to set this ObjectMap to. Defaults to true.
262 */
263 void setReadOnly(bool state = true) { read_only_ = state; }
264
265 /**
266 Check if value string is valid for this type
267
268 @param value Value to set the object to expressed as a string
269 */
270 virtual bool checkValue(const std::string& UNUSED(value)) const { return false; }
271
272 /**
273 Get the name of the variable represented by this ObjectMap. If
274 this ObjectMap has no metadata registered (i.e. it was not
275 selected by another ObjectMap), then an empty string will be
276 returned, since it has no name.
277
278 @return Name of variable
279 */
280 std::string getName() const { return mdata_ ? mdata_->name : ""; }
281
282 /**
283 Get the full hierarchical name of the variable represented by
284 this ObjectMap, based on the path taken to get to this
285 object. If this ObjectMap has no metadata registered (i.e. it
286 was not selected by another ObjectMap), then an empty string
287 will be returned, since it has no name.
288
289 @return Full hierarchical name of variable
290 */
291 std::string getFullName() const;
292
293 /**
294 Get the type of the variable represented by the ObjectMap
295
296 @return Type of variable
297 */
298 virtual std::string getType() const = 0;
299
300 /**
301 Get the address of the variable represented by the ObjectMap
302
303 @return Address of variable
304 */
305 virtual void* getAddr() const = 0;
306
307 /**
308 Get the list of child variables contained in this ObjectMap
309
310 @return Reference to map containing ObjectMaps for this
311 ObjectMap's child variables. Fundamental types will return the
312 same empty map.
313 */
314 virtual const ObjectMultimap& getVariables() const
315 {
316 /**
317 Static empty variable map for use by versions that don't have
318 variables (i.e. are fundamentals or classes treated as
319 fundamentals. This is needed because getVariables() returns a
320 reference to the map.
321 */
322 static ObjectMultimap emptyVars;
323 return emptyVars;
324 }
325
326 /**
327 Increment the reference counter for this ObjectMap. When
328 keeping a pointer to the ObjectMap, incRefCount() should be
329 called to indicate usage. When done, call decRefCount() to
330 indicate it is no longer needed.
331 */
332 void incRefCount() { ++refCount_; }
333
334 /**
335 Decrement the reference counter for this ObjectMap. If this
336 reference count reaches zero, the object will delete itself.
337 NOTE: delete should not be called directly on this object and
338 should only be done automatically using decRefCount().
339 */
341 {
342 if ( !--refCount_ ) delete this;
343 }
344
345 /**
346 Get the current reference count
347
348 @return current value of reference counter for the object
349 */
350 size_t getRefCount() const { return refCount_; }
351
352 /**
353 Get a watch point for this object. If it is not a valid object
354 for a watch point, nullptr will be returned.
355 */
357 const std::string& UNUSED(name), ObjectMapComparison::Op UNUSED(op), const std::string& UNUSED(value)) const
358 {
359 return nullptr;
360 }
361
362 virtual ObjectMapComparison* getComparisonVar(const std::string& UNUSED(name), ObjectMapComparison::Op UNUSED(op),
363 const std::string& UNUSED(name2), ObjectMap* UNUSED(var2)) const
364 {
365 printf("In virtual ObjectMapComparison\n");
366 return nullptr;
367 }
368
369 virtual ObjectBuffer* getObjectBuffer(const std::string& UNUSED(name), size_t UNUSED(sz)) { return nullptr; }
370
371 /************ Functions for walking the Object Hierarchy ************/
372
373 /**
374 Get the parent for this ObjectMap
375
376 @return Parent for this ObjectMap. If this is the top of the
377 hierarchy, it will return nullptr
378 */
380
381 /**
382 Get the ObjectMap for the specified variable.
383 Important!!! This function return 'this' pointer and not a nullptr!!!
384 TODO: prefer this return nullptr as bugs have occurred with incorrect use
385
386 @param name Name of variable to select
387 @param confirm Prompt user to resolve duplicate match of name. Select first found if false.
388
389 @return ObjectMap for specified variable, if it exists, this
390 otherwise
391 */
392 ObjectMap* selectVariable(std::string name, bool& loop_detected, bool confirm = false);
393
394 /**
395 Adds a variable to this ObjectMap. NOTE: calls to this
396 function will be ignored if isFundamental() returns true.
397
398 @param name Name of the object in the context of the parent class
399
400 @param obj ObjectMap to add as a variable
401
402 */
403 virtual void addVariable(const std::string& UNUSED(name), ObjectMap* UNUSED(obj)) {}
404
405 /**
406 Removes a variable from this ObjectMap. NOTE: calls to this
407 function will be ignored if isFundamental() returns true.
408
409 @param name Name of the object in the context of the parent class
410 */
411
412 virtual void removeVariable(const std::string& UNUSED(name)) {}
413
414 /************ Functions for getting/setting Object's Value *************/
415
416 /**
417 Get the value of the variable as a string. NOTE: this function
418 is only valid for ObjectMaps that represent fundamental types
419 or classes treated as fundamental types (i.e. isFundamental()
420 returns true).
421
422 @return Value of the represented variable as a string
423 */
424 virtual std::string get() const { return ""; }
425
426 /**
427 Sets the value of the variable represented by the ObjectMap to
428 the specified value, which is represented as a string. The
429 templated child classes for fundamentals will know how to
430 convert the string to a value of the approproprite type. NOTE:
431 this function is only valid for ObjectMaps that represent
432 fundamental types or classes treated as fundamental types
433 (i.e. isFundamental() returns true).
434
435 @param value Value to set the object to, represented as a string
436
437 */
438 void set(const std::string& value)
439 {
440 if ( !read_only_ ) set_impl(value);
441 }
442
443 /**
444 Gets the value of the specified variable as a string. NOTE:
445 this function is only valid for ObjectMaps that represent
446 non-fundamental types or classes not treated as fundamental
447 types.
448
449 @param var Name of variable
450
451 @return Value of the specified variable, represented as a
452 string
453 */
454 virtual std::string get(const std::string& var);
455
456 /**
457 Sets the value of the specified variable to the specified
458 value, which is represented as a string. The templated child
459 classes for fundamentals will know how to convert the string to
460 a value of the approproprite type. NOTE: this function is only
461 valid for ObjectMaps that represent non-fundamental types or
462 classes not treated as fundamental types (i.e. they must have
463 children).
464
465 @param var Name of variable
466
467 @param value Value to set var to represented as a string
468
469 @param[out] found Set to true if var is found, set to false otherwise
470
471 @param[out] read_only Set to true if var is read-only, set to false otherwise
472
473 */
474 virtual void set(const std::string& var, const std::string& value, bool& found, bool& read_only);
475
476 /**
477 Check to see if this ObjectMap represents a fundamental or a
478 class treated as a fundamental.
479
480 @return true if this ObjectMap represents a fundamental or
481 class treated as a fundamental, false otherwise
482 */
483 virtual bool isFundamental() const { return false; }
484
485 /**
486 Check to see if this ObjectMap represents a container
487
488 @return true if this ObjectMap represents a container, false
489 otherwise
490 */
491 virtual bool isContainer() const { return false; }
492
493 /**
494 Destructor. NOTE: delete should not be called directly on
495 ObjectMaps, rather decRefCount() should be called when the
496 object is no longer needed.
497 */
498 virtual ~ObjectMap() = default;
499
500 /**
501 Disallow copying and assignment
502 */
503
504 ObjectMap(const ObjectMap&) = delete;
505 ObjectMap& operator=(const ObjectMap&) = delete;
506
507 /**
508 Static function to demangle type names returned from typeid(T).name()
509
510 @param name typename returned from typeid(T).name()
511
512 @return demangled name
513 */
514 static std::string demangle_name(const char* name);
515
516 /**
517 Create a string that lists information for the specified
518 variable. This will list all child variables, including the
519 values for any children that are fundamentals, up to the
520 specified recursion depth.
521
522 @param name Name of variable to list
523
524 @param[out] found Set to true if variable is found, set to false otherwise
525
526 @param recurse Number of levels to recurse (default is 0)
527
528 @return String representing this object and any children
529 included based on the value of recurse
530 */
531 virtual std::string listVariable(std::string name, bool& found, int recurse = 0);
532
533 /**
534 Create a string that lists information for the current object.
535 This will list all child variables, including the values for
536 any children that are fundamentals, up to the specified
537 recursion depth.
538
539 @param recurse Number of levels to recurse (default is 0)
540
541 @return String representing this object and any children
542 included based on the value of recurse
543 */
544 virtual std::string list(int recurse = 0);
545
546 /**
547 Find a variable in this object map
548
549 @param name Name of variable to find
550 @param confirm Prompt user to resolve duplicate match of name. Select first found if false.
551
552 @return ObjectMap representing the requested variable if it is
553 found, nullptr otherwise
554 */
555 ObjectMap* findVariable(const std::string& name, bool confirm = false) const;
556
557 /**
558 Refresh the ObjectMap, reconstructing children
559 */
560 virtual void refresh() {}
561
562private:
563 /**
564 Called to activate this ObjectMap. This will create the
565 metadata object and call activate_callback().
566
567 @param parent ObjectMap parent of this ObjectMap
568
569 @param name Name of this ObjectMap in the context of the parent
570 */
571 void activate(ObjectMap* parent, const std::string& name)
572 {
573 mdata_ = new ObjectMapMetaData(parent, name);
575 }
576
577 /**
578 Deactivate this object. This will remove and delete the
579 metadata and call deactivate_callback().
580 */
581 void deactivate()
582 {
583 delete mdata_;
584 mdata_ = nullptr;
586 }
587
588 /**
589 Function called by list to recurse the object hierarchy
590
591 @param name Name of current ObjectMap
592
593 @param level Current level of recursion
594
595 @param recurse Number of levels deep to recurse
596 */
597 std::string listRecursive(const std::string& name, int level, int recurse);
598}; // class ObjectMap
599
600/**
601 Dump an ObjectMap structure in a formatted way to a stream
602**/
603std::ostream& dumpObjectMap(std::ostream& os, const ObjectMap& obj, size_t indent = 0);
604
605inline std::ostream&
606operator<<(std::ostream& os, const ObjectMap& obj)
607{
608 return dumpObjectMap(os, obj);
609}
610
611/**
612 ObjectMap object for non-fundamental, non-container types. This
613 class allows for child variables.
614 */
616{
617protected:
618 /**
619 Map that child ObjectMaps are stored in
620 */
621 ObjectMultimap variables_;
622
623 /**
624 Default constructor
625 */
627
628public:
629 /**
630 Destructor. Should not be called directly (i.e. do not call
631 delete on the object). Call decRefCount() when object is no
632 longer needed. This will also call decRefCount() on all its
633 children.
634 */
636 {
637 for ( const auto& [name, child] : variables_ )
638 if ( child != nullptr ) child->decRefCount();
639 }
640
641 /**
642 Disallow copying and assignment
643 */
644
646 ObjectMapWithChildren& operator=(const ObjectMapWithChildren&) = delete;
647
648 /**
649 Adds a variable to this ObjectMap
650
651 @param name Name of the object in the context of this ObjectMap
652
653 @param obj ObjectMap to add as a variable
654 */
655 void addVariable(const std::string& name, ObjectMap* obj) final override { variables_.emplace(name, obj); }
656
657 /**
658 Removes a variable from this ObjectMap
659
660 @param name Name of the object in the context of this ObjectMap
661 */
662 void removeVariable(const std::string& name) final override { variables_.erase(name); }
663
664 /**
665 Get the list of child variables contained in this ObjectMap
666
667 @return Reference to map containing ObjectMaps for this ObjectMap's
668 child variables. pair.first is the name of the variable in the
669 context of this object. pair.second is a pointer to the ObjectMap.
670 */
671 const ObjectMultimap& getVariables() const final override { return variables_; }
672
673
674 /**
675 Refresh the children
676 */
677 void refresh() override
678 {
679 for ( const auto& [name, child] : variables_ )
680 if ( child != nullptr ) child->refresh();
681 }
682
683}; // class ObjectMapWithChildren
684
685/**
686 ObjectMap object to create a level of hierarchy that doesn't
687 represent a specific object. This can be used to create views of
688 data that don't align specifically with the underlying data
689 structures.
690 */
692{
693public:
694 /**
695 Default constructor
696 */
698
699 /**
700 Destructor. Should not be called directly (i.e. do not call
701 delete on the object). Call decRefCount() when object is no
702 longer needed. This will also call decRefCount() on all its
703 children.
704 */
705 ~ObjectMapHierarchyOnly() override = default;
706
707 /**
708 Returns empty string since there is no underlying object being
709 represented
710
711 @return empty string
712 */
713 std::string getType() const override { return ""; }
714
715 /**
716 Returns nullptr since there is no underlying object being
717 represented
718
719 @return nullptr
720 */
721 void* getAddr() const override { return nullptr; }
722}; // class ObjectMapHierarchyOnly
723
724/**
725 ObjectMap object for non-fundamental, non-container types. This
726 class allows for child variables.
727 */
729{
730protected:
731 /**
732 Type of the variable as given by the demangled version of
733 typeid(T).name() for the type.
734 */
735 std::string type_;
736
737 /**
738 Address of the variable for reading and writing
739 */
740 void* addr_ = nullptr;
741
742public:
743 /**
744 Default constructor
745 */
746 ObjectMapClass() = default;
747
748 /**
749 Disallow copying and assignment
750 */
751
753 ObjectMapClass& operator=(const ObjectMapClass&) = delete;
754
755 /**
756 Constructor
757
758 @param addr Address of the object represented by this ObjectMap
759
760 @param type Type of this object as return by typeid(T).name()
761 */
762 ObjectMapClass(void* addr, const std::string& type) :
764 type_(demangle_name(type.c_str())),
765 addr_(addr)
766 {}
767
768 /**
769 Destructor. Should not be called directly (i.e. do not call
770 delete on the object). Call decRefCount() when object is no
771 longer needed. This will also call decRefCount() on all its
772 children.
773 */
774 ~ObjectMapClass() override = default;
775
776 /**
777 Get the type of the represented object
778
779 @return type of represented object
780 */
781 std::string getType() const override { return type_; }
782
783 /**
784 Get the address of the represented object
785
786 @return address of represented object
787 */
788 void* getAddr() const override { return addr_; }
789}; // class ObjectMapClass
790
791// Whether two types share a common type they can both be converted to
792// Users are allowed to provide specializations for std::common_type<T1, T2> for user-defined types
793// See https://en.cppreference.com/w/cpp/types/common_type.html
794template <class T1, class T2, class = void>
795constexpr bool have_common_type_v = false;
796
797template <class T1, class T2>
798constexpr bool have_common_type_v<T1, T2, std::void_t<std::common_type_t<T1, T2>>> = true;
799
800// Whether a type is ordered
801template <class T, class = void>
802constexpr bool is_ordered_v = false;
803
804template <class T>
805constexpr bool is_ordered_v<T, std::void_t<decltype(T {} < T {})>> = true;
806
807// Comparison of two variables if they are convertible to a common type
808// See https://en.cppreference.com/w/cpp/language/usual_arithmetic_conversions.html
809template <typename T1, typename T2>
810std::enable_if_t<have_common_type_v<T1, T2>, bool>
811cmp(T1 t1, ObjectMapComparison::Op op, T2 t2)
812{
813 using T = std::common_type_t<T1, T2>;
814 switch ( op ) {
815 case ObjectMapComparison::Op::LT:
816 if constexpr ( is_ordered_v<T> )
817 return static_cast<T>(t1) < static_cast<T>(t2);
818 else
819 return false;
820 case ObjectMapComparison::Op::LTE:
821 if constexpr ( is_ordered_v<T> )
822 return static_cast<T>(t1) <= static_cast<T>(t2);
823 else
824 return false;
825 case ObjectMapComparison::Op::GT:
826 if constexpr ( is_ordered_v<T> )
827 return static_cast<T>(t1) > static_cast<T>(t2);
828 else
829 return false;
830 case ObjectMapComparison::Op::GTE:
831 if constexpr ( is_ordered_v<T> )
832 return static_cast<T>(t1) >= static_cast<T>(t2);
833 else
834 return false;
835 case ObjectMapComparison::Op::EQ:
836 return static_cast<T>(t1) == static_cast<T>(t2);
837 case ObjectMapComparison::Op::NEQ:
838 case ObjectMapComparison::Op::CHANGED:
839 return static_cast<T>(t1) != static_cast<T>(t2);
840 default:
841 std::cout << "Invalid comparison operator\n";
842 return false;
843 }
844}
845
846// Comparison of two variables if they are not convertible to a common type
847template <typename T1, typename T2>
848std::enable_if_t<!have_common_type_v<T1, T2>, bool>
849cmp(T1 UNUSED(t1), ObjectMapComparison::Op UNUSED(op), T2 UNUSED(t2))
850{
851 // We shouldn't get here.... Can I throw an error somehow?
852 printf("ERROR: cmp() does not support comparison of two types without a std::common_type\n");
853 return false;
854}
855
856/**
857 Template implementation of ObjectMapComparison for <var> <op> <value>
858 */
859template <typename T, typename REF = T>
860class ObjectMapComparison_impl : public ObjectMapComparison
861{
862public:
863 ObjectMapComparison_impl(const std::string& name, REF* var, Op op, const std::string& value) :
864 ObjectMapComparison(name),
865 var_(var),
866 op_(op)
867 {
868 if ( op_ == Op::CHANGED ) {
869 // If we are looking for changes, get the current value as the comp_value_
870 comp_value_ = static_cast<T>(*var_);
871 }
872 else {
873 // Otherwise, we have to have a valid value. If the value is not valid, it will throw an exception.
874 comp_value_ = SST::Core::from_string<T>(value);
875 }
876 }
877
878 bool compare() override
879 {
880 // Get the result of the comparison
881 bool ret = cmp(*var_, op_, comp_value_);
882
883 // For change detection, store the current value for the next test
884 if ( op_ == Op::CHANGED ) comp_value_ = static_cast<T>(*var_);
885
886 return ret;
887 }
888
889 std::string getCurrentValue() const override { return SST::Core::to_string(*var_); }
890
891 void* getVar() const override { return var_; }
892
893 void print(std::ostream& stream) const override
894 {
895 stream << name_ << " " << getStringFromOp(op_);
896 if ( op_ == Op::CHANGED )
897 stream << " ";
898 else
899 stream << " " << SST::Core::to_string(comp_value_) << " ";
900 }
901
902private:
903 REF* const var_;
904 Op const op_;
905 T comp_value_;
906}; // class ObjectMapComparison_impl
907
908/**
909Template implementation of ObjectMapComparison for <var> <op> <var>
910*/
911template <typename T1, typename T2>
912class ObjectMapComparison_var : public ObjectMapComparison
913{
914public:
915 ObjectMapComparison_var(const std::string& name1, T1* var1, Op op, const std::string& name2, T2* var2) :
916 ObjectMapComparison(name1),
917 name2_(name2),
918 var1_(var1),
919 op_(op),
920 var2_(var2)
921 {}
922
923 bool compare() override
924 {
925 T1 v1 = *var1_;
926 T2 v2 = *var2_;
927 return cmp(v1, op_, v2);
928 }
929
930 std::string getCurrentValue() const override
931 {
932 return SST::Core::to_string(*var1_) + " " + SST::Core::to_string(*var2_);
933 }
934
935 void* getVar() const override { return var1_; }
936
937 void print(std::ostream& stream) const override
938 {
939 stream << name_ << " " << getStringFromOp(op_);
940 if ( op_ == Op::CHANGED )
941 stream << " ";
942 else
943 stream << " " << name2_ << " ";
944 }
945
946private:
947 std::string const name2_;
948 T1* const var1_;
949 Op const op_;
950 T2* const var2_;
951}; // class ObjectMapComparison_impl
952
953class ObjectBuffer
954{
955public:
956 ObjectBuffer(const std::string& name, size_t sz) :
957 name_(name),
958 bufSize_(sz)
959 {}
960
961 virtual ~ObjectBuffer() = default;
962
963 virtual void sample(size_t index, bool trigger) = 0;
964 virtual std::string get(size_t index) const = 0;
965 virtual std::string getTriggerVal() const = 0;
966
967 std::string getName() const { return name_; }
968 size_t getBufSize() const { return bufSize_; }
969
970private:
971 std::string name_;
972 size_t bufSize_;
973}; // class ObjectBuffer
974
975template <typename T, typename REF = T>
976class ObjectBuffer_impl : public ObjectBuffer
977{
978public:
979 ObjectBuffer_impl(const std::string& name, REF* varPtr, size_t sz) :
980 ObjectBuffer(name, sz),
981 varPtr_(varPtr)
982 {
983 objectBuffer_.resize(sz);
984 }
985
986 void sample(size_t index, bool trigger) override
987 {
988 objectBuffer_[index] = *varPtr_;
989 if ( trigger ) triggerVal = *varPtr_;
990 }
991
992 std::string get(size_t index) const override { return SST::Core::to_string(objectBuffer_.at(index)); }
993
994 std::string getTriggerVal() const override { return SST::Core::to_string(triggerVal); }
995
996private:
997 REF* const varPtr_;
998 std::vector<T> objectBuffer_;
999 T triggerVal {};
1000}; // class ObjectBuffer_impl
1001
1002class TraceBuffer
1003{
1004
1005public:
1006 TraceBuffer(Core::Serialization::ObjectMap* var, size_t sz, size_t pdelay) :
1007 varObj_(var),
1008 bufSize_(sz),
1009 postDelay_(pdelay)
1010 {
1011 tagBuffer_.resize(bufSize_);
1012 cycleBuffer_.resize(bufSize_);
1013 handlerBuffer_.resize(bufSize_);
1014 }
1015
1016 virtual ~TraceBuffer() = default;
1017
1018 void setBufferReset() { reset_ = true; }
1019
1020 void resetTraceBuffer()
1021 {
1022 printf(" Reset Trace Buffer\n");
1023 postCount_ = 0;
1024 cur_ = 0;
1025 first_ = 0;
1026 numRecs_ = 0;
1027 samplesLost_ = 0;
1028 isOverrun_ = false;
1029 reset_ = false;
1030 state_ = CLEAR;
1031 }
1032
1033 size_t getBufferSize() { return bufSize_; }
1034
1035 void addObjectBuffer(ObjectBuffer* vb)
1036 {
1037 objBuffers_.push_back(vb);
1038 numObjects++;
1039 }
1040
1041 enum BufferState : int {
1042 CLEAR, // 0 Pre Trigger
1043 TRIGGER, // 1 Trigger
1044 POSTTRIGGER, // 2 Post Trigger
1045 OVERRUN // 3 Overrun
1046 };
1047
1048 const std::map<BufferState, char> state2char { { CLEAR, '-' }, { TRIGGER, '!' }, { POSTTRIGGER, '+' },
1049 { OVERRUN, 'o' } };
1050
1051 bool sampleT(bool trigger, uint64_t cycle, const std::string& handler)
1052 {
1053 size_t start_state = state_;
1054 bool invokeAction = false;
1055
1056 // if Trigger == TRUE
1057 if ( trigger ) {
1058 if ( start_state == CLEAR ) { // Not previously triggered
1059 state_ = TRIGGER; // State becomes trigger record
1060 }
1061 // printf(" Sample: trigger\n");
1062
1063 } // if trigger
1064
1065 if ( start_state == TRIGGER || start_state == POSTTRIGGER ) { // trigger record or post trigger
1066 state_ = POSTTRIGGER; // State becomes post trigger
1067 // printf(" Sample: post trigger\n");
1068 }
1069
1070// Circular buffer
1071#ifdef _OBJMAP_DEBUG_
1072 std::cout << " Sample:" << handler << ": numRecs:" << numRecs_ << " first:" << first_ << " cur:" << cur_
1073 << " state:" << state2char.at(state_) << " isOverrun:" << isOverrun_
1074 << " samplesLost:" << samplesLost_ << std::endl;
1075#endif
1076 cycleBuffer_[cur_] = cycle;
1077 handlerBuffer_[cur_] = handler;
1078 if ( trigger ) {
1079 triggerCycle = cycle;
1080 }
1081
1082 // Sample all the trace object buffers
1083 ObjectBuffer* varBuffer_;
1084 for ( size_t obj = 0; obj < numObjects; obj++ ) {
1085 varBuffer_ = objBuffers_[obj];
1086 varBuffer_->sample(cur_, trigger);
1087 }
1088
1089 if ( numRecs_ < bufSize_ ) {
1090 tagBuffer_[cur_] = state_;
1091 numRecs_++;
1092 cur_ = (cur_ + 1) % bufSize_;
1093 if ( cur_ == 0 ) first_ = 0; // 1;
1094 }
1095 else { // Buffer full
1096 // Check to see if we are overwriting trigger
1097 if ( tagBuffer_[cur_] == TRIGGER ) {
1098 // printf(" Sample Overrun\n");
1099 isOverrun_ = true;
1100 }
1101 tagBuffer_[cur_] = state_;
1102 numRecs_++;
1103 cur_ = (cur_ + 1) % bufSize_;
1104 first_ = cur_;
1105 }
1106
1107 if ( isOverrun_ ) {
1108 samplesLost_++;
1109 }
1110
1111 if ( (state_ == TRIGGER) && (postDelay_ == 0) ) {
1112 invokeAction = true;
1113 std::cout << " Invoke Action\n";
1114 }
1115
1116 if ( state_ == POSTTRIGGER ) {
1117 postCount_++;
1118 if ( postCount_ >= postDelay_ ) {
1119 invokeAction = true;
1120 std::cout << " Invoke Action\n";
1121 }
1122 }
1123
1124 return invokeAction;
1125 }
1126
1127 void dumpTraceBufferT()
1128 {
1129 if ( numRecs_ == 0 ) return;
1130
1131 size_t start;
1132 size_t end;
1133
1134 start = first_;
1135 if ( cur_ == 0 ) {
1136 end = bufSize_ - 1;
1137 }
1138 else {
1139 end = cur_ - 1;
1140 }
1141 // std::cout << "start=" << start << " end=" << end << std::endl;
1142
1143 for ( int j = start;; j++ ) {
1144 size_t i = j % bufSize_;
1145
1146 std::cout << "buf[" << i << "] " << handlerBuffer_.at(i) << " @" << cycleBuffer_.at(i) << " ("
1147 << state2char.at(tagBuffer_.at(i)) << ") ";
1148
1149 for ( size_t obj = 0; obj < numObjects; obj++ ) {
1150 ObjectBuffer* varBuffer_ = objBuffers_[obj];
1151 std::cout << SST::Core::to_string(varBuffer_->getName()) << "=" << varBuffer_->get(i) << " ";
1152 }
1153 std::cout << "\n";
1154
1155 if ( i == end ) {
1156 break;
1157 }
1158 }
1159 }
1160
1161 void dumpTriggerRecord()
1162 {
1163 std::stringstream ss;
1164 if ( numRecs_ == 0 ) {
1165 std::cout << "No trace samples in current buffer" << std::endl;
1166 return;
1167 }
1168 if ( state_ != CLEAR ) {
1169 ss << "LastTriggerRecord:@cycle" << triggerCycle << ": SamplesLost=" << samplesLost_ << ": ";
1170 for ( size_t obj = 0; obj < numObjects; obj++ ) {
1171 ObjectBuffer* varBuffer_ = objBuffers_[obj];
1172 ss << SST::Core::to_string(varBuffer_->getName()) << "=" << varBuffer_->getTriggerVal() << " ";
1173 }
1174 ss << "\n";
1175 std::cout << ss.str();
1176 }
1177 }
1178
1179 void printVars(std::stringstream& ss)
1180 {
1181 for ( size_t obj = 0; obj < numObjects; obj++ ) {
1182 ObjectBuffer* varBuffer_ = objBuffers_[obj];
1183 ss << SST::Core::to_string(varBuffer_->getName()) << " ";
1184 }
1185 }
1186
1187 void printConfig(std::stringstream& ss)
1188 {
1189 ss << "bufsize = " << bufSize_ << " postDelay = " << postDelay_ << " : ";
1190 printVars(ss);
1191 }
1192
1193 // private:
1194 Core::Serialization::ObjectMap* varObj_ = nullptr;
1195 size_t bufSize_ = 64;
1196 size_t postDelay_ = 8;
1197 size_t postCount_ = 0;
1198 size_t cur_ = 0;
1199 size_t first_ = 0;
1200 size_t numRecs_ = 0;
1201 bool isOverrun_ = false;
1202 size_t samplesLost_ = 0;
1203 bool reset_ = false;
1204 BufferState state_ = CLEAR;
1205
1206 size_t numObjects = 0;
1207 std::vector<BufferState> tagBuffer_;
1208 std::vector<std::string> handlerBuffer_;
1209 std::vector<ObjectBuffer*> objBuffers_;
1210 std::vector<uint64_t> cycleBuffer_;
1211 uint64_t triggerCycle;
1212
1213}; // class TraceBuffer
1214
1215/**
1216 ObjectMap representing fundamental types, and classes treated as
1217 fundamental types. In order for an object to be treated as a
1218 fundamental, it must be printable using SST::Core::to_string() and
1219 assignable using SST::Core::from_string(). If this is not true, it
1220 is possible to create a template specialization for the type
1221 desired to be treated as a fundamental. The specialization will
1222 need to provide the functions for getting and setting the values as
1223 a string.
1224
1225 REF defaults to T, but may be a type like std::vector<bool>::reference
1226 or std::bitset<N>::reference indicating a proxy reference to the object.
1227*/
1228template <typename T, typename REF = T>
1229class ObjectMapFundamental : public ObjectMap
1230{
1231protected:
1232 /**
1233 Address of the variable for reading and writing
1234 */
1235 REF* addr_ = nullptr;
1236
1237public:
1238 /**
1239 Set the value of the object represented as a string
1240
1241 @param value Value to set the underlying object to, represented
1242 as a string
1243 */
1244 virtual void set_impl(const std::string& value) override
1245 {
1246 try {
1247 *addr_ = SST::Core::from_string<T>(value);
1248 }
1249 catch ( const std::exception& e ) {
1250 std::cerr << e.what() << ": " << value << std::endl;
1251 }
1252 }
1253
1254 bool checkValue(const std::string& value) const override
1255 {
1256 try {
1257 *addr_ = SST::Core::from_string<T>(value);
1258 return true;
1259 }
1260 catch ( const std::exception& e ) {
1261 std::cerr << e.what() << ": " << value << std::endl;
1262 return false;
1263 }
1264 }
1265
1266 /**
1267 Get the value of the object as a string
1268 */
1269 std::string get() const override { return addr_ ? SST::Core::to_string(static_cast<T>(*addr_)) : "nullptr"; }
1270
1271 /**
1272 Returns true as object is a fundamental
1273
1274 @return true
1275 */
1276 bool isFundamental() const final override { return true; }
1277
1278 /**
1279 Get the address of the variable represented by the ObjectMap
1280
1281 @return Address of variable
1282 */
1283 void* getAddr() const override { return addr_; }
1284
1285 explicit ObjectMapFundamental(REF* addr) :
1286 addr_(addr)
1287 {}
1288
1289 /**
1290 Destructor. Should not be called directly (i.e. do not call
1291 delete on the object). Call decRefCount() when object is no
1292 longer needed. This will also call decRefCount() on all its
1293 children.
1294 */
1295 ~ObjectMapFundamental() override = default;
1296
1297 /**
1298 Disallow copying and assignment
1299 */
1300
1301 ObjectMapFundamental(const ObjectMapFundamental&) = delete;
1302 ObjectMapFundamental& operator=(const ObjectMapFundamental&) = delete;
1303
1304 /**
1305 Return the type represented by this ObjectMap as given by the
1306 demangled version of typeid(T).name()
1307
1308 @return type of underlying object
1309 */
1310 std::string getType() const override { return demangle_name(typeid(T).name()); }
1311
1312 ObjectMapComparison* getComparison(
1313 const std::string& name, ObjectMapComparison::Op op, const std::string& value) const override
1314 {
1315 return new ObjectMapComparison_impl<T, REF>(name, addr_, op, value);
1316 }
1317
1318 ObjectMapComparison* getComparisonVar(const std::string& name, ObjectMapComparison::Op UNUSED(op),
1319 const std::string& name2, ObjectMap* var2) const override
1320 {
1321 // Ensure var2 is fundamental type
1322 if ( !var2->isFundamental() ) {
1323 printf("Triggers can only use fundamental types; %s is not fundamental\n", name2.c_str());
1324 return nullptr;
1325 }
1326
1327 std::string type = var2->getType();
1328#if 0
1329 std::cout << "In ObjectMapComparison_var: " << name << " " << name2 << std::endl;
1330 // std::cout << "typeid(T): " << demangle_name(typeid(T).name()) << std::endl;
1331 std::string type1 = getType();
1332 std::cout << "getType(v1): " << type1 << std::endl;
1333 std::cout << "getType(v2): " << type << std::endl;
1334#endif
1335
1336 // Create ObjectMapComparison_var which compares two variables
1337 // Only support arithmetic types for now
1338 if constexpr ( std::is_arithmetic_v<T> ) {
1339 if ( type == "int" ) {
1341 name, addr_, op, name2, static_cast<int*>(var2->getAddr()));
1342 }
1343 else if ( type == "unsigned" || type == "unsigned int" ) {
1344 return new ObjectMapComparison_var<REF, unsigned>(
1345 name, addr_, op, name2, static_cast<unsigned*>(var2->getAddr()));
1346 }
1347 else if ( type == "long" ) {
1348 return new ObjectMapComparison_var<REF, long>(
1349 name, addr_, op, name2, static_cast<long*>(var2->getAddr()));
1350 }
1351 else if ( type == "unsigned long" ) {
1352 return new ObjectMapComparison_var<REF, unsigned long>(
1353 name, addr_, op, name2, static_cast<unsigned long*>(var2->getAddr()));
1354 }
1355 else if ( type == "char" ) {
1356 return new ObjectMapComparison_var<REF, char>(
1357 name, addr_, op, name2, static_cast<char*>(var2->getAddr()));
1358 }
1359 else if ( type == "signed char" ) {
1360 return new ObjectMapComparison_var<REF, signed char>(
1361 name, addr_, op, name2, static_cast<signed char*>(var2->getAddr()));
1362 }
1363 else if ( type == "unsigned char" ) {
1364 return new ObjectMapComparison_var<REF, unsigned char>(
1365 name, addr_, op, name2, static_cast<unsigned char*>(var2->getAddr()));
1366 }
1367 else if ( type == "short" ) {
1368 return new ObjectMapComparison_var<REF, short>(
1369 name, addr_, op, name2, static_cast<short*>(var2->getAddr()));
1370 }
1371 else if ( type == "unsigned short" ) {
1372 return new ObjectMapComparison_var<REF, unsigned short>(
1373 name, addr_, op, name2, static_cast<unsigned short*>(var2->getAddr()));
1374 }
1375 else if ( type == "long long" ) {
1376 return new ObjectMapComparison_var<REF, long long>(
1377 name, addr_, op, name2, static_cast<long long*>(var2->getAddr()));
1378 }
1379 else if ( type == "unsigned long long" ) {
1380 return new ObjectMapComparison_var<REF, unsigned long long>(
1381 name, addr_, op, name2, static_cast<unsigned long long*>(var2->getAddr()));
1382 }
1383 else if ( type == "bool" ) {
1384 return new ObjectMapComparison_var<REF, bool>(
1385 name, addr_, op, name2, static_cast<bool*>(var2->getAddr()));
1386 }
1387 else if ( type == "float" ) {
1388 return new ObjectMapComparison_var<REF, float>(
1389 name, addr_, op, name2, static_cast<float*>(var2->getAddr()));
1390 }
1391 else if ( type == "double" ) {
1392 return new ObjectMapComparison_var<REF, double>(
1393 name, addr_, op, name2, static_cast<double*>(var2->getAddr()));
1394 }
1395 else if ( type == "long double" ) {
1396 return new ObjectMapComparison_var<REF, long double>(
1397 name, addr_, op, name2, static_cast<long double*>(var2->getAddr()));
1398 }
1399 } // end if first var is arithmetic
1400
1401 std::cout << "Invalid type for comparison: " << name2 << "(" << type << ")\n";
1402 return nullptr;
1403 }
1404
1405 ObjectBuffer* getObjectBuffer(const std::string& name, size_t sz) override
1406 {
1407 return new ObjectBuffer_impl<T, REF>(name, addr_, sz);
1408 }
1409};
1410
1411// Forward declaration of ObjectMapSerialization
1412template <typename T>
1413ObjectMap* ObjectMapSerialization(T&& obj);
1414
1415/**
1416 Class used to map containers
1417 */
1418template <class T>
1419class ObjectMapContainer : public ObjectMapWithChildren
1420{
1421protected:
1422 T* addr_;
1423
1424public:
1425 explicit ObjectMapContainer(T* addr) :
1426 addr_(addr)
1427 {}
1428 bool isContainer() const final override { return true; }
1429 std::string getType() const override { return demangle_name(typeid(T).name()); }
1430 void* getAddr() const override { return addr_; }
1431 void refresh() override
1432 {
1433 // Decrement the reference count of all children, which will be replaced
1434 for ( const auto& [name, child] : variables_ )
1435 if ( child != nullptr ) child->decRefCount();
1436
1437 // Replace the children with new children by re-serializing the container
1438 // ObjectMapSerialization(*addr_) returns an ObjectMap* to a new serialization of the container
1439 // dynamic_cast<ObjectMapContainer&> downcasts the returned ObjectMap to this ObjectMapContainer
1440 // std::move improves performance, by shallow-moving the new variables_ into this class's variables_
1441 variables_ = std::move(dynamic_cast<ObjectMapContainer&>(*ObjectMapSerialization(*addr_)).variables_);
1442 }
1443 ~ObjectMapContainer() override = default;
1444};
1445
1446// ObjectMap for reference proxy types such as std::bitset<N>::reference, std::vector<bool>::reference,
1447// atomic_reference, whose referenced types cannot be copied or pointed to with pointers, but whose
1448// underlying values are ordinary fundamental types.
1449//
1450// T is the underlying fundamental type, such as bool, which is the type in which values are read and written.
1451// REF is the type of the proxy reference class, which is copyable, convertible to T, and assignable from T.
1452// PTYPE is the type to print, which defaults to T, but might be a decorated class name like std::atomic<T>.
1453template <typename T, typename REF, typename PTYPE = T>
1454class ObjectMapFundamentalReference : public ObjectMapFundamental<T, REF>
1455{
1456 REF ref;
1457
1458 static_assert(std::is_copy_constructible_v<REF> && std::is_convertible_v<REF, T> && std::is_assignable_v<REF, T>,
1459 "ObjectMapFundamentalReference<T, REF, PTYPE>: REF must be copyable, implicitly convertible to T, and "
1460 "assignable from T.");
1461
1462public:
1463 // std::addressof is used because some libraries overload REF::operator&()
1464 explicit ObjectMapFundamentalReference(const REF& ref) :
1465 ObjectMapFundamental<T, REF>(std::addressof(this->ref)),
1466 ref(ref)
1467 {}
1468
1469 // Although this is a fundamental type of underlying type T, PTYPE can be something like std::atomic<T>
1470 std::string getType() const override { return this->demangle_name(typeid(PTYPE).name()); }
1471
1474 ~ObjectMapFundamentalReference() override = default;
1475};
1476
1477} // namespace SST::Core::Serialization
1478
1479#endif // SST_CORE_SERIALIZATION_OBJECTMAP_H
Definition objectMap.h:954
void * getAddr() const override
Get the address of the represented object.
Definition objectMap.h:788
std::string type_
Type of the variable as given by the demangled version of typeid(T).name() for the type.
Definition objectMap.h:735
ObjectMapClass(const ObjectMapClass &)=delete
Disallow copying and assignment.
std::string getType() const override
Get the type of the represented object.
Definition objectMap.h:781
ObjectMapClass(void *addr, const std::string &type)
Constructor.
Definition objectMap.h:762
void * addr_
Address of the variable for reading and writing.
Definition objectMap.h:740
~ObjectMapClass() override=default
Destructor.
ObjectMapClass()=default
Default constructor.
Template implementation of ObjectMapComparison for <op> .
Definition objectMap.h:861
Template implementation of ObjectMapComparison for <op> .
Definition objectMap.h:913
Base class for interacting with data from ObjectMap.
Definition objectMap.h:117
Class used to map containers.
Definition objectMap.h:1420
void refresh() override
Refresh the ObjectMap, reconstructing children.
Definition objectMap.h:1431
std::string getType() const override
Get the type of the variable represented by the ObjectMap.
Definition objectMap.h:1429
bool isContainer() const final override
Check to see if this ObjectMap represents a container.
Definition objectMap.h:1428
void * getAddr() const override
Get the address of the variable represented by the ObjectMap.
Definition objectMap.h:1430
std::string getType() const override
Return the type represented by this ObjectMap as given by the demangled version of typeid(T)....
Definition objectMap.h:1470
ObjectMap representing fundamental types, and classes treated as fundamental types.
Definition objectMap.h:1230
std::string getType() const override
Return the type represented by this ObjectMap as given by the demangled version of typeid(T)....
Definition objectMap.h:1310
REF * addr_
Address of the variable for reading and writing.
Definition objectMap.h:1235
void * getAddr() const override
Get the address of the variable represented by the ObjectMap.
Definition objectMap.h:1283
std::string get() const override
Get the value of the object as a string.
Definition objectMap.h:1269
virtual void set_impl(const std::string &value) override
Set the value of the object represented as a string.
Definition objectMap.h:1244
bool isFundamental() const final override
Returns true as object is a fundamental.
Definition objectMap.h:1276
ObjectMapFundamental(const ObjectMapFundamental &)=delete
Disallow copying and assignment.
~ObjectMapFundamental() override=default
Destructor.
ObjectMapHierarchyOnly()=default
Default constructor.
~ObjectMapHierarchyOnly() override=default
Destructor.
std::string getType() const override
Returns empty string since there is no underlying object being represented.
Definition objectMap.h:713
void * getAddr() const override
Returns nullptr since there is no underlying object being represented.
Definition objectMap.h:721
const ObjectMultimap & getVariables() const final override
Get the list of child variables contained in this ObjectMap.
Definition objectMap.h:671
ObjectMapWithChildren()=default
Default constructor.
~ObjectMapWithChildren() override
Destructor.
Definition objectMap.h:635
void addVariable(const std::string &name, ObjectMap *obj) final override
Adds a variable to this ObjectMap.
Definition objectMap.h:655
void refresh() override
Refresh the children.
Definition objectMap.h:677
void removeVariable(const std::string &name) final override
Removes a variable from this ObjectMap.
Definition objectMap.h:662
ObjectMultimap variables_
Map that child ObjectMaps are stored in.
Definition objectMap.h:621
ObjectMapWithChildren(const ObjectMapWithChildren &)=delete
Disallow copying and assignment.
Base class for objects created by the serializer mapping mode used to map the variables for objects.
Definition objectMap.h:188
ObjectMap()=default
Default constructor primarily used for the "top" object in the hierarchy.
bool isReadOnly() const
Check to see if this object is read-only.
Definition objectMap.h:253
virtual std::string get() const
Get the value of the variable as a string.
Definition objectMap.h:424
virtual void removeVariable(const std::string &UNUSED(name))
Removes a variable from this ObjectMap.
Definition objectMap.h:412
size_t getRefCount() const
Get the current reference count.
Definition objectMap.h:350
virtual const ObjectMultimap & getVariables() const
Get the list of child variables contained in this ObjectMap.
Definition objectMap.h:314
bool read_only_
Indicates whether or not the variable is read-only.
Definition objectMap.h:211
virtual std::string listVariable(std::string name, bool &found, int recurse=0)
Create a string that lists information for the specified variable.
Definition objectMap.cc:168
std::string getFullName() const
Get the full hierarchical name of the variable represented by this ObjectMap, based on the path taken...
Definition objectMap.cc:23
ObjectMap(const ObjectMap &)=delete
Disallow copying and assignment.
std::string getName() const
Get the name of the variable represented by this ObjectMap.
Definition objectMap.h:280
virtual std::string list(int recurse=0)
Create a string that lists information for the current object.
Definition objectMap.cc:192
virtual ObjectMapComparison * getComparison(const std::string &UNUSED(name), ObjectMapComparison::Op UNUSED(op), const std::string &UNUSED(value)) const
Get a watch point for this object.
Definition objectMap.h:356
virtual std::string getType() const =0
Get the type of the variable represented by the ObjectMap.
ObjectMap * selectVariable(std::string name, bool &loop_detected, bool confirm=false)
Get the ObjectMap for the specified variable.
Definition objectMap.cc:50
virtual void addVariable(const std::string &UNUSED(name), ObjectMap *UNUSED(obj))
Adds a variable to this ObjectMap.
Definition objectMap.h:403
virtual ~ObjectMap()=default
Destructor.
void incRefCount()
Increment the reference counter for this ObjectMap.
Definition objectMap.h:332
virtual bool checkValue(const std::string &UNUSED(value)) const
Check if value string is valid for this type.
Definition objectMap.h:270
virtual bool isContainer() const
Check to see if this ObjectMap represents a container.
Definition objectMap.h:491
void set(const std::string &value)
Sets the value of the variable represented by the ObjectMap to the specified value,...
Definition objectMap.h:438
virtual void refresh()
Refresh the ObjectMap, reconstructing children.
Definition objectMap.h:560
ObjectMap * findVariable(const std::string &name, bool confirm=false) const
Find a variable in this object map.
Definition objectMap.cc:228
virtual void deactivate_callback()
Function that will get called when this object is deactivated (i.e selectParent() is called).
Definition objectMap.h:230
virtual bool isFundamental() const
Check to see if this ObjectMap represents a fundamental or a class treated as a fundamental.
Definition objectMap.h:483
virtual void set_impl(const std::string &UNUSED(value))
Function implemented by derived classes to implement set().
Definition objectMap.h:219
virtual void activate_callback()
Function that will get called when this object is selected.
Definition objectMap.h:224
static std::string demangle_name(const char *name)
Static function to demangle type names returned from typeid(T).name().
Definition objectMap.cc:152
void decRefCount()
Decrement the reference counter for this ObjectMap.
Definition objectMap.h:340
ObjectMap * selectParent()
Get the parent for this ObjectMap.
Definition objectMap.cc:38
void setReadOnly(bool state=true)
Set the read-only state of the object.
Definition objectMap.h:263
virtual void * getAddr() const =0
Get the address of the variable represented by the ObjectMap.
ObjectMapMetaData * mdata_
Metadata object for walking the object hierarchy.
Definition objectMap.h:206
Definition objectMap.h:1003
Metadata object that each ObjectMap has a pointer to in order to track the hierarchy information whil...
Definition objectMap.h:82
ObjectMapMetaData(ObjectMap *parent, const std::string &name)
Constructor for intializing data memebers.
Definition objectMap.h:97
ObjectMap * parent
Parent object that contained this object and through which it was selected.
Definition objectMap.h:87
std::string name
Name of this object in the context of the currently set parent.
Definition objectMap.h:92