20 template<
typename Derived>
23 string valueStr(value);
24 self().attribute(name, valueStr);
36 unsigned OutputArchiveBase2::generateID1(
const void* p)
39 assert(
"Can't serialize ID of object located on the stack" &&
43 assert(polyIdMap.find(p) == polyIdMap.end());
44 polyIdMap[p] = lastId;
47 unsigned OutputArchiveBase2::generateID2(
48 const void* p,
const std::type_info& typeInfo)
51 assert(
"Can't serialize ID of object located on the stack" &&
55 auto key = std::make_pair(p,
TypeInfo(typeInfo));
56 assert(idMap.find(key) == idMap.end());
61 unsigned OutputArchiveBase2::getID1(
const void* p)
63 auto it = polyIdMap.find(p);
64 return it != polyIdMap.end() ? it->second : 0;
66 unsigned OutputArchiveBase2::getID2(
67 const void* p,
const std::type_info& typeInfo)
69 auto key = std::make_pair(p,
TypeInfo(typeInfo));
70 auto it = idMap.find(key);
71 return it != idMap.end() ? it->second : 0;
75 template<
typename Derived>
77 const char* tag,
const void* data,
size_t len)
84 tmp = HexDump::encode(data, len);
87 tmp = Base64::encode(data, len);
89 encoding =
"gz-base64";
91 auto dstLen = uLongf(len + len / 1000 + 12 + 1);
93 if (compress2(buf.
data(), &dstLen,
94 reinterpret_cast<const Bytef*
>(data),
99 tmp = Base64::encode(buf.
data(), dstLen);
101 this->
self().beginTag(tag);
102 this->
self().attribute(
"encoding", encoding);
104 saver(this->
self(), tmp,
false);
105 this->
self().endTag(tag);
115 auto it = idMap.find(
id);
116 return it != idMap.end() ? it->second :
nullptr;
121 assert(idMap.find(
id) == idMap.end());
122 idMap[id] =
const_cast<void*
>(p);
125 template<
typename Derived>
127 const char* tag,
void* data,
size_t len)
129 this->
self().beginTag(tag);
131 this->
self().attribute(
"encoding", encoding);
135 loader(this->
self(), tmp, std::make_tuple(), -1);
136 this->
self().endTag(tag);
138 if (encoding ==
"gz-base64") {
139 tmp = Base64::decode(tmp);
140 auto dstLen = uLongf(len);
141 if ((
uncompress(reinterpret_cast<Bytef*>(data), &dstLen,
142 reinterpret_cast<const Bytef*>(tmp.data()), uLong(tmp.size()))
147 }
else if ((encoding ==
"hex") || (encoding ==
"base64")) {
148 if (encoding ==
"hex") {
149 tmp = HexDump::decode(tmp);
151 tmp = Base64::decode(tmp);
153 if (tmp.size() != len) {
155 <<
"Length of decoded blob: " << tmp.size()
156 <<
" not identical to expected value: " << len);
158 memcpy(data, tmp.data(), len);
160 throw XMLException(
"Unsupported encoding \"" + encoding +
"\" for blob");
171 auto size = s.size();
174 memcpy(buf +
sizeof(
size), s.data(),
size);
203 static const size_t SMALL_SIZE = 100;
219 if (len >= SMALL_SIZE) {
223 reinterpret_cast<char*>(&buf[
sizeof(dstLen)]), dstLen);
224 memcpy(buf, &dstLen,
sizeof(dstLen));
225 buffer.
deallocate(&buf[
sizeof(dstLen) + dstLen]);
228 memcpy(buf, data, len);
235 if (len >= SMALL_SIZE) {
236 size_t srcLen;
load(srcLen);
238 srcLen, reinterpret_cast<char*>(data), len);
253 throw XMLException(
"Could not open compressed file \"" + filename +
"\"");
255 file = gzdopen(fileno(f),
"wb9");
258 throw XMLException(
"Could not open compressed file \"" + filename +
"\"");
260 current.push_back(&root);
265 assert(current.back() == &root);
267 "<?xml version=\"1.0\" ?>\n"
268 "<!DOCTYPE openmsx-serialize SYSTEM 'openmsx-serialize.dtd'>\n";
269 gzwrite(file, const_cast<char*>(header),
unsigned(strlen(header)));
270 string dump = root.
dump();
271 gzwrite(file, const_cast<char*>(dump.data()),
unsigned(dump.size()));
281 assert(!current.empty());
282 assert(current.back()->getData().empty());
283 current.back()->setData(str);
287 assert(!current.empty());
288 assert(current.back()->getData().empty());
289 current.back()->setData(b ?
"true" :
"false");
318 assert(!current.empty());
319 assert(!current.back()->hasAttribute(name));
320 current.back()->addAttribute(name, str);
333 assert(!current.empty());
334 auto& elem = current.back()->addChild(
XMLElement(tag));
335 current.push_back(&elem);
339 assert(!current.empty());
340 assert(current.back()->getName() == tag); (void)tag;
347 : elem(XMLLoader::
load(filename,
"openmsx-serialize.dtd"))
349 elems.push_back(std::make_pair(&elem, 0));
356 std::istringstream is(str);
361 if (!elems.back().first->getChildren().empty()) {
362 throw XMLException(
"No child tags expected for string types");
364 t = elems.back().first->getData();
368 if (!elems.back().first->getChildren().empty()) {
369 throw XMLException(
"No child tags expected for boolean types");
371 const auto& s = elems.back().first->getData();
372 if ((s ==
"true") || (s ==
"1")) {
374 }
else if ((s ==
"false") || (s ==
"0")) {
377 throw XMLException(
"Bad value found for boolean: " + s);
412 template<
bool IS_SIGNED>
struct ConditionalNegate;
413 template<>
struct ConditionalNegate<true> {
418 template<>
struct ConditionalNegate<false> {
420 assert(!negate); (void)negate;
423 template<
typename T>
static inline void fastAtoi(
const string& str, T& t)
428 size_t l = str.size();
430 static const bool IS_SIGNED = std::numeric_limits<T>::is_signed;
439 unsigned d = str[i] -
'0';
441 throw XMLException(
"Invalid integer: " + str);
449 ConditionalNegate<IS_SIGNED> negateFunctor;
450 negateFunctor(neg, t);
473 auto* child = elems.back().first->findNextChild(
474 tag, elems.back().second);
477 for (
auto& e : elems) {
478 path += e.first->getName() +
'/';
481 "No child tag \"" << tag <<
482 "\" found at location \"" << path <<
'\"');
484 elems.push_back(std::make_pair(child, 0));
488 const auto& elem = *elems.back().first;
491 "\" not equal to begin tag \"" + tag +
"\"");
501 t = elems.back().first->getAttribute(name);
516 return elems.back().first->hasAttribute(name);
520 return elems.back().first->findAttributeInt(name, value);
524 return int(elems.back().first->getChildren().size());