22 using std::string_view;
26 template<
typename Derived>
29 string valueStr(value);
30 self().attribute(name, valueStr);
37 unsigned OutputArchiveBase2::generateID1(
const void* p)
40 assert(
"Can't serialize ID of object located on the stack" &&
48 unsigned OutputArchiveBase2::generateID2(
49 const void* p,
const std::type_info& typeInfo)
52 assert(
"Can't serialize ID of object located on the stack" &&
56 auto key = std::pair(p, std::type_index(typeInfo));
57 assert(!idMap.contains(key));
58 idMap.emplace_noDuplicateCheck(key, lastId);
62 unsigned OutputArchiveBase2::getID1(
const void* p)
64 auto* v =
lookup(polyIdMap, p);
67 unsigned OutputArchiveBase2::getID2(
68 const void* p,
const std::type_info& typeInfo)
70 auto* v =
lookup(idMap, std::pair(p, std::type_index(typeInfo)));
75 template<
typename Derived>
77 const char* tag,
const void* data_,
size_t len,
bool )
79 const auto* data =
static_cast<const uint8_t*
>(data_);
86 tmp = HexDump::encode(data, len);
89 tmp = Base64::encode(data, len);
91 encoding =
"gz-base64";
93 auto dstLen = uLongf(len + len / 1000 + 12 + 1);
95 if (compress2(buf.
data(), &dstLen,
96 reinterpret_cast<const Bytef*
>(data),
101 tmp = Base64::encode(buf.
data(), dstLen);
103 this->
self().beginTag(tag);
104 this->
self().attribute(
"encoding", encoding);
106 saver(this->
self(), tmp,
false);
107 this->
self().endTag(tag);
117 auto* v =
lookup(idMap,
id);
118 return v ? *v :
nullptr;
129 for (
const auto& [
id, pt] : idMap) {
130 if (pt == ptr)
return id;
135 template<
typename Derived>
137 const char* tag,
void* data,
size_t len,
bool )
139 this->
self().beginTag(tag);
141 this->
self().attribute(
"encoding", encoding);
143 string_view tmp = this->
self().loadStr();
144 this->
self().endTag(tag);
146 if (encoding ==
"gz-base64") {
147 auto [buf, bufSize] = Base64::decode(tmp);
148 auto dstLen = uLongf(len);
149 if ((uncompress(
reinterpret_cast<Bytef*
>(data), &dstLen,
150 reinterpret_cast<const Bytef*
>(buf.data()), uLong(bufSize))
155 }
else if (encoding ==
one_of(
"hex",
"base64")) {
156 bool ok = (encoding ==
"hex")
161 "Length of decoded blob different from "
162 "expected value (", len,
')');
165 throw XMLException(
"Unsupported encoding \"", encoding,
"\" for blob");
176 auto size = s.size();
179 memcpy(buf +
sizeof(
size), s.data(),
size);
205 return string_view(
reinterpret_cast<const char*
>(p),
length);
217 size_t len,
bool diff)
221 auto deltaBlockIdx = unsigned(deltaBlocks.size());
223 deltaBlocks.push_back(diff
225 data,
static_cast<const uint8_t*
>(data), len)
227 data,
static_cast<const uint8_t*
>(data), len));
229 uint8_t* buf = buffer.
allocate(len);
230 memcpy(buf, data, len);
247 unsigned deltaBlockIdx;
load(deltaBlockIdx);
248 deltaBlocks[deltaBlockIdx]->apply(
static_cast<uint8_t*
>(data), len);
266 int duped_fd = dup(fileno(f.get()));
267 if (duped_fd == -1)
goto error;
268 file = gzdopen(duped_fd,
"wb9");
273 current.push_back(&root);
287 assert(current.back() == &root);
289 "<?xml version=\"1.0\" ?>\n"
290 "<!DOCTYPE openmsx-serialize SYSTEM 'openmsx-serialize.dtd'>\n";
291 string dump = root.
dump();
292 if ((gzwrite(file,
const_cast<char*
>(header),
unsigned(strlen(header))) == 0) ||
293 (gzwrite(file,
const_cast<char*
>(dump.data()),
unsigned(dump.size())) == 0) ||
294 (gzclose(file) != Z_OK)) {
316 assert(!current.empty());
317 assert(current.back()->getData().empty());
318 current.back()->setData(str);
322 assert(!current.empty());
323 assert(current.back()->getData().empty());
324 current.back()->setData(std::string_view(b ?
"true" :
"false"));
353 assert(!current.empty());
354 assert(!current.back()->hasAttribute(name));
355 current.back()->addAttribute(name, std::move(str));
368 assert(!current.empty());
369 auto& elem = current.back()->addChild(tag);
370 current.push_back(&elem);
374 assert(!current.empty());
375 assert(current.back()->getName() == tag); (void)tag;
382 : rootElem(XMLLoader::
load(
filename,
"openmsx-serialize.dtd"))
384 elems.emplace_back(&rootElem, 0);
389 if (!elems.back().first->getChildren().empty()) {
390 throw XMLException(
"No child tags expected for primitive type");
392 return elems.back().first->getData();
402 std::istringstream is(str);
408 if (s ==
one_of(
"true",
"1")) {
410 }
else if (s ==
one_of(
"false",
"0")) {
438 assert(!negate); (void)negate;
441 template<
typename T>
static inline void fastAtoi(string_view str, T&
t)
446 size_t l = str.
size();
448 constexpr
bool IS_SIGNED = std::numeric_limits<T>::is_signed;
457 unsigned d = str[i] -
'0';
459 throw XMLException(
"Invalid integer: ", str);
468 negateFunctor(neg,
t);
506 const auto* child = elems.back().first->findNextChild(
507 tag, elems.back().second);
510 for (
auto& e : elems) {
511 strAppend(path, e.first->getName(),
'/');
514 "\" found at location \"", path,
'\"');
516 elems.emplace_back(child, 0);
520 const auto& elem = *elems.back().first;
521 if (elem.getName() != tag) {
523 "\" not equal to begin tag \"", tag,
"\"");
533 t = elems.back().first->getAttribute(name);
548 return elems.back().first->hasAttribute(name);
552 return elems.back().first->findAttributeInt(name, value);
556 return int(elems.back().first->getChildren().size());
bool contains(const K &k) const
iterator emplace_noDuplicateCheck(Args &&... args)
void attribute(const char *name, T &t)
Load/store an attribute from/in the archive.
std::shared_ptr< DeltaBlock > createNullDiff(const void *id, const uint8_t *data, size_t size)
std::shared_ptr< DeltaBlock > createNew(const void *id, const uint8_t *data, size_t size)
const T * data() const
Returns pointer to the start of the memory buffer.
MemBuffer< uint8_t > releaseBuffer(size_t &size)
void serialize_blob(const char *tag, const void *data, size_t len, bool diff=true)
void serialize_blob(const char *tag, const void *data, size_t len, bool diff=true)
uint8_t * allocate(size_t len)
Reserve space to insert the given number of bytes.
MemBuffer< uint8_t > release(size_t &size)
Release ownership of the buffer.
static std::string full()
void addAttribute(String1 &&attrName, String2 &&value)
void saveImpl(const T &t)
XmlOutputArchive(zstring_view filename)
void attributeImpl(const char *name, const T &t)
void endTag(const char *tag)
void beginTag(const char *tag)
void attribute(const char *name, const T &t)
Like std::string_view, but with the extra guarantee that it refers to a zero-terminated string.
const Value * lookup(const hash_map< Key, Value, Hasher, Equal > &map, const Key2 &key)
bool decode_inplace(std::string_view input, uint8_t *output, size_t outSize)
bool decode_inplace(std::string_view input, uint8_t *output, size_t outSize)
T length(const vecN< N, T > &x)
std::string toString(time_t time)
FILE_t openFile(zstring_view filename, zstring_view mode)
Call fopen() in a platform-independent manner.
XMLElement load(const string &filename, string_view systemID)
This file implemented 3 utility functions:
constexpr size_t SMALL_SIZE
constexpr const char *const filename
size_t size(std::string_view utf8)
void strAppend(std::string &result, Ts &&...ts)
void operator()(bool negate, T &)
void operator()(bool negate, T &t)