23 for (
const auto* child = firstChild; child; child = child->nextSibling) {
24 if (child->name == childName) {
39 for (
const auto* current = hint; current; current = current->nextSibling) {
40 if (current->name == childName) {
41 hint = current->nextSibling;
45 for (
const auto* current = firstChild; current != hint; current = current->nextSibling) {
46 if (current->name == childName) {
47 hint = current->nextSibling;
57 if (
const auto* elem =
findChild(childName)) {
71 std::string_view childName, std::string_view defaultValue)
const
74 return child ? child->getData() : defaultValue;
86 if (!child)
return defaultValue;
87 return StringOp::stringTo<int>(child->getData()).value_or(defaultValue);
98 for (
const auto* attr = firstAttribute; attr; attr = attr->nextAttribute) {
99 if (attr->getName() == attrName) {
122 std::string_view defaultValue)
const
125 return attr ? attr->getValue() : defaultValue;
130 bool defaultValue)
const
137 int defaultValue)
const
140 if (!attr)
return defaultValue;
141 return StringOp::stringTo<int>(attr->getValue()).value_or(defaultValue);
148 for (
auto** attr = &firstAttribute; *attr; attr = &(*attr)->nextAttribute) {
149 if ((*attr)->getName() == attrName) {
159 auto* attr = *attrPtr;
160 *attrPtr = attr->nextAttribute;
173 auto** elem = &parent.firstChild;
177 n->setData(childData);
181 if ((*elem)->getName() == childName) {
184 elem = &(*elem)->nextSibling;
192 auto** elem = &parent.firstChild;
197 (*elem)->setData(childData);
200 if ((*elem)->getName() == childName) {
201 (*elem)->setData(childData);
204 elem = &(*elem)->nextSibling;
212 auto** attr = &elem.firstAttribute;
219 if ((*attr)->getName() == attrName) {
220 (*attr)->setValue(attrValue);
223 attr = &(*attr)->nextAttribute;
234 , nextElement(&doc.root) {}
236 [[nodiscard]] std::string_view
getSystemID()
const {
return systemID; }
239 stack.push_back(currentElement);
244 assert(*nextElement ==
nullptr);
246 nextElement = &n->firstChild;
248 nextAttribute = &n->firstAttribute;
252 nextElement = ¤tElement->nextSibling;
253 nextAttribute =
nullptr;
254 currentElement = stack.back();
259 currentElement->data =
text.data();
262 void attribute(std::string_view name, std::string_view value) {
265 assert(nextAttribute);
266 assert(*nextAttribute ==
nullptr);
268 nextAttribute = &a->nextAttribute;
272 auto pos1 = txt.find(
" SYSTEM ");
273 if (pos1 == std::string_view::npos)
return;
274 if ((pos1 + 8) >= txt.size())
return;
275 char q = txt[pos1 + 8];
276 if (q !=
one_of(
'"',
'\''))
return;
277 auto t = txt.substr(pos1 + 9);
278 auto pos2 =
t.find(q);
279 if (pos2 == std::string_view::npos)
return;
281 systemID =
t.substr(0, pos2);
287 std::string_view systemID;
288 std::vector<XMLElement*> stack;
314 auto* p =
static_cast<char*
>(allocator.
allocate(str.size() + 1,
alignof(
char)));
328 file.
read(std::span{buf.
data(), size});
331 throw XMLException(filename,
": failed to read: ", e.getMessage());
336 rapidsax::parse<rapidsax::zeroTerminateStrings>(handler, buf.
data());
338 throw XMLException(filename,
": Document parsing failed: ", e.what());
342 ": Document doesn't contain mandatory root Element");
346 "You're probably using an old incompatible file format.");
349 throw XMLException(filename,
": systemID doesn't match "
350 "(expected ", systemID,
", got ", handler.
getSystemID(),
")\n"
351 "You're probably using an old incompatible file format.");
358 if (name.empty())
return nullptr;
361 unsigned numAttrs; ar.
load(numAttrs);
362 auto** attrPtr = &elem->firstAttribute;
368 attrPtr = &attr->nextAttribute;
371 unsigned numElems; ar.
load(numElems);
373 auto** elemPtr = &elem->firstChild;
375 auto* n = loadElement(ar);
377 elemPtr = &n->nextSibling;
391 root = loadElement(ar);
399 for (
const auto& attr : elem.getAttributes()) {
400 ar.
save(attr.getName());
401 ar.
save(attr.getValue());
407 for (
const auto& child : elem.getChildren()) {
408 saveElement(ar, child);
418 saveElement(ar, *root);
420 std::string_view empty;
429 auto** attrPtr = &outElem->firstAttribute;
430 for (
const auto& inAttr : inElem.getAttributes()) {
435 attrPtr = &outAttr->nextAttribute;
438 if (
auto data = inElem.
getData() ; !data.empty()) {
442 auto** childPtr = &outElem->firstChild;
443 for (
const auto& inChild : inElem.getChildren()) {
444 auto* outChild = clone(inChild);
445 *childPtr = outChild;
446 childPtr = &outChild->nextSibling;
456 assert(elem->nextSibling ==
nullptr);
464 for (const auto& attr : elem.getAttributes()) {
465 stream.attribute(attr.getName(), attr.getValue());
468 for (const auto& child : elem.getChildren()) {
469 saveElement(stream, child);
481 saveElement(stream, *root);
487 auto* outElem = allocateElement(allocateString(inElem.
name));
489 auto** attrPtr = &outElem->firstAttribute;
490 for (
const auto& [inName, inValue] : inElem.attributes) {
491 const char* n = allocateString(inName);
492 const char* v = allocateString(inValue);
493 auto* outAttr = allocateAttribute(n, v);
495 attrPtr = &outAttr->nextAttribute;
498 if (!inElem.
data.empty()) {
499 outElem->setData(allocateString(inElem.
data));
502 auto** childPtr = &outElem->firstChild;
503 for (
const auto& inChild : inElem.children) {
504 auto* outChild = clone(inChild);
505 *childPtr = outChild;
506 childPtr = &outChild->nextSibling;
518static std::unique_ptr<FileContext> lastSerializedFileContext;
519std::unique_ptr<FileContext> OldXMLElement::getLastSerializedFileContext()
521 return std::move(lastSerializedFileContext);
535template<
typename Archive>
536void OldXMLElement::serialize(Archive& ar,
unsigned version)
538 assert(Archive::IS_LOADER);
539 ar.serialize(
"name", name,
541 "attributes", attributes,
542 "children", children);
544 if (ar.versionBelow(version, 2)) {
545 std::unique_ptr<FileContext> context;
546 ar.serialize(
"context", context);
548 lastSerializedFileContext = std::move(context);
'XMLOutputStream' is a helper to write an XML file in a streaming way.
void with_tag(std::string_view tag, std::invocable auto next)
void data(std::string_view value)
void * allocate(size_t bytes, size_t alignment)
void read(std::span< uint8_t > buffer)
Read from file.
size_t getSize()
Returns the size of this file.
void resize(size_t size)
Grow or shrink the memory block.
const T * data() const
Returns pointer to the start of the memory buffer.
std::string_view getValue() const
void attribute(std::string_view name, std::string_view value)
void doctype(std::string_view txt)
void start(std::string_view name)
XMLDocumentHandler(XMLDocument &doc_)
std::string_view getSystemID() const
void text(std::string_view text)
XMLElement * setChildData(XMLElement &parent, const char *childName, const char *childData)
void serialize(MemInputArchive &ar, unsigned version)
XMLElement * getOrCreateChild(XMLElement &parent, const char *childName, const char *childData)
void setAttribute(XMLElement &elem, const char *attrName, const char *attrValue)
const char * allocateString(std::string_view str)
XMLElement * allocateElement(const char *name)
XMLAttribute * allocateAttribute(const char *name, const char *value)
void load(const std::string &filename, std::string_view systemID)
std::string_view getName() const
size_t numChildren() const
XMLAttribute ** findAttributePointer(std::string_view attrName)
int getChildDataAsInt(std::string_view childName, int defaultValue) const
AttributeRange getAttributes() const
const XMLAttribute * findAttribute(std::string_view attrName) const
const XMLElement * findChild(std::string_view childName) const
static void removeAttribute(XMLAttribute **attrPtr)
std::string_view getAttributeValue(std::string_view attrName) const
size_t numAttributes() const
int getAttributeValueAsInt(std::string_view attrName, int defaultValue) const
const XMLAttribute & getAttribute(std::string_view attrName) const
const XMLElement & getChild(std::string_view childName) const
std::string_view getChildData(std::string_view childName) const
std::string_view getData() const
bool getChildDataAsBool(std::string_view childName, bool defaultValue) const
bool getAttributeValueAsBool(std::string_view attrName, bool defaultValue) const
ChildRange getChildren() const
const XMLElement * getFirstChild() const
auto & getXMLOutputStream()
bool stringToBool(string_view str)
This file implemented 3 utility functions:
constexpr auto copy(InputRange &&range, OutputIter out)
constexpr size_t EXTRA_BUFFER_SPACE
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
constexpr void repeat(T n, Op op)
Repeat the given operation 'op' 'n' times.
constexpr auto begin(const zstring_view &x)
constexpr auto end(const zstring_view &x)