SST  15.1.0
StructuralSimulationToolkit
serializable_base.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_SERIALIZABLE_BASE_H
13 #define SST_CORE_SERIALIZATION_SERIALIZABLE_BASE_H
14 
15 #include "sst/core/serialization/serializer.h"
16 #include "sst/core/warnmacros.h"
17 
18 #include <cstdint>
19 #include <cstring>
20 #include <limits>
21 #include <stdint.h>
22 #include <string>
23 #include <typeinfo>
24 #include <unordered_map>
25 
26 namespace SST::Core::Serialization {
27 
28 namespace pvt {
29 
30 // Functions to implement the hash for cls_id at compile time. The
31 // hash function being implemented is:
32 
33 inline uint32_t
34 type_hash(const char* key)
35 {
36  int len = ::strlen(key);
37  uint32_t hash = 0;
38  for ( int i = 0; i < len; ++i ) {
39  hash += key[i];
40  hash += (hash << 10);
41  hash ^= (hash >> 6);
42  }
43  hash += (hash << 3);
44  hash ^= (hash >> 11);
45  hash += (hash << 15);
46 
47  return hash;
48 }
49 
50 // Using constexpr is very limited, so the implementation is a bit
51 // convoluted. May be able to streamline later.
52 
53 // computes hash ^= (hash >> 6)
54 constexpr uint32_t
55 B(const uint32_t b)
56 {
57  return b ^ (b >> 6);
58 }
59 
60 // computes hash += (hash << 10)
61 constexpr uint32_t
62 A(const uint32_t a)
63 {
64  return B((a << 10) + a);
65 }
66 
67 // recursive piece that computes the for loop
68 template <size_t idx>
69 constexpr uint32_t
70 ct_hash_rec(const char* str)
71 {
72  return A(str[idx] + ct_hash_rec<idx - 1>(str));
73 }
74 
75 // End of the recursion (i.e. when you've walked back off the front of
76 // the string
77 template <>
78 constexpr uint32_t
79 ct_hash_rec<size_t(-1)>(const char* UNUSED(str))
80 {
81  return 0;
82 }
83 
84 // computes hash += (hash << 15)
85 constexpr uint32_t
86 E(const uint32_t e)
87 {
88  return (e << 15) + e;
89 }
90 
91 // computes hash ^= (hash >> 11)
92 constexpr uint32_t
93 D(const uint32_t d)
94 {
95  return E((d >> 11) ^ d);
96 }
97 
98 // computes hash += (hash << 3)
99 constexpr uint32_t
100 C(const uint32_t c)
101 {
102  return D((c << 3) + c);
103 }
104 
105 // Main function that computes the final manipulations after calling
106 // the recursive function to compute the for loop.
107 template <size_t idx>
108 constexpr uint32_t
109 ct_hash(const char* str)
110 {
111  return C(ct_hash_rec<idx>(str));
112 }
113 
114 // Macro that should be used to call the compile time hash function
115 #define COMPILE_TIME_HASH(x) (::SST::Core::Serialization::pvt::ct_hash<sizeof(x) - 2>(x))
116 
117 } // namespace pvt
118 
120 {
121 public:
122  static constexpr uint32_t NullClsId = std::numeric_limits<uint32_t>::max();
123 
124  virtual const char* cls_name() const = 0;
125 
126  virtual void serialize_order(serializer& ser) = 0;
127 
128  virtual uint32_t cls_id() const = 0;
129  virtual std::string serialization_name() const = 0;
130 
131  virtual ~serializable_base() {}
132 
133 protected:
134  enum cxn_flag_t { ConstructorFlag };
135  [[noreturn]]
136  static void serializable_abort(uint32_t line, const char* file, const char* func, const char* obj);
137 };
138 
139 
140 template <class T>
142 {};
143 
144 #define ImplementVirtualSerializable(obj) \
145  \
146 public: \
147  [[noreturn]] \
148  static void throw_exc() \
149  { \
150  ::SST::Core::Serialization::serializable_base::serializable_abort(__LINE__, __FILE__, __FUNCTION__, #obj); \
151  } \
152  virtual const char* cls_name() const override \
153  { \
154  return #obj; \
155  } \
156  virtual uint32_t cls_id() const override \
157  { \
158  throw_exc(); \
159  return 0; \
160  } \
161  virtual std::string serialization_name() const override \
162  { \
163  throw_exc(); \
164  return ""; \
165  }
166 
167 #define NotSerializable(obj) \
168  \
169 public: \
170  [[noreturn]] \
171  static void throw_exc() \
172  { \
173  ::SST::Core::Serialization::serializable_base::serializable_abort(__LINE__, __FILE__, __FUNCTION__, #obj); \
174  } \
175  virtual void serialize_order(SST::Core::Serialization::serializer& UNUSED(sst)) override \
176  { \
177  throw_exc(); \
178  } \
179  virtual uint32_t cls_id() const override \
180  { \
181  throw_exc(); \
182  return ::SST::Core::Serialization::serializable_base::NullClsId; \
183  } \
184  static obj* construct_deserialize_stub() \
185  { \
186  throw_exc(); \
187  return 0; \
188  } \
189  virtual std::string serialization_name() const override \
190  { \
191  throw_exc(); \
192  return ""; \
193  } \
194  virtual const char* cls_name() const override \
195  { \
196  return #obj; \
197  }
198 
199 // virtual const char* cls_name() const override { return obj_str; }
200 #define ImplementSerializableDefaultConstructor(obj, obj_str) \
201  \
202 public: \
203  virtual const char* cls_name() const override \
204  { \
205  return SST::Core::Serialization::serializable_builder_impl<obj>::static_name(); \
206  } \
207  virtual uint32_t cls_id() const override \
208  { \
209  return SST::Core::Serialization::serializable_builder_impl<obj>::static_cls_id(); \
210  } \
211  static obj* construct_deserialize_stub() \
212  { \
213  return new obj; \
214  } \
215  virtual std::string serialization_name() const override \
216  { \
217  return obj_str; \
218  } \
219  \
220 private: \
221  friend class SST::Core::Serialization::serializable_builder_impl<obj>; \
222  static bool you_forgot_to_add_ImplementSerializable_to_this_class() \
223  { \
224  return false; \
225  }
226 
227 #define SER_FORWARD_AS_ONE(...) __VA_ARGS__
228 
229 #define ImplementSerializable(...) \
230  \
231 public: \
232  ImplementSerializableDefaultConstructor(SER_FORWARD_AS_ONE(__VA_ARGS__), #__VA_ARGS__)
233 
235 {
236 public:
237  virtual serializable_base* build() const = 0;
238 
239  virtual ~serializable_builder() {}
240 
241  virtual const char* name() const = 0;
242 
243  virtual uint32_t cls_id() const = 0;
244 
245  virtual bool sanity(serializable_base* ser) = 0;
246 };
247 
248 template <class T>
250 {
251 protected:
252  static const char* name_;
253  static const uint32_t cls_id_;
254 
255 public:
256  serializable_base* build() const override { return T::construct_deserialize_stub(); }
257 
258  const char* name() const override { return name_; }
259 
260  uint32_t cls_id() const override { return cls_id_; }
261 
262  static uint32_t static_cls_id() { return cls_id_; }
263 
264  static const char* static_name() { return name_; }
265 
266  bool sanity(serializable_base* ser) override { return (typeid(T) == typeid(*ser)); }
267 };
268 
270 {
271 protected:
272  using builder_map = std::unordered_map<long, serializable_builder*>;
273  static builder_map* builders_;
274 
275 public:
276  static serializable_base* get_serializable(uint32_t cls_id);
277 
278  /**
279  @return The cls id for the given builder
280  */
281  static uint32_t
282  // add_builder(serializable_builder* builder, uint32_t cls_id);
283  add_builder(serializable_builder* builder, const char* name);
284 
285  static bool sanity(serializable_base* ser, uint32_t cls_id) { return (*builders_)[cls_id]->sanity(ser); }
286 
287  static void delete_statics();
288 };
289 
290 template <class T>
291 const char* serializable_builder_impl<T>::name_ = typeid(T).name();
292 template <class T>
295 
296 // Hold off on trivially_serializable for now, as it's not really safe
297 // in the case of inheritance
298 //
299 // class trivially_serializable {
300 // };
301 
302 } // namespace SST::Core::Serialization
303 
304 #define SerializableName(obj) #obj
305 
306 #define DeclareSerializable(obj)
307 
308 // #include "sst/core/serialization/serialize_serializable_base.h"
309 
310 #endif
This class is basically a wrapper for objects to declare the order in which their members should be s...
Definition: serializer.h:42
Definition: serializable_base.h:249
Definition: serializable_base.h:119
Definition: serializable_base.h:234
static uint32_t add_builder(serializable_builder *builder, const char *name)
Definition: serializable_base.cc:37
Definition: serializable_base.h:269
Definition: serializable_base.h:141