SST 15.0
Structural Simulation Toolkit
serializer.h
1// Copyright 2009-2025 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-2025, 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_SERIALIZER_H
13#define SST_CORE_SERIALIZATION_SERIALIZER_H
14
15// These includes have guards to print warnings if they are included
16// independent of this file. Set the #define that will disable the warnings.
17#define SST_INCLUDING_SERIALIZER_H
18#include "sst/core/serialization/impl/mapper.h"
19#include "sst/core/serialization/impl/packer.h"
20#include "sst/core/serialization/impl/sizer.h"
21#include "sst/core/serialization/impl/unpacker.h"
22// Reenble warnings for including the above file independent of this file.
23#undef SST_INCLUDING_SERIALIZER_H
24
25#include <cstdint>
26#include <cstring>
27#include <list>
28#include <map>
29#include <set>
30#include <stack>
31#include <stdexcept>
32#include <string>
33#include <utility>
34
35namespace SST::Core::Serialization {
36
37class ObjectMap;
39
40/**
41 * This class is basically a wrapper for objects to declare the order in
42 * which their members should be ser/des
43 */
44class serializer
45{
46public:
47 enum SERIALIZE_MODE { SIZER, PACK, UNPACK, MAP };
48
49public:
50 serializer() :
51 mode_(SIZER) // just sizing by default
52 {}
53
54 pvt::ser_mapper& mapper() { return mapper_; }
55
56 pvt::ser_packer& packer() { return packer_; }
57
58 pvt::ser_unpacker& unpacker() { return unpacker_; }
59
60 pvt::ser_sizer& sizer() { return sizer_; }
61
62 template <class T>
63 void size(T& t)
64 {
65 sizer_.size<T>(t);
66 }
67
68 template <class T>
69 void pack(T& t)
70 {
71 packer_.pack<T>(t);
72 }
73
74 template <class T>
75 void unpack(T& t)
76 {
77 unpacker_.unpack<T>(t);
78 }
79
80 virtual ~serializer() {}
81
82 SERIALIZE_MODE
83 mode() const { return mode_; }
84
85 void set_mode(SERIALIZE_MODE mode) { mode_ = mode; }
86
87 void reset()
88 {
89 sizer_.reset();
90 packer_.reset();
91 unpacker_.reset();
92 }
93
94 template <typename T>
95 void primitive(T& t)
96 {
97 switch ( mode_ ) {
98 case SIZER:
99 sizer_.size(t);
100 break;
101 case PACK:
102 packer_.pack(t);
103 break;
104 case UNPACK:
105 unpacker_.unpack(t);
106 break;
107 case MAP:
108 break;
109 }
110 }
111
112 void raw(void* data, size_t size)
113 {
114 switch ( mode_ ) {
115 case SIZER:
116 sizer_.add(size);
117 break;
118 case PACK:
119 memcpy(packer_.next_str(size), data, size);
120 break;
121 case UNPACK:
122 memcpy(data, unpacker_.next_str(size), size);
123 break;
124 case MAP:
125 break;
126 }
127 }
128
129 template <typename ELEM_T, typename SIZE_T>
130 void binary(ELEM_T*& buffer, SIZE_T& size)
131 {
132 switch ( mode_ ) {
133 case SIZER:
134 sizer_.add(sizeof(SIZE_T));
135 sizer_.add(size * sizeof(ELEM_T));
136 break;
137 case PACK:
138 if ( buffer ) {
139 packer_.pack(size);
140 packer_.pack_buffer(buffer, size * sizeof(ELEM_T));
141 }
142 else {
143 SIZE_T nullsize = 0;
144 packer_.pack(nullsize);
145 }
146 break;
147 case UNPACK:
148 unpacker_.unpack(size);
149 buffer = nullptr;
150 if ( size ) unpacker_.unpack_buffer(&buffer, size * sizeof(ELEM_T));
151 break;
152 case MAP:
153 break;
154 }
155 }
156
157 // For void*, we get sizeof(), which errors.
158 // Create a wrapper that casts to char* and uses above
159 template <typename Int>
160 void binary(void*& buffer, Int& size)
161 {
162 binary(reinterpret_cast<char*&>(buffer), size);
163 }
164
165 void string(std::string& str);
166
167 void start_packing(char* buffer, size_t size)
168 {
169 packer_.init(buffer, size);
170 mode_ = PACK;
171 ser_pointer_set.clear();
172 ser_pointer_map.clear();
173 }
174
175 void start_sizing()
176 {
177 sizer_.reset();
178 mode_ = SIZER;
179 ser_pointer_set.clear();
180 ser_pointer_map.clear();
181 }
182
183 void start_unpacking(char* buffer, size_t size)
184 {
185 unpacker_.init(buffer, size);
186 mode_ = UNPACK;
187 ser_pointer_set.clear();
188 ser_pointer_map.clear();
189 }
190
191 void start_mapping(ObjectMap* obj)
192 {
193 mapper_.init(obj);
194 mode_ = MAP;
195 }
196
197 size_t size() const
198 {
199 switch ( mode_ ) {
200 case SIZER:
201 return sizer_.size();
202 case PACK:
203 return packer_.size();
204 case UNPACK:
205 return unpacker_.size();
206 case MAP:
207 break;
208 }
209 return 0;
210 }
211
212 inline bool check_pointer_pack(uintptr_t ptr)
213 {
214 if ( ser_pointer_set.count(ptr) == 0 ) {
215 ser_pointer_set.insert(ptr);
216 return false;
217 }
218 return true;
219 }
220
221 inline uintptr_t check_pointer_unpack(uintptr_t ptr)
222 {
223 auto it = ser_pointer_map.find(ptr);
224 if ( it != ser_pointer_map.end() ) {
225 return it->second;
226 }
227 // Keep a copy of the ptr in case we have a split report
228 split_key = ptr;
229 return 0;
230 }
231
232 ObjectMap* check_pointer_map(uintptr_t ptr)
233 {
234 auto it = ser_pointer_map.find(ptr);
235 if ( it != ser_pointer_map.end() ) {
236 return reinterpret_cast<ObjectMap*>(it->second);
237 }
238 return nullptr;
239 }
240
241 inline void report_new_pointer(uintptr_t real_ptr) { ser_pointer_map[split_key] = real_ptr; }
242
243 inline void report_real_pointer(uintptr_t ptr, uintptr_t real_ptr) { ser_pointer_map[ptr] = real_ptr; }
244
245 void enable_pointer_tracking(bool value = true) { enable_ptr_tracking_ = value; }
246
247 inline bool is_pointer_tracking_enabled() { return enable_ptr_tracking_; }
248
249 void report_object_map(ObjectMap* ptr);
250
251 // Get the map name
252 const char* getMapName() const;
253
254protected:
255 // only one of these is going to be valid for this serializer
256 // not very good class design, but a little more convenient
257 pvt::ser_packer packer_;
258 pvt::ser_unpacker unpacker_;
259 pvt::ser_sizer sizer_;
260 pvt::ser_mapper mapper_;
261 SERIALIZE_MODE mode_;
262 bool enable_ptr_tracking_ = false;
263
264 std::set<uintptr_t> ser_pointer_set;
265 // Used for unpacking and mapping
266 std::map<uintptr_t, uintptr_t> ser_pointer_map;
267 uintptr_t split_key;
268 const ObjectMapContext* mapContext = nullptr;
269 friend class ObjectMapContext;
270}; // class serializer
271
272/**
273 ObjectMap context which is saved in a virtual stack when name or other information changes.
274 When ObjectMapContext is destroyed, the serializer goes back to the previous ObjectMapContext.
275 */
276
277class ObjectMapContext
278{
279 serializer& ser;
280 const ObjectMapContext* const prevContext;
281 const char* const name;
282
283public:
284 ObjectMapContext(serializer& ser, const char* name) :
285 ser(ser),
286 prevContext(ser.mapContext),
287 name(name)
288 {
289 DISABLE_WARN_DANGLING_POINTER // GCC 13 bug causes spurious warning
290 ser.mapContext = this; // change the serializer's context to this new one
291 REENABLE_WARNING
292 }
293 ~ObjectMapContext() { ser.mapContext = prevContext; } // restore the serializer's old context
294 const char* getName() const { return name; }
295}; // class ObjectMapContext
296
297} // namespace SST::Core::Serialization
298
299#endif // SST_CORE_SERIALIZATION_SERIALIZER_H
ObjectMap context which is saved in a virtual stack when name or other information changes.
Definition serializer.h:278
Base class for objects created by the serializer mapping mode used to map the variables for objects.
Definition objectMap.h:112
This class is basically a wrapper for objects to declare the order in which their members should be s...
Definition serializer.h:45