Update pugiXML library

Release highlights:

xml_attribute::set_value, xml_node::set_value and xml_text::set now have overloads that accept pointer to non-null-terminated string and size
Fix error handling in xml_document::save_file that could result in the function succeeding while running out of disk space
Fix memory leak during error handling of some out-of-memory conditions during xml_document::load
pull/5125/head
mosfet80 2023-06-03 11:16:39 +02:00
parent d9a8837a5b
commit 62cefd5b27
3 changed files with 224 additions and 90 deletions

View File

@ -1,5 +1,5 @@
/** /**
* pugixml parser - version 1.12 * pugixml parser - version 1.13
* -------------------------------------------------------- * --------------------------------------------------------
* Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
* Report bugs and download new versions at https://pugixml.org/ * Report bugs and download new versions at https://pugixml.org/

View File

@ -1,5 +1,5 @@
/** /**
* pugixml parser - version 1.12 * pugixml parser - version 1.13
* -------------------------------------------------------- * --------------------------------------------------------
* Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
* Report bugs and download new versions at https://pugixml.org/ * Report bugs and download new versions at https://pugixml.org/
@ -1276,12 +1276,14 @@ PUGI__NS_BEGIN
child->parent = parent; child->parent = parent;
if (node->next_sibling) xml_node_struct* next = node->next_sibling;
node->next_sibling->prev_sibling_c = child;
if (next)
next->prev_sibling_c = child;
else else
parent->first_child->prev_sibling_c = child; parent->first_child->prev_sibling_c = child;
child->next_sibling = node->next_sibling; child->next_sibling = next;
child->prev_sibling_c = node; child->prev_sibling_c = node;
node->next_sibling = child; node->next_sibling = child;
@ -1293,12 +1295,14 @@ PUGI__NS_BEGIN
child->parent = parent; child->parent = parent;
if (node->prev_sibling_c->next_sibling) xml_node_struct* prev = node->prev_sibling_c;
node->prev_sibling_c->next_sibling = child;
if (prev->next_sibling)
prev->next_sibling = child;
else else
parent->first_child = child; parent->first_child = child;
child->prev_sibling_c = node->prev_sibling_c; child->prev_sibling_c = prev;
child->next_sibling = node; child->next_sibling = node;
node->prev_sibling_c = child; node->prev_sibling_c = child;
@ -1308,15 +1312,18 @@ PUGI__NS_BEGIN
{ {
xml_node_struct* parent = node->parent; xml_node_struct* parent = node->parent;
if (node->next_sibling) xml_node_struct* next = node->next_sibling;
node->next_sibling->prev_sibling_c = node->prev_sibling_c; xml_node_struct* prev = node->prev_sibling_c;
else
parent->first_child->prev_sibling_c = node->prev_sibling_c;
if (node->prev_sibling_c->next_sibling) if (next)
node->prev_sibling_c->next_sibling = node->next_sibling; next->prev_sibling_c = prev;
else else
parent->first_child = node->next_sibling; parent->first_child->prev_sibling_c = prev;
if (prev->next_sibling)
prev->next_sibling = next;
else
parent->first_child = next;
node->parent = 0; node->parent = 0;
node->prev_sibling_c = 0; node->prev_sibling_c = 0;
@ -1360,39 +1367,46 @@ PUGI__NS_BEGIN
inline void insert_attribute_after(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node) inline void insert_attribute_after(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node)
{ {
if (place->next_attribute) xml_attribute_struct* next = place->next_attribute;
place->next_attribute->prev_attribute_c = attr;
if (next)
next->prev_attribute_c = attr;
else else
node->first_attribute->prev_attribute_c = attr; node->first_attribute->prev_attribute_c = attr;
attr->next_attribute = place->next_attribute; attr->next_attribute = next;
attr->prev_attribute_c = place; attr->prev_attribute_c = place;
place->next_attribute = attr; place->next_attribute = attr;
} }
inline void insert_attribute_before(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node) inline void insert_attribute_before(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node)
{ {
if (place->prev_attribute_c->next_attribute) xml_attribute_struct* prev = place->prev_attribute_c;
place->prev_attribute_c->next_attribute = attr;
if (prev->next_attribute)
prev->next_attribute = attr;
else else
node->first_attribute = attr; node->first_attribute = attr;
attr->prev_attribute_c = place->prev_attribute_c; attr->prev_attribute_c = prev;
attr->next_attribute = place; attr->next_attribute = place;
place->prev_attribute_c = attr; place->prev_attribute_c = attr;
} }
inline void remove_attribute(xml_attribute_struct* attr, xml_node_struct* node) inline void remove_attribute(xml_attribute_struct* attr, xml_node_struct* node)
{ {
if (attr->next_attribute) xml_attribute_struct* next = attr->next_attribute;
attr->next_attribute->prev_attribute_c = attr->prev_attribute_c; xml_attribute_struct* prev = attr->prev_attribute_c;
else
node->first_attribute->prev_attribute_c = attr->prev_attribute_c;
if (attr->prev_attribute_c->next_attribute) if (next)
attr->prev_attribute_c->next_attribute = attr->next_attribute; next->prev_attribute_c = prev;
else else
node->first_attribute = attr->next_attribute; node->first_attribute->prev_attribute_c = prev;
if (prev->next_attribute)
prev->next_attribute = next;
else
node->first_attribute = next;
attr->prev_attribute_c = 0; attr->prev_attribute_c = 0;
attr->next_attribute = 0; attr->next_attribute = 0;
@ -4707,6 +4721,9 @@ PUGI__NS_BEGIN
// get actual encoding // get actual encoding
xml_encoding buffer_encoding = impl::get_buffer_encoding(encoding, contents, size); xml_encoding buffer_encoding = impl::get_buffer_encoding(encoding, contents, size);
// if convert_buffer below throws bad_alloc, we still need to deallocate contents if we own it
auto_deleter<void> contents_guard(own ? contents : 0, xml_memory::deallocate);
// get private buffer // get private buffer
char_t* buffer = 0; char_t* buffer = 0;
size_t length = 0; size_t length = 0;
@ -4714,6 +4731,9 @@ PUGI__NS_BEGIN
// coverity[var_deref_model] // coverity[var_deref_model]
if (!impl::convert_buffer(buffer, length, buffer_encoding, contents, size, is_mutable)) return impl::make_parse_result(status_out_of_memory); if (!impl::convert_buffer(buffer, length, buffer_encoding, contents, size, is_mutable)) return impl::make_parse_result(status_out_of_memory);
// after this we either deallocate contents (below) or hold on to it via doc->buffer, so we don't need to guard it
contents_guard.release();
// delete original buffer if we performed a conversion // delete original buffer if we performed a conversion
if (own && buffer != contents && contents) impl::xml_memory::deallocate(contents); if (own && buffer != contents && contents) impl::xml_memory::deallocate(contents);
@ -5050,7 +5070,7 @@ PUGI__NS_BEGIN
xml_writer_file writer(file); xml_writer_file writer(file);
doc.save(writer, indent, flags, encoding); doc.save(writer, indent, flags, encoding);
return ferror(file) == 0; return fflush(file) == 0 && ferror(file) == 0;
} }
struct name_null_sentry struct name_null_sentry
@ -5185,53 +5205,72 @@ namespace pugi
PUGI__FN xml_attribute xml_attribute::next_attribute() const PUGI__FN xml_attribute xml_attribute::next_attribute() const
{ {
return _attr ? xml_attribute(_attr->next_attribute) : xml_attribute(); if (!_attr) return xml_attribute();
return xml_attribute(_attr->next_attribute);
} }
PUGI__FN xml_attribute xml_attribute::previous_attribute() const PUGI__FN xml_attribute xml_attribute::previous_attribute() const
{ {
return _attr && _attr->prev_attribute_c->next_attribute ? xml_attribute(_attr->prev_attribute_c) : xml_attribute(); if (!_attr) return xml_attribute();
xml_attribute_struct* prev = _attr->prev_attribute_c;
return prev->next_attribute ? xml_attribute(prev) : xml_attribute();
} }
PUGI__FN const char_t* xml_attribute::as_string(const char_t* def) const PUGI__FN const char_t* xml_attribute::as_string(const char_t* def) const
{ {
return (_attr && _attr->value) ? _attr->value + 0 : def; if (!_attr) return def;
const char_t* value = _attr->value;
return value ? value : def;
} }
PUGI__FN int xml_attribute::as_int(int def) const PUGI__FN int xml_attribute::as_int(int def) const
{ {
return (_attr && _attr->value) ? impl::get_value_int(_attr->value) : def; if (!_attr) return def;
const char_t* value = _attr->value;
return value ? impl::get_value_int(value) : def;
} }
PUGI__FN unsigned int xml_attribute::as_uint(unsigned int def) const PUGI__FN unsigned int xml_attribute::as_uint(unsigned int def) const
{ {
return (_attr && _attr->value) ? impl::get_value_uint(_attr->value) : def; if (!_attr) return def;
const char_t* value = _attr->value;
return value ? impl::get_value_uint(value) : def;
} }
PUGI__FN double xml_attribute::as_double(double def) const PUGI__FN double xml_attribute::as_double(double def) const
{ {
return (_attr && _attr->value) ? impl::get_value_double(_attr->value) : def; if (!_attr) return def;
const char_t* value = _attr->value;
return value ? impl::get_value_double(value) : def;
} }
PUGI__FN float xml_attribute::as_float(float def) const PUGI__FN float xml_attribute::as_float(float def) const
{ {
return (_attr && _attr->value) ? impl::get_value_float(_attr->value) : def; if (!_attr) return def;
const char_t* value = _attr->value;
return value ? impl::get_value_float(value) : def;
} }
PUGI__FN bool xml_attribute::as_bool(bool def) const PUGI__FN bool xml_attribute::as_bool(bool def) const
{ {
return (_attr && _attr->value) ? impl::get_value_bool(_attr->value) : def; if (!_attr) return def;
const char_t* value = _attr->value;
return value ? impl::get_value_bool(value) : def;
} }
#ifdef PUGIXML_HAS_LONG_LONG #ifdef PUGIXML_HAS_LONG_LONG
PUGI__FN long long xml_attribute::as_llong(long long def) const PUGI__FN long long xml_attribute::as_llong(long long def) const
{ {
return (_attr && _attr->value) ? impl::get_value_llong(_attr->value) : def; if (!_attr) return def;
const char_t* value = _attr->value;
return value ? impl::get_value_llong(value) : def;
} }
PUGI__FN unsigned long long xml_attribute::as_ullong(unsigned long long def) const PUGI__FN unsigned long long xml_attribute::as_ullong(unsigned long long def) const
{ {
return (_attr && _attr->value) ? impl::get_value_ullong(_attr->value) : def; if (!_attr) return def;
const char_t* value = _attr->value;
return value ? impl::get_value_ullong(value) : def;
} }
#endif #endif
@ -5242,12 +5281,16 @@ namespace pugi
PUGI__FN const char_t* xml_attribute::name() const PUGI__FN const char_t* xml_attribute::name() const
{ {
return (_attr && _attr->name) ? _attr->name + 0 : PUGIXML_TEXT(""); if (!_attr) return PUGIXML_TEXT("");
const char_t* name = _attr->name;
return name ? name : PUGIXML_TEXT("");
} }
PUGI__FN const char_t* xml_attribute::value() const PUGI__FN const char_t* xml_attribute::value() const
{ {
return (_attr && _attr->value) ? _attr->value + 0 : PUGIXML_TEXT(""); if (!_attr) return PUGIXML_TEXT("");
const char_t* value = _attr->value;
return value ? value : PUGIXML_TEXT("");
} }
PUGI__FN size_t xml_attribute::hash_value() const PUGI__FN size_t xml_attribute::hash_value() const
@ -5329,6 +5372,13 @@ namespace pugi
return impl::strcpy_insitu(_attr->name, _attr->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs)); return impl::strcpy_insitu(_attr->name, _attr->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs));
} }
PUGI__FN bool xml_attribute::set_value(const char_t* rhs, size_t sz)
{
if (!_attr) return false;
return impl::strcpy_insitu(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, sz);
}
PUGI__FN bool xml_attribute::set_value(const char_t* rhs) PUGI__FN bool xml_attribute::set_value(const char_t* rhs)
{ {
if (!_attr) return false; if (!_attr) return false;
@ -5521,7 +5571,9 @@ namespace pugi
PUGI__FN const char_t* xml_node::name() const PUGI__FN const char_t* xml_node::name() const
{ {
return (_root && _root->name) ? _root->name + 0 : PUGIXML_TEXT(""); if (!_root) return PUGIXML_TEXT("");
const char_t* name = _root->name;
return name ? name : PUGIXML_TEXT("");
} }
PUGI__FN xml_node_type xml_node::type() const PUGI__FN xml_node_type xml_node::type() const
@ -5531,7 +5583,9 @@ namespace pugi
PUGI__FN const char_t* xml_node::value() const PUGI__FN const char_t* xml_node::value() const
{ {
return (_root && _root->value) ? _root->value + 0 : PUGIXML_TEXT(""); if (!_root) return PUGIXML_TEXT("");
const char_t* value = _root->value;
return value ? value : PUGIXML_TEXT("");
} }
PUGI__FN xml_node xml_node::child(const char_t* name_) const PUGI__FN xml_node xml_node::child(const char_t* name_) const
@ -5539,7 +5593,11 @@ namespace pugi
if (!_root) return xml_node(); if (!_root) return xml_node();
for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
if (i->name && impl::strequal(name_, i->name)) return xml_node(i); {
const char_t* iname = i->name;
if (iname && impl::strequal(name_, iname))
return xml_node(i);
}
return xml_node(); return xml_node();
} }
@ -5549,8 +5607,11 @@ namespace pugi
if (!_root) return xml_attribute(); if (!_root) return xml_attribute();
for (xml_attribute_struct* i = _root->first_attribute; i; i = i->next_attribute) for (xml_attribute_struct* i = _root->first_attribute; i; i = i->next_attribute)
if (i->name && impl::strequal(name_, i->name)) {
const char_t* iname = i->name;
if (iname && impl::strequal(name_, iname))
return xml_attribute(i); return xml_attribute(i);
}
return xml_attribute(); return xml_attribute();
} }
@ -5560,7 +5621,11 @@ namespace pugi
if (!_root) return xml_node(); if (!_root) return xml_node();
for (xml_node_struct* i = _root->next_sibling; i; i = i->next_sibling) for (xml_node_struct* i = _root->next_sibling; i; i = i->next_sibling)
if (i->name && impl::strequal(name_, i->name)) return xml_node(i); {
const char_t* iname = i->name;
if (iname && impl::strequal(name_, iname))
return xml_node(i);
}
return xml_node(); return xml_node();
} }
@ -5575,7 +5640,11 @@ namespace pugi
if (!_root) return xml_node(); if (!_root) return xml_node();
for (xml_node_struct* i = _root->prev_sibling_c; i->next_sibling; i = i->prev_sibling_c) for (xml_node_struct* i = _root->prev_sibling_c; i->next_sibling; i = i->prev_sibling_c)
if (i->name && impl::strequal(name_, i->name)) return xml_node(i); {
const char_t* iname = i->name;
if (iname && impl::strequal(name_, iname))
return xml_node(i);
}
return xml_node(); return xml_node();
} }
@ -5591,24 +5660,30 @@ namespace pugi
// optimistically search from hint up until the end // optimistically search from hint up until the end
for (xml_attribute_struct* i = hint; i; i = i->next_attribute) for (xml_attribute_struct* i = hint; i; i = i->next_attribute)
if (i->name && impl::strequal(name_, i->name)) {
const char_t* iname = i->name;
if (iname && impl::strequal(name_, iname))
{ {
// update hint to maximize efficiency of searching for consecutive attributes // update hint to maximize efficiency of searching for consecutive attributes
hint_._attr = i->next_attribute; hint_._attr = i->next_attribute;
return xml_attribute(i); return xml_attribute(i);
} }
}
// wrap around and search from the first attribute until the hint // wrap around and search from the first attribute until the hint
// 'j' null pointer check is technically redundant, but it prevents a crash in case the assertion above fails // 'j' null pointer check is technically redundant, but it prevents a crash in case the assertion above fails
for (xml_attribute_struct* j = _root->first_attribute; j && j != hint; j = j->next_attribute) for (xml_attribute_struct* j = _root->first_attribute; j && j != hint; j = j->next_attribute)
if (j->name && impl::strequal(name_, j->name)) {
const char_t* jname = j->name;
if (jname && impl::strequal(name_, jname))
{ {
// update hint to maximize efficiency of searching for consecutive attributes // update hint to maximize efficiency of searching for consecutive attributes
hint_._attr = j->next_attribute; hint_._attr = j->next_attribute;
return xml_attribute(j); return xml_attribute(j);
} }
}
return xml_attribute(); return xml_attribute();
} }
@ -5616,9 +5691,8 @@ namespace pugi
PUGI__FN xml_node xml_node::previous_sibling() const PUGI__FN xml_node xml_node::previous_sibling() const
{ {
if (!_root) return xml_node(); if (!_root) return xml_node();
xml_node_struct* prev = _root->prev_sibling_c;
if (_root->prev_sibling_c->next_sibling) return xml_node(_root->prev_sibling_c); return prev->next_sibling ? xml_node(prev) : xml_node();
else return xml_node();
} }
PUGI__FN xml_node xml_node::parent() const PUGI__FN xml_node xml_node::parent() const
@ -5645,8 +5719,11 @@ namespace pugi
return _root->value; return _root->value;
for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
if (impl::is_text_node(i) && i->value) {
return i->value; const char_t* ivalue = i->value;
if (impl::is_text_node(i) && ivalue)
return ivalue;
}
return PUGIXML_TEXT(""); return PUGIXML_TEXT("");
} }
@ -5658,22 +5735,28 @@ namespace pugi
PUGI__FN xml_attribute xml_node::first_attribute() const PUGI__FN xml_attribute xml_node::first_attribute() const
{ {
return _root ? xml_attribute(_root->first_attribute) : xml_attribute(); if (!_root) return xml_attribute();
return xml_attribute(_root->first_attribute);
} }
PUGI__FN xml_attribute xml_node::last_attribute() const PUGI__FN xml_attribute xml_node::last_attribute() const
{ {
return _root && _root->first_attribute ? xml_attribute(_root->first_attribute->prev_attribute_c) : xml_attribute(); if (!_root) return xml_attribute();
xml_attribute_struct* first = _root->first_attribute;
return first ? xml_attribute(first->prev_attribute_c) : xml_attribute();
} }
PUGI__FN xml_node xml_node::first_child() const PUGI__FN xml_node xml_node::first_child() const
{ {
return _root ? xml_node(_root->first_child) : xml_node(); if (!_root) return xml_node();
return xml_node(_root->first_child);
} }
PUGI__FN xml_node xml_node::last_child() const PUGI__FN xml_node xml_node::last_child() const
{ {
return _root && _root->first_child ? xml_node(_root->first_child->prev_sibling_c) : xml_node(); if (!_root) return xml_node();
xml_node_struct* first = _root->first_child;
return first ? xml_node(first->prev_sibling_c) : xml_node();
} }
PUGI__FN bool xml_node::set_name(const char_t* rhs) PUGI__FN bool xml_node::set_name(const char_t* rhs)
@ -5686,6 +5769,16 @@ namespace pugi
return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs)); return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs));
} }
PUGI__FN bool xml_node::set_value(const char_t* rhs, size_t sz)
{
xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null;
if (type_ != node_pcdata && type_ != node_cdata && type_ != node_comment && type_ != node_pi && type_ != node_doctype)
return false;
return impl::strcpy_insitu(_root->value, _root->header, impl::xml_memory_page_value_allocated_mask, rhs, sz);
}
PUGI__FN bool xml_node::set_value(const char_t* rhs) PUGI__FN bool xml_node::set_value(const char_t* rhs)
{ {
xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null; xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null;
@ -6199,12 +6292,22 @@ namespace pugi
if (!_root) return xml_node(); if (!_root) return xml_node();
for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
if (i->name && impl::strequal(name_, i->name)) {
const char_t* iname = i->name;
if (iname && impl::strequal(name_, iname))
{ {
for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute) for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute)
if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 : PUGIXML_TEXT(""))) {
return xml_node(i); const char_t* aname = a->name;
if (aname && impl::strequal(attr_name, aname))
{
const char_t* avalue = a->value;
if (impl::strequal(attr_value, avalue ? avalue : PUGIXML_TEXT("")))
return xml_node(i);
}
}
} }
}
return xml_node(); return xml_node();
} }
@ -6215,8 +6318,15 @@ namespace pugi
for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute) for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute)
if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 : PUGIXML_TEXT(""))) {
return xml_node(i); const char_t* aname = a->name;
if (aname && impl::strequal(attr_name, aname))
{
const char_t* avalue = a->value;
if (impl::strequal(attr_value, avalue ? avalue : PUGIXML_TEXT("")))
return xml_node(i);
}
}
return xml_node(); return xml_node();
} }
@ -6230,8 +6340,9 @@ namespace pugi
for (xml_node_struct* i = _root; i; i = i->parent) for (xml_node_struct* i = _root; i; i = i->parent)
{ {
const char_t* iname = i->name;
offset += (i != _root); offset += (i != _root);
offset += i->name ? impl::strlength(i->name) : 0; offset += iname ? impl::strlength(iname) : 0;
} }
string_t result; string_t result;
@ -6242,12 +6353,13 @@ namespace pugi
if (j != _root) if (j != _root)
result[--offset] = delimiter; result[--offset] = delimiter;
if (j->name) const char_t* jname = j->name;
if (jname)
{ {
size_t length = impl::strlength(j->name); size_t length = impl::strlength(jname);
offset -= length; offset -= length;
memcpy(&result[offset], j->name, length * sizeof(char_t)); memcpy(&result[offset], jname, length * sizeof(char_t));
} }
} }
@ -6285,7 +6397,8 @@ namespace pugi
{ {
for (xml_node_struct* j = context._root->first_child; j; j = j->next_sibling) for (xml_node_struct* j = context._root->first_child; j; j = j->next_sibling)
{ {
if (j->name && impl::strequalrange(j->name, path_segment, static_cast<size_t>(path_segment_end - path_segment))) const char_t* jname = j->name;
if (jname && impl::strequalrange(jname, path_segment, static_cast<size_t>(path_segment_end - path_segment)))
{ {
xml_node subsearch = xml_node(j).first_element_by_path(next_segment, delimiter); xml_node subsearch = xml_node(j).first_element_by_path(next_segment, delimiter);
@ -6477,68 +6590,84 @@ namespace pugi
PUGI__FN const char_t* xml_text::get() const PUGI__FN const char_t* xml_text::get() const
{ {
xml_node_struct* d = _data(); xml_node_struct* d = _data();
if (!d) return PUGIXML_TEXT("");
return (d && d->value) ? d->value + 0 : PUGIXML_TEXT(""); const char_t* value = d->value;
return value ? value : PUGIXML_TEXT("");
} }
PUGI__FN const char_t* xml_text::as_string(const char_t* def) const PUGI__FN const char_t* xml_text::as_string(const char_t* def) const
{ {
xml_node_struct* d = _data(); xml_node_struct* d = _data();
if (!d) return def;
return (d && d->value) ? d->value + 0 : def; const char_t* value = d->value;
return value ? value : def;
} }
PUGI__FN int xml_text::as_int(int def) const PUGI__FN int xml_text::as_int(int def) const
{ {
xml_node_struct* d = _data(); xml_node_struct* d = _data();
if (!d) return def;
return (d && d->value) ? impl::get_value_int(d->value) : def; const char_t* value = d->value;
return value ? impl::get_value_int(value) : def;
} }
PUGI__FN unsigned int xml_text::as_uint(unsigned int def) const PUGI__FN unsigned int xml_text::as_uint(unsigned int def) const
{ {
xml_node_struct* d = _data(); xml_node_struct* d = _data();
if (!d) return def;
return (d && d->value) ? impl::get_value_uint(d->value) : def; const char_t* value = d->value;
return value ? impl::get_value_uint(value) : def;
} }
PUGI__FN double xml_text::as_double(double def) const PUGI__FN double xml_text::as_double(double def) const
{ {
xml_node_struct* d = _data(); xml_node_struct* d = _data();
if (!d) return def;
return (d && d->value) ? impl::get_value_double(d->value) : def; const char_t* value = d->value;
return value ? impl::get_value_double(value) : def;
} }
PUGI__FN float xml_text::as_float(float def) const PUGI__FN float xml_text::as_float(float def) const
{ {
xml_node_struct* d = _data(); xml_node_struct* d = _data();
if (!d) return def;
return (d && d->value) ? impl::get_value_float(d->value) : def; const char_t* value = d->value;
return value ? impl::get_value_float(value) : def;
} }
PUGI__FN bool xml_text::as_bool(bool def) const PUGI__FN bool xml_text::as_bool(bool def) const
{ {
xml_node_struct* d = _data(); xml_node_struct* d = _data();
if (!d) return def;
return (d && d->value) ? impl::get_value_bool(d->value) : def; const char_t* value = d->value;
return value ? impl::get_value_bool(value) : def;
} }
#ifdef PUGIXML_HAS_LONG_LONG #ifdef PUGIXML_HAS_LONG_LONG
PUGI__FN long long xml_text::as_llong(long long def) const PUGI__FN long long xml_text::as_llong(long long def) const
{ {
xml_node_struct* d = _data(); xml_node_struct* d = _data();
if (!d) return def;
return (d && d->value) ? impl::get_value_llong(d->value) : def; const char_t* value = d->value;
return value ? impl::get_value_llong(value) : def;
} }
PUGI__FN unsigned long long xml_text::as_ullong(unsigned long long def) const PUGI__FN unsigned long long xml_text::as_ullong(unsigned long long def) const
{ {
xml_node_struct* d = _data(); xml_node_struct* d = _data();
if (!d) return def;
return (d && d->value) ? impl::get_value_ullong(d->value) : def; const char_t* value = d->value;
return value ? impl::get_value_ullong(value) : def;
} }
#endif #endif
PUGI__FN bool xml_text::set(const char_t* rhs, size_t sz)
{
xml_node_struct* dn = _data_new();
return dn ? impl::strcpy_insitu(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, sz) : false;
}
PUGI__FN bool xml_text::set(const char_t* rhs) PUGI__FN bool xml_text::set(const char_t* rhs)
{ {
xml_node_struct* dn = _data_new(); xml_node_struct* dn = _data_new();
@ -7294,7 +7423,7 @@ namespace pugi
using impl::auto_deleter; // MSVC7 workaround using impl::auto_deleter; // MSVC7 workaround
auto_deleter<FILE> file(impl::open_file(path_, (flags & format_save_file_text) ? "w" : "wb"), impl::close_file); auto_deleter<FILE> file(impl::open_file(path_, (flags & format_save_file_text) ? "w" : "wb"), impl::close_file);
return impl::save_file_impl(*this, file.data, indent, flags, encoding); return impl::save_file_impl(*this, file.data, indent, flags, encoding) && fclose(file.release()) == 0;
} }
PUGI__FN bool xml_document::save_file(const wchar_t* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const PUGI__FN bool xml_document::save_file(const wchar_t* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const
@ -7302,7 +7431,7 @@ namespace pugi
using impl::auto_deleter; // MSVC7 workaround using impl::auto_deleter; // MSVC7 workaround
auto_deleter<FILE> file(impl::open_file_wide(path_, (flags & format_save_file_text) ? L"w" : L"wb"), impl::close_file); auto_deleter<FILE> file(impl::open_file_wide(path_, (flags & format_save_file_text) ? L"w" : L"wb"), impl::close_file);
return impl::save_file_impl(*this, file.data, indent, flags, encoding); return impl::save_file_impl(*this, file.data, indent, flags, encoding) && fclose(file.release()) == 0;
} }
PUGI__FN xml_node xml_document::document_element() const PUGI__FN xml_node xml_document::document_element() const

View File

@ -1,5 +1,5 @@
/** /**
* pugixml parser - version 1.12 * pugixml parser - version 1.13
* -------------------------------------------------------- * --------------------------------------------------------
* Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
* Report bugs and download new versions at https://pugixml.org/ * Report bugs and download new versions at https://pugixml.org/
@ -14,7 +14,7 @@
// Define version macro; evaluates to major * 1000 + minor * 10 + patch so that it's safe to use in less-than comparisons // Define version macro; evaluates to major * 1000 + minor * 10 + patch so that it's safe to use in less-than comparisons
// Note: pugixml used major * 100 + minor * 10 + patch format up until 1.9 (which had version identifier 190); starting from pugixml 1.10, the minor version number is two digits // Note: pugixml used major * 100 + minor * 10 + patch format up until 1.9 (which had version identifier 190); starting from pugixml 1.10, the minor version number is two digits
#ifndef PUGIXML_VERSION #ifndef PUGIXML_VERSION
# define PUGIXML_VERSION 1120 // 1.12 # define PUGIXML_VERSION 1130 // 1.13
#endif #endif
// Include user configuration file (this can define various configuration macros) // Include user configuration file (this can define various configuration macros)
@ -115,6 +115,8 @@
#ifndef PUGIXML_NULL #ifndef PUGIXML_NULL
# if __cplusplus >= 201103 # if __cplusplus >= 201103
# define PUGIXML_NULL nullptr # define PUGIXML_NULL nullptr
# elif defined(_MSC_VER) && _MSC_VER >= 1600
# define PUGIXML_NULL nullptr
# else # else
# define PUGIXML_NULL 0 # define PUGIXML_NULL 0
# endif # endif
@ -416,6 +418,7 @@ namespace pugi
// Set attribute name/value (returns false if attribute is empty or there is not enough memory) // Set attribute name/value (returns false if attribute is empty or there is not enough memory)
bool set_name(const char_t* rhs); bool set_name(const char_t* rhs);
bool set_value(const char_t* rhs, size_t sz);
bool set_value(const char_t* rhs); bool set_value(const char_t* rhs);
// Set attribute value with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") // Set attribute value with type conversion (numbers are converted to strings, boolean is converted to "true"/"false")
@ -550,6 +553,7 @@ namespace pugi
// Set node name/value (returns false if node is empty, there is not enough memory, or node can not have name/value) // Set node name/value (returns false if node is empty, there is not enough memory, or node can not have name/value)
bool set_name(const char_t* rhs); bool set_name(const char_t* rhs);
bool set_value(const char_t* rhs, size_t sz);
bool set_value(const char_t* rhs); bool set_value(const char_t* rhs);
// Add attribute with specified name. Returns added attribute, or empty attribute on errors. // Add attribute with specified name. Returns added attribute, or empty attribute on errors.
@ -775,6 +779,7 @@ namespace pugi
bool as_bool(bool def = false) const; bool as_bool(bool def = false) const;
// Set text (returns false if object is empty or there is not enough memory) // Set text (returns false if object is empty or there is not enough memory)
bool set(const char_t* rhs, size_t sz);
bool set(const char_t* rhs); bool set(const char_t* rhs);
// Set text with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") // Set text with type conversion (numbers are converted to strings, boolean is converted to "true"/"false")