OXYGENHUB
◆ main openmsx / src / serialize_meta.cc
3.6 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#include "serialize_meta.hh"
2
3
#include "MSXException.hh"
4
#include "serialize.hh"
5
6
#include "ranges.hh"
7
#include "stl.hh"
8
9
#include <algorithm>
10
#include <cassert>
11
#include <iostream>
12
13
namespace openmsx {
14
15
template<typename Archive>
16
PolymorphicSaverRegistry<Archive>& PolymorphicSaverRegistry<Archive>::instance()
17
{
18
	static PolymorphicSaverRegistry oneInstance;
19
	return oneInstance;
20
}
21
22
template<typename Archive>
23
void PolymorphicSaverRegistry<Archive>::registerHelper(
24
	const std::type_info& type, SaveFunction saver)
25
{
26
	assert(!initialized);
27
	assert(!contains(saverMap, type, &Entry::index)); // not yet sorted
28
	saverMap.emplace_back(type, std::move(saver));
29
}
30
31
template<typename Archive>
32
void PolymorphicSaverRegistry<Archive>::save(
33
	Archive& ar, const void* t, const std::type_info& typeInfo)
34
{
35
	auto& reg = PolymorphicSaverRegistry<Archive>::instance();
36
	if (!reg.initialized) [[unlikely]] {
37
		reg.initialized = true;
38
		std::ranges::sort(reg.saverMap, {}, &Entry::index);
39
	}
40
	auto s = binary_find(reg.saverMap, std::type_index(typeInfo), {}, &Entry::index);
41
	if (!s) {
42
		std::cerr << "Trying to save an unregistered polymorphic type: "
43
			  << typeInfo.name() << '\n';
44
		assert(false); return;
45
	}
46
	s->saver(ar, t);
47
}
48
template<typename Archive>
49
void PolymorphicSaverRegistry<Archive>::save(
50
	const char* tag, Archive& ar, const void* t, const std::type_info& typeInfo)
51
{
52
	ar.beginTag(tag);
53
	save(ar, t, typeInfo);
54
	ar.endTag(tag);
55
}
56
57
template class PolymorphicSaverRegistry<MemOutputArchive>;
58
template class PolymorphicSaverRegistry<XmlOutputArchive>;
59
60
////
61
62
template<typename Archive>
63
PolymorphicLoaderRegistry<Archive>& PolymorphicLoaderRegistry<Archive>::instance()
64
{
65
	static PolymorphicLoaderRegistry oneInstance;
66
	return oneInstance;
67
}
68
69
template<typename Archive>
70
void PolymorphicLoaderRegistry<Archive>::registerHelper(
71
	const char* name, LoadFunction loader)
72
{
73
	assert(!loaderMap.contains(name));
74
	loaderMap.emplace_noDuplicateCheck(name, std::move(loader));
75
}
76
77
template<typename Archive>
78
void* PolymorphicLoaderRegistry<Archive>::load(
79
	Archive& ar, unsigned id, const void* args)
80
{
81
	std::string type;
82
	ar.attribute("type", type);
83
	auto& reg = PolymorphicLoaderRegistry<Archive>::instance();
84
	auto* v = lookup(reg.loaderMap, type);
85
	if (!v) {
86
		throw MSXException("Deserialize unknown polymorphic type: '", type, "'.");
87
	}
88
	return (*v)(ar, id, args);
89
}
90
91
template class PolymorphicLoaderRegistry<MemInputArchive>;
92
template class PolymorphicLoaderRegistry<XmlInputArchive>;
93
94
////
95
96
void polyInitError(const char* expected, const char* actual)
97
{
98
	throw MSXException("Expected type: ", expected, " but got: ", actual, '.');
99
}
100
101
template<typename Archive>
102
PolymorphicInitializerRegistry<Archive>& PolymorphicInitializerRegistry<Archive>::instance()
103
{
104
	static PolymorphicInitializerRegistry oneInstance;
105
	return oneInstance;
106
}
107
108
template<typename Archive>
109
void PolymorphicInitializerRegistry<Archive>::registerHelper(
110
	const char* name, InitFunction initializer)
111
{
112
	assert(!initializerMap.contains(name));
113
	initializerMap.emplace_noDuplicateCheck(name, std::move(initializer));
114
}
115
116
template<typename Archive>
117
void PolymorphicInitializerRegistry<Archive>::init(
118
	const char* tag, Archive& ar, void* t)
119
{
120
	ar.beginTag(tag);
121
	unsigned id;
122
	ar.attribute("id", id);
123
	assert(id);
124
	std::string type;
125
	ar.attribute("type", type);
126
127
	auto& reg = PolymorphicInitializerRegistry<Archive>::instance();
128
	auto v = lookup(reg.initializerMap, type);
129
	if (!v) {
130
		throw MSXException("Deserialize unknown polymorphic type: '", type, "'.");
131
	}
132
	(*v)(ar, t, id);
133
134
	ar.endTag(tag);
135
}
136
137
template class PolymorphicInitializerRegistry<MemInputArchive>;
138
template class PolymorphicInitializerRegistry<XmlInputArchive>;
139
140
} // namespace openmsx