openMSX
serialize_meta.cc
Go to the documentation of this file.
1 #include "serialize_meta.hh"
2 #include "serialize.hh"
3 #include "MSXException.hh"
4 #include "ranges.hh"
5 #include "stl.hh"
6 #include <cassert>
7 #include <iostream>
8 
9 namespace openmsx {
10 
11 template<typename Archive>
13 {
14  static PolymorphicSaverRegistry oneInstance;
15  return oneInstance;
16 }
17 
18 template<typename Archive>
20  const std::type_info& type,
21  std::unique_ptr<PolymorphicSaverBase<Archive>> saver)
22 {
23  assert(!initialized);
24  assert(ranges::none_of(saverMap, EqualTupleValue<0>(type)));
25  saverMap.emplace_back(type, std::move(saver));
26 }
27 
28 template<typename Archive>
30  Archive& ar, const void* t, const std::type_info& typeInfo)
31 {
33  if (unlikely(!reg.initialized)) {
34  reg.initialized = true;
35  ranges::sort(reg.saverMap, LessTupleElement<0>());
36  }
37  auto it = ranges::lower_bound(reg.saverMap, typeInfo, LessTupleElement<0>());
38  if ((it == end(reg.saverMap)) || (it->first != typeInfo)) {
39  std::cerr << "Trying to save an unregistered polymorphic type: "
40  << typeInfo.name() << '\n';
41  assert(false); return;
42  }
43  it->second->save(ar, t);
44 }
45 template<typename Archive>
47  const char* tag, Archive& ar, const void* t, const std::type_info& typeInfo)
48 {
49  ar.beginTag(tag);
50  save(ar, t, typeInfo);
51  ar.endTag(tag);
52 }
53 
56 
58 
59 template<typename Archive>
61 {
62  static PolymorphicLoaderRegistry oneInstance;
63  return oneInstance;
64 }
65 
66 template<typename Archive>
68  const char* name,
69  std::unique_ptr<PolymorphicLoaderBase<Archive>> loader)
70 {
71  assert(!loaderMap.contains(name));
72  loaderMap.emplace_noDuplicateCheck(name, std::move(loader));
73 }
74 
75 template<typename Archive>
77  Archive& ar, unsigned id, const void* args)
78 {
79  std::string type;
80  ar.attribute("type", type);
82  auto v = lookup(reg.loaderMap, type);
83  assert(v);
84  return (*v)->load(ar, id, args);
85 }
86 
89 
91 
92 void polyInitError(const char* expected, const char* actual)
93 {
94  throw MSXException("Expected type: ", expected, " but got: ", actual, '.');
95 }
96 
97 template<typename Archive>
99 {
100  static PolymorphicInitializerRegistry oneInstance;
101  return oneInstance;
102 }
103 
104 template<typename Archive>
106  const char* name,
107  std::unique_ptr<PolymorphicInitializerBase<Archive>> initializer)
108 {
109  assert(!initializerMap.contains(name));
110  initializerMap.emplace_noDuplicateCheck(name, std::move(initializer));
111 }
112 
113 template<typename Archive>
115  const char* tag, Archive& ar, void* t)
116 {
117  ar.beginTag(tag);
118  unsigned id;
119  ar.attribute("id", id);
120  assert(id);
121  std::string type;
122  ar.attribute("type", type);
123 
125  auto v = lookup(reg.initializerMap, type);
126  assert(v);
127  (*v)->init(ar, t, id);
128 
129  ar.endTag(tag);
130 }
131 
134 
135 } // namespace openmsx
void polyInitError(const char *expected, const char *actual)
#define unlikely(x)
Definition: likely.hh:15
static PolymorphicInitializerRegistry & instance()
const Value * lookup(const hash_map< Key, Value, Hasher, Equal > &map, const Key2 &key)
Definition: hash_map.hh:91
static PolymorphicLoaderRegistry & instance()
bool none_of(InputRange &&range, UnaryPredicate pred)
Definition: ranges.hh:131
static PolymorphicSaverRegistry & instance()
static void * load(Archive &ar, unsigned id, const void *args)
void sort(RandomAccessRange &&range)
Definition: ranges.hh:35
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
auto lower_bound(ForwardRange &&range, const T &value)
Definition: ranges.hh:71
TclObject t
auto end(const string_view &x)
Definition: string_view.hh:152
static void init(const char *tag, Archive &ar, void *t)
static void save(Archive &ar, T *t)