0
0
mirror of https://github.com/zeux/pugixml.git synced 2024-12-25 20:14:10 +08:00

Add remaining std::string_view overloads (#636)

Add remaining overloads and supporting unit tests. This concludes the initial phase of std::string_view support; for now the support is still opt-in via PUGIXML_STRING_VIEW define, but that will become unnecessary (enabled-by-default) in a future version.
This commit is contained in:
dantargz 2024-10-24 14:10:09 -07:00 committed by GitHub
parent 7e702740ff
commit 13beda24b8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 578 additions and 10 deletions

View File

@ -252,6 +252,24 @@ PUGI_IMPL_NS_BEGIN
#endif
}
#ifdef PUGIXML_HAS_STRING_VIEW
// Check if the null-terminated dst string is equal to the entire contents of srcview
PUGI_IMPL_FN bool stringview_equal(string_view_t srcview, const char_t* dst)
{
// std::basic_string_view::compare(const char*) has the right behavior, but it performs an
// extra traversal of dst to compute its length.
assert(dst);
const char_t* src = srcview.data();
size_t srclen = srcview.size();
while (srclen && *dst && *src == *dst)
{
--srclen; ++dst; ++src;
}
return srclen == 0 && *dst == 0;
}
#endif
// Compare lhs with [rhs_begin, rhs_end)
PUGI_IMPL_FN bool strequalrange(const char_t* lhs, const char_t* rhs, size_t count)
{
@ -5413,6 +5431,14 @@ namespace pugi
return *this;
}
#ifdef PUGIXML_HAS_STRING_VIEW
PUGI_IMPL_FN xml_attribute& xml_attribute::operator=(string_view_t rhs)
{
set_value(rhs);
return *this;
}
#endif
#ifdef PUGIXML_HAS_LONG_LONG
PUGI_IMPL_FN xml_attribute& xml_attribute::operator=(long long rhs)
{
@ -5736,6 +5762,64 @@ namespace pugi
return xml_node();
}
#ifdef PUGIXML_HAS_STRING_VIEW
PUGI_IMPL_FN xml_node xml_node::child(string_view_t name_) const
{
if (!_root) return xml_node();
for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
{
const char_t* iname = i->name;
if (iname && impl::stringview_equal(name_, iname))
return xml_node(i);
}
return xml_node();
}
PUGI_IMPL_FN xml_attribute xml_node::attribute(string_view_t name_) const
{
if (!_root) return xml_attribute();
for (xml_attribute_struct* i = _root->first_attribute; i; i = i->next_attribute)
{
const char_t* iname = i->name;
if (iname && impl::stringview_equal(name_, iname))
return xml_attribute(i);
}
return xml_attribute();
}
PUGI_IMPL_FN xml_node xml_node::next_sibling(string_view_t name_) const
{
if (!_root) return xml_node();
for (xml_node_struct* i = _root->next_sibling; i; i = i->next_sibling)
{
const char_t* iname = i->name;
if (iname && impl::stringview_equal(name_, iname))
return xml_node(i);
}
return xml_node();
}
PUGI_IMPL_FN xml_node xml_node::previous_sibling(string_view_t name_) const
{
if (!_root) return xml_node();
for (xml_node_struct* i = _root->prev_sibling_c; i->next_sibling; i = i->prev_sibling_c)
{
const char_t* iname = i->name;
if (iname && impl::stringview_equal(name_, iname))
return xml_node(i);
}
return xml_node();
}
#endif
PUGI_IMPL_FN xml_attribute xml_node::attribute(const char_t* name_, xml_attribute& hint_) const
{
xml_attribute_struct* hint = hint_._attr;
@ -5775,6 +5859,47 @@ namespace pugi
return xml_attribute();
}
#ifdef PUGIXML_HAS_STRING_VIEW
PUGI_IMPL_FN xml_attribute xml_node::attribute(string_view_t name_, xml_attribute& hint_) const
{
xml_attribute_struct* hint = hint_._attr;
// if hint is not an attribute of node, behavior is not defined
assert(!hint || (_root && impl::is_attribute_of(hint, _root)));
if (!_root) return xml_attribute();
// optimistically search from hint up until the end
for (xml_attribute_struct* i = hint; i; i = i->next_attribute)
{
const char_t* iname = i->name;
if (iname && impl::stringview_equal(name_, iname))
{
// update hint to maximize efficiency of searching for consecutive attributes
hint_._attr = i->next_attribute;
return xml_attribute(i);
}
}
// 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
for (xml_attribute_struct* j = _root->first_attribute; j && j != hint; j = j->next_attribute)
{
const char_t* jname = j->name;
if (jname && impl::stringview_equal(name_, jname))
{
// update hint to maximize efficiency of searching for consecutive attributes
hint_._attr = j->next_attribute;
return xml_attribute(j);
}
}
return xml_attribute();
}
#endif
PUGI_IMPL_FN xml_node xml_node::previous_sibling() const
{
if (!_root) return xml_node();
@ -5980,6 +6105,78 @@ namespace pugi
return a;
}
#ifdef PUGIXML_HAS_STRING_VIEW
PUGI_IMPL_FN xml_attribute xml_node::append_attribute(string_view_t name_)
{
if (!impl::allow_insert_attribute(type())) return xml_attribute();
impl::xml_allocator& alloc = impl::get_allocator(_root);
if (!alloc.reserve()) return xml_attribute();
xml_attribute a(impl::allocate_attribute(alloc));
if (!a) return xml_attribute();
impl::append_attribute(a._attr, _root);
a.set_name(name_);
return a;
}
PUGI_IMPL_FN xml_attribute xml_node::prepend_attribute(string_view_t name_)
{
if (!impl::allow_insert_attribute(type())) return xml_attribute();
impl::xml_allocator& alloc = impl::get_allocator(_root);
if (!alloc.reserve()) return xml_attribute();
xml_attribute a(impl::allocate_attribute(alloc));
if (!a) return xml_attribute();
impl::prepend_attribute(a._attr, _root);
a.set_name(name_);
return a;
}
PUGI_IMPL_FN xml_attribute xml_node::insert_attribute_after(string_view_t name_, const xml_attribute& attr)
{
if (!impl::allow_insert_attribute(type())) return xml_attribute();
if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute();
impl::xml_allocator& alloc = impl::get_allocator(_root);
if (!alloc.reserve()) return xml_attribute();
xml_attribute a(impl::allocate_attribute(alloc));
if (!a) return xml_attribute();
impl::insert_attribute_after(a._attr, attr._attr, _root);
a.set_name(name_);
return a;
}
PUGI_IMPL_FN xml_attribute xml_node::insert_attribute_before(string_view_t name_, const xml_attribute& attr)
{
if (!impl::allow_insert_attribute(type())) return xml_attribute();
if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute();
impl::xml_allocator& alloc = impl::get_allocator(_root);
if (!alloc.reserve()) return xml_attribute();
xml_attribute a(impl::allocate_attribute(alloc));
if (!a) return xml_attribute();
impl::insert_attribute_before(a._attr, attr._attr, _root);
a.set_name(name_);
return a;
}
#endif
PUGI_IMPL_FN xml_attribute xml_node::append_copy(const xml_attribute& proto)
{
if (!proto) return xml_attribute();
@ -6156,6 +6353,44 @@ namespace pugi
return result;
}
#ifdef PUGIXML_HAS_STRING_VIEW
PUGI_IMPL_FN xml_node xml_node::append_child(string_view_t name_)
{
xml_node result = append_child(node_element);
result.set_name(name_);
return result;
}
PUGI_IMPL_FN xml_node xml_node::prepend_child(string_view_t name_)
{
xml_node result = prepend_child(node_element);
result.set_name(name_);
return result;
}
PUGI_IMPL_FN xml_node xml_node::insert_child_after(string_view_t name_, const xml_node& node)
{
xml_node result = insert_child_after(node_element, node);
result.set_name(name_);
return result;
}
PUGI_IMPL_FN xml_node xml_node::insert_child_before(string_view_t name_, const xml_node& node)
{
xml_node result = insert_child_before(node_element, node);
result.set_name(name_);
return result;
}
#endif
PUGI_IMPL_FN xml_node xml_node::append_copy(const xml_node& proto)
{
xml_node_type type_ = proto.type();
@ -6299,6 +6534,13 @@ namespace pugi
return remove_attribute(attribute(name_));
}
#ifdef PUGIXML_HAS_STRING_VIEW
PUGI_IMPL_FN bool xml_node::remove_attribute(string_view_t name_)
{
return remove_attribute(attribute(name_));
}
#endif
PUGI_IMPL_FN bool xml_node::remove_attribute(const xml_attribute& a)
{
if (!_root || !a._attr) return false;
@ -6339,6 +6581,13 @@ namespace pugi
return remove_child(child(name_));
}
#ifdef PUGIXML_HAS_STRING_VIEW
PUGI_IMPL_FN bool xml_node::remove_child(string_view_t name_)
{
return remove_child(child(name_));
}
#endif
PUGI_IMPL_FN bool xml_node::remove_child(const xml_node& n)
{
if (!_root || !n._root || n._root->parent != _root) return false;
@ -6935,6 +7184,14 @@ namespace pugi
return *this;
}
#ifdef PUGIXML_HAS_STRING_VIEW
PUGI_IMPL_FN xml_text& xml_text::operator=(string_view_t rhs)
{
set(rhs);
return *this;
}
#endif
#ifdef PUGIXML_HAS_LONG_LONG
PUGI_IMPL_FN xml_text& xml_text::operator=(long long rhs)
{

View File

@ -477,6 +477,10 @@ namespace pugi
xml_attribute& operator=(float rhs);
xml_attribute& operator=(bool rhs);
#ifdef PUGIXML_HAS_STRING_VIEW
xml_attribute& operator=(string_view_t rhs);
#endif
#ifdef PUGIXML_HAS_LONG_LONG
xml_attribute& operator=(long long rhs);
xml_attribute& operator=(unsigned long long rhs);
@ -571,9 +575,18 @@ namespace pugi
xml_attribute attribute(const char_t* name) const;
xml_node next_sibling(const char_t* name) const;
xml_node previous_sibling(const char_t* name) const;
#ifdef PUGIXML_HAS_STRING_VIEW
xml_node child(string_view_t name) const;
xml_attribute attribute(string_view_t name) const;
xml_node next_sibling(string_view_t name) const;
xml_node previous_sibling(string_view_t name) const;
#endif
// Get attribute, starting the search from a hint (and updating hint so that searching for a sequence of attributes is fast)
xml_attribute attribute(const char_t* name, xml_attribute& hint) const;
#ifdef PUGIXML_HAS_STRING_VIEW
xml_attribute attribute(string_view_t name, xml_attribute& hint) const;
#endif
// Get child value of current node; that is, value of the first child node of type PCDATA/CDATA
const char_t* child_value() const;
@ -598,6 +611,12 @@ namespace pugi
xml_attribute prepend_attribute(const char_t* name);
xml_attribute insert_attribute_after(const char_t* name, const xml_attribute& attr);
xml_attribute insert_attribute_before(const char_t* name, const xml_attribute& attr);
#ifdef PUGIXML_HAS_STRING_VIEW
xml_attribute append_attribute(string_view_t name);
xml_attribute prepend_attribute(string_view_t name);
xml_attribute insert_attribute_after(string_view_t name, const xml_attribute& attr);
xml_attribute insert_attribute_before(string_view_t name, const xml_attribute& attr);
#endif
// Add a copy of the specified attribute. Returns added attribute, or empty attribute on errors.
xml_attribute append_copy(const xml_attribute& proto);
@ -616,6 +635,12 @@ namespace pugi
xml_node prepend_child(const char_t* name);
xml_node insert_child_after(const char_t* name, const xml_node& node);
xml_node insert_child_before(const char_t* name, const xml_node& node);
#ifdef PUGIXML_HAS_STRING_VIEW
xml_node append_child(string_view_t name);
xml_node prepend_child(string_view_t name);
xml_node insert_child_after(string_view_t, const xml_node& node);
xml_node insert_child_before(string_view_t name, const xml_node& node);
#endif
// Add a copy of the specified node as a child. Returns added node, or empty node on errors.
xml_node append_copy(const xml_node& proto);
@ -632,6 +657,9 @@ namespace pugi
// Remove specified attribute
bool remove_attribute(const xml_attribute& a);
bool remove_attribute(const char_t* name);
#ifdef PUGIXML_HAS_STRING_VIEW
bool remove_attribute(string_view_t name);
#endif
// Remove all attributes
bool remove_attributes();
@ -639,6 +667,9 @@ namespace pugi
// Remove specified child
bool remove_child(const xml_node& n);
bool remove_child(const char_t* name);
#ifdef PUGIXML_HAS_STRING_VIEW
bool remove_child(string_view_t name);
#endif
// Remove all children
bool remove_children();
@ -851,6 +882,10 @@ namespace pugi
xml_text& operator=(float rhs);
xml_text& operator=(bool rhs);
#ifdef PUGIXML_HAS_STRING_VIEW
xml_text& operator=(string_view_t rhs);
#endif
#ifdef PUGIXML_HAS_LONG_LONG
xml_text& operator=(long long rhs);
xml_text& operator=(unsigned long long rhs);

View File

@ -33,7 +33,13 @@ TEST_XML(dom_attr_assign, "<node/>")
node.append_attribute(STR("attr8")) = true;
xml_attribute() = true;
CHECK_NODE(node, STR("<node attr1=\"v1\" attr2=\"-2147483647\" attr3=\"-2147483648\" attr4=\"4294967295\" attr5=\"4294967294\" attr6=\"0.5\" attr7=\"0.25\" attr8=\"true\"/>"));
#ifdef PUGIXML_HAS_STRING_VIEW
node.append_attribute(string_view_t(STR("attr9"))) = string_view_t(STR("v2"));
#else
node.append_attribute(STR("attr9")) = STR("v2");
#endif
CHECK_NODE(node, STR("<node attr1=\"v1\" attr2=\"-2147483647\" attr3=\"-2147483648\" attr4=\"4294967295\" attr5=\"4294967294\" attr6=\"0.5\" attr7=\"0.25\" attr8=\"true\" attr9=\"v2\"/>"));
}
TEST_XML(dom_attr_set_name, "<node attr='value' />")
@ -103,7 +109,14 @@ TEST_XML(dom_attr_set_value, "<node/>")
CHECK(node.append_attribute(STR("attr10")).set_value(STR("v3foobar"), 2));
CHECK(!xml_attribute().set_value(STR("v3")));
CHECK_NODE(node, STR("<node attr1=\"v1\" attr2=\"-2147483647\" attr3=\"-2147483648\" attr4=\"4294967295\" attr5=\"4294967294\" attr6=\"0.5\" attr7=\"0.25\" attr8=\"true\" attr9=\"v2\" attr10=\"v3\"/>"));
#ifdef PUGIXML_HAS_STRING_VIEW
CHECK(node.append_attribute(string_view_t(STR("attr11"))).set_value(string_view_t(STR("v4"))));
CHECK(!xml_attribute().set_value(string_view_t(STR("v4"))));
#else
CHECK(node.append_attribute(STR("attr11")).set_value(STR("v4")));
#endif
CHECK_NODE(node, STR("<node attr1=\"v1\" attr2=\"-2147483647\" attr3=\"-2147483648\" attr4=\"4294967295\" attr5=\"4294967294\" attr6=\"0.5\" attr7=\"0.25\" attr8=\"true\" attr9=\"v2\" attr10=\"v3\" attr11=\"v4\"/>"));
}
#if LONG_MAX > 2147483647
@ -335,7 +348,15 @@ TEST_XML(dom_node_prepend_attribute, "<node><child/></node>")
CHECK(a3 && a1 != a3 && a2 != a3);
a3 = STR("v3");
CHECK_NODE(doc, STR("<node a2=\"v2\" a1=\"v1\"><child a3=\"v3\"/></node>"));
#ifdef PUGIXML_HAS_STRING_VIEW
xml_attribute a4 = doc.child(STR("node")).child(STR("child")).prepend_attribute(string_view_t(STR("a4")));
#else
xml_attribute a4 = doc.child(STR("node")).child(STR("child")).prepend_attribute(STR("a4"));
#endif
CHECK(a4 && a1 != a4 && a2 != a4 && a3 != a4);
a4 = STR("v4");
CHECK_NODE(doc, STR("<node a2=\"v2\" a1=\"v1\"><child a4=\"v4\" a3=\"v3\"/></node>"));
}
TEST_XML(dom_node_append_attribute, "<node><child/></node>")
@ -385,7 +406,17 @@ TEST_XML(dom_node_insert_attribute_after, "<node a1='v1'><child a2='v2'/></node>
CHECK(child.insert_attribute_after(STR("a"), a4) == xml_attribute());
CHECK_NODE(doc, STR("<node a1=\"v1\" a4=\"v4\" a3=\"v3\" a5=\"v5\"><child a2=\"v2\"/></node>"));
#ifdef PUGIXML_HAS_STRING_VIEW
xml_attribute a6 = node.insert_attribute_after(string_view_t(STR("a6")), a5);
CHECK(child.insert_attribute_after(string_view_t(STR("a")), a5) == xml_attribute());
#else
xml_attribute a6 = node.insert_attribute_after(STR("a6"), a5);
CHECK(child.insert_attribute_after(STR("a"), a5) == xml_attribute());
#endif
CHECK(a6 && a6 != a5 && a6 != a4 && a6 != a3 && a6 != a2 && a6 != a1);
a6 = STR("v6");
CHECK_NODE(doc, STR("<node a1=\"v1\" a4=\"v4\" a3=\"v3\" a5=\"v5\" a6=\"v6\"><child a2=\"v2\"/></node>"));
}
TEST_XML(dom_node_insert_attribute_before, "<node a1='v1'><child a2='v2'/></node>")
@ -415,7 +446,17 @@ TEST_XML(dom_node_insert_attribute_before, "<node a1='v1'><child a2='v2'/></node
CHECK(child.insert_attribute_before(STR("a"), a4) == xml_attribute());
CHECK_NODE(doc, STR("<node a5=\"v5\" a3=\"v3\" a4=\"v4\" a1=\"v1\"><child a2=\"v2\"/></node>"));
#ifdef PUGIXML_HAS_STRING_VIEW
xml_attribute a6 = node.insert_attribute_before(string_view_t(STR("a6")), a1);
CHECK(child.insert_attribute_before(string_view_t(STR("a")), a4) == xml_attribute());
#else
xml_attribute a6 = node.insert_attribute_before(STR("a6"), a1);
CHECK(child.insert_attribute_before(STR("a"), a4) == xml_attribute());
#endif
CHECK(a6 && a6 != a5 && a6 != a4 && a6 != a3 && a6 != a2 && a6 != a1);
a6 = STR("v6");
CHECK_NODE(doc, STR("<node a5=\"v5\" a3=\"v3\" a4=\"v4\" a6=\"v6\" a1=\"v1\"><child a2=\"v2\"/></node>"));
}
TEST_XML(dom_node_prepend_copy_attribute, "<node a1='v1'><child a2='v2'/><child/></node>")
@ -589,6 +630,14 @@ TEST_XML(dom_node_remove_attribute, "<node a1='v1' a2='v2' a3='v3'><child a4='v4
CHECK(child.remove_attribute(STR("a4")));
CHECK_NODE(doc, STR("<node a2=\"v2\"><child/></node>"));
#ifdef PUGIXML_HAS_STRING_VIEW
CHECK(!node.remove_attribute(string_view_t()));
CHECK(!node.remove_attribute(string_view_t(STR("a2"), 1)));
CHECK(node.remove_attribute(string_view_t(STR("a2extra"), 2)));
CHECK_NODE(doc, STR("<node><child/></node>"));
#endif
}
TEST_XML(dom_node_remove_attributes, "<node a1='v1' a2='v2' a3='v3'><child a4='v4'/></node>")
@ -747,6 +796,10 @@ TEST_XML(dom_node_prepend_child_name, "<node>foo<child/></node>")
{
CHECK(xml_node().prepend_child(STR("")) == xml_node());
CHECK(doc.child(STR("node")).first_child().prepend_child(STR("")) == xml_node());
#ifdef PUGIXML_HAS_STRING_VIEW
CHECK(xml_node().prepend_child(string_view_t()) == xml_node());
CHECK(doc.child(STR("node")).first_child().prepend_child(string_view_t()) == xml_node());
#endif
xml_node n1 = doc.child(STR("node")).prepend_child(STR("n1"));
CHECK(n1);
@ -754,7 +807,14 @@ TEST_XML(dom_node_prepend_child_name, "<node>foo<child/></node>")
xml_node n2 = doc.child(STR("node")).prepend_child(STR("n2"));
CHECK(n2 && n1 != n2);
CHECK_NODE(doc, STR("<node><n2/><n1/>foo<child/></node>"));
#ifdef PUGIXML_HAS_STRING_VIEW
xml_node n3 = doc.prepend_child(string_view_t(STR("n3")));
#else
xml_node n3 = doc.prepend_child(STR("n3"));
#endif
CHECK(n3 && n1 != n3 && n2 != n3);
CHECK_NODE(doc, STR("<n3/><node><n2/><n1/>foo<child/></node>"));
}
TEST_XML(dom_node_append_child_name, "<node>foo<child/></node>")
@ -768,7 +828,14 @@ TEST_XML(dom_node_append_child_name, "<node>foo<child/></node>")
xml_node n2 = doc.child(STR("node")).append_child(STR("n2"));
CHECK(n2 && n1 != n2);
CHECK_NODE(doc, STR("<node>foo<child/><n1/><n2/></node>"));
#ifdef PUGIXML_HAS_STRING_VIEW
xml_node n3 = doc.append_child(string_view_t(STR("n3")));
#else
xml_node n3 = doc.append_child(STR("n3"));
#endif
CHECK(n3 && n3 != n2 && n3 != n1);
CHECK_NODE(doc, STR("<node>foo<child/><n1/><n2/></node><n3/>"));
}
TEST_XML(dom_node_insert_child_after_name, "<node>foo<child/></node>")
@ -790,7 +857,14 @@ TEST_XML(dom_node_insert_child_after_name, "<node>foo<child/></node>")
CHECK(child.insert_child_after(STR(""), n2) == xml_node());
CHECK_NODE(doc, STR("<node>foo<child/><n2/><n1/></node>"));
#ifdef PUGIXML_HAS_STRING_VIEW
xml_node n3 = node.insert_child_after(string_view_t(STR("n3")), n1);
#else
xml_node n3 = node.insert_child_after(STR("n3"), n1);
#endif
CHECK(n3 && n3 != node && n3 != child && n3 != n2 && n3 != n1);
CHECK_NODE(doc, STR("<node>foo<child/><n2/><n1/><n3/></node>"));
}
TEST_XML(dom_node_insert_child_before_name, "<node>foo<child/></node>")
@ -812,7 +886,14 @@ TEST_XML(dom_node_insert_child_before_name, "<node>foo<child/></node>")
CHECK(child.insert_child_before(STR(""), n2) == xml_node());
CHECK_NODE(doc, STR("<node>foo<n1/><n2/><child/></node>"));
#ifdef PUGIXML_HAS_STRING_VIEW
xml_node n3 = node.insert_child_before(string_view_t(STR("n3")), child);
#else
xml_node n3 = node.insert_child_before(STR("n3"), child);
#endif
CHECK(n3 && n3 != node && n3 != child && n3 != n2 && n3 != n1);
CHECK_NODE(doc, STR("<node>foo<n1/><n2/><n3/><child/></node>"));
}
TEST_XML(dom_node_remove_child, "<node><n1/><n2/><n3/><child><n4/></child></node>")
@ -834,6 +915,20 @@ TEST_XML(dom_node_remove_child, "<node><n1/><n2/><n3/><child><n4/></child></node
CHECK(child.remove_child(STR("n4")));
CHECK_NODE(doc, STR("<node><n2/><child/></node>"));
#ifdef PUGIXML_HAS_STRING_VIEW
CHECK(!node.remove_child(string_view_t()));
CHECK(!node.remove_child(string_view_t(STR("child"), 3)));
CHECK(!node.remove_child(string_view_t(STR("n2"), 1)));
CHECK_NODE(doc, STR("<node><n2/><child/></node>"));
CHECK(node.remove_child(string_view_t(STR("child"))));
CHECK_NODE(doc, STR("<node><n2/></node>"));
CHECK(node.remove_child(string_view_t(STR("n2_notinview"), 2)));
CHECK_NODE(doc, STR("<node/>"));
#endif
}
TEST_XML(dom_node_remove_children, "<node><n1/><n2/><n3/><child><n4/></child></node>")

View File

@ -388,7 +388,14 @@ TEST_XML(dom_text_assign, "<node/>")
node.append_child(STR("text8")).text() = true;
xml_text() = true;
CHECK_NODE(node, STR("<node><text1>v1</text1><text2>-2147483647</text2><text3>-2147483648</text3><text4>4294967295</text4><text5>4294967294</text5><text6>0.5</text6><text7>0.25</text7><text8>true</text8></node>"));
#ifdef PUGIXML_HAS_STRING_VIEW
node.append_child(string_view_t(STR("text9"))).text() = string_view_t(STR("v2"));
xml_text() = string_view_t(STR("text9"));
#else
node.append_child(STR("text9")).text() = STR("v2");
#endif
CHECK_NODE(node, STR("<node><text1>v1</text1><text2>-2147483647</text2><text3>-2147483648</text3><text4>4294967295</text4><text5>4294967294</text5><text6>0.5</text6><text7>0.25</text7><text8>true</text8><text9>v2</text9></node>"));
}
TEST_XML(dom_text_set_value, "<node/>")

View File

@ -536,6 +536,42 @@ TEST_XML(dom_node_child, "<node><child1/><child2/></node>")
CHECK(doc.child(STR("node")).child(STR("child2")) == doc.child(STR("node")).last_child());
}
#ifdef PUGIXML_HAS_STRING_VIEW
TEST_XML(dom_node_child_stringview, "<node><child1/><child2/></node>")
{
CHECK(xml_node().child(string_view_t(STR("n"))) == xml_node());
CHECK(doc.child(string_view_t()) == xml_node());
CHECK(doc.child(string_view_t(STR("n"))) == xml_node());
xml_node node = doc.child(string_view_t(STR("node")));
CHECK_NAME_VALUE(node, STR("node"), STR(""));
CHECK(node.child(string_view_t(STR("child2"))) == node.last_child());
// verify only the characters in the view of the string view are included in the comparison
CHECK_NAME_VALUE(doc.child(string_view_t(STR("node_andextratext"), 4)), STR("node"), STR(""));
CHECK(doc.child(string_view_t(STR("node"), 2)) == xml_node());
}
TEST_XML(dom_node_child_interior_null, "<node><child1/><child2/></node>")
{
const char_t name[] = STR("node\0extra");
size_t len = (sizeof(name) / sizeof(char_t)) - 1;
CHECK(len == 10);
xml_node node = doc.child(string_view_t(name, 4)); // "node" view excluding null
CHECK_NAME_VALUE(node, STR("node"), STR(""));
CHECK(doc.child(string_view_t(name, 5)) == xml_node()); // "node\0" view including null
CHECK(doc.child(string_view_t(name, len)) == xml_node()); // "node\0extra" view
node.set_name(string_view_t(name, len));
CHECK_NODE(doc, STR("<node><child1/><child2/></node>"));
CHECK_NAME_VALUE(node, STR("node"), STR(""));
CHECK_NAME_VALUE(doc.child(string_view_t(name, 4)), STR("node"), STR("")); // "node" view excluding null
CHECK(doc.child(string_view_t(name, 5)) == xml_node()); // "node\0" view including null
CHECK(doc.child(string_view_t(name, len)) == xml_node()); // "node\0extra" view
}
#endif
TEST_XML(dom_node_attribute, "<node attr1='0' attr2='1'/>")
{
CHECK(xml_node().attribute(STR("a")) == xml_attribute());
@ -547,6 +583,46 @@ TEST_XML(dom_node_attribute, "<node attr1='0' attr2='1'/>")
CHECK(node.attribute(STR("attr2")) == node.last_attribute());
}
#ifdef PUGIXML_HAS_STRING_VIEW
TEST_XML(dom_node_attribute_stringview, "<node attr1='0' attr2='1'/>")
{
CHECK(xml_node().attribute(string_view_t(STR("a"))) == xml_attribute());
xml_node node = doc.child(string_view_t(STR("node")));
CHECK(node.attribute(string_view_t()) == xml_attribute());
CHECK(node.attribute(string_view_t(STR("n"))) == xml_attribute());
CHECK_NAME_VALUE(node.attribute(string_view_t(STR("attr1"))), STR("attr1"), STR("0"));
CHECK(node.attribute(string_view_t(STR("attr2"))) == node.last_attribute());
// verify only the characters in the view of the string view are included in the comparison
CHECK_NAME_VALUE(node.attribute(string_view_t(STR("attr1_andextratext"), 5)), STR("attr1"), STR("0"));
CHECK(node.attribute(string_view_t(STR("attr1"), 2)) == xml_attribute());
}
TEST_XML(dom_node_attribute_interior_null, "<node attr1='0' attr2='1'/>")
{
xml_node node = doc.child(STR("node"));
CHECK_NAME_VALUE(node, STR("node"), STR(""));
const char_t name[] = STR("attr2\0extra");
size_t len = (sizeof(name) / sizeof(char_t)) - 1;
CHECK(len == 11);
CHECK_NAME_VALUE(node.attribute(string_view_t(name, 5)), STR("attr2"), STR("1")); // "attr2" view excluding null
CHECK(node.attribute(string_view_t(name, 6)) == xml_attribute()); // "attr2\0" view including null
CHECK(node.attribute(string_view_t(name, len)) == xml_attribute()); // "attr2\0extra" view
xml_attribute attr = node.attribute(STR("attr2"));
CHECK_NAME_VALUE(attr, STR("attr2"), STR("1"));
attr.set_name(string_view_t(name, len));
CHECK_NODE(doc, STR("<node attr1=\"0\" attr2=\"1\"/>"));
CHECK_NAME_VALUE(node.attribute(string_view_t(name, 5)), STR("attr2"), STR("1")); // "attr2" view excluding null
CHECK(node.attribute(string_view_t(name, 6)) == xml_attribute()); // "attr2\0" view including null
CHECK(node.attribute(string_view_t(name, len)) == xml_attribute()); // "attr2\0extra" view
}
#endif
TEST_XML(dom_node_next_previous_sibling, "<node><child1/><child2/><child3/></node>")
{
CHECK(xml_node().next_sibling() == xml_node());
@ -567,9 +643,17 @@ TEST_XML(dom_node_next_previous_sibling, "<node><child1/><child2/><child3/></nod
CHECK(child1.next_sibling(STR("child3")) == child3);
CHECK(child1.next_sibling(STR("child")) == xml_node());
#ifdef PUGIXML_HAS_STRING_VIEW
CHECK(child1.next_sibling(string_view_t(STR("child3"))) == child3);
CHECK(child1.next_sibling(string_view_t(STR("child"))) == xml_node());
#endif
CHECK(child3.previous_sibling(STR("child1")) == child1);
CHECK(child3.previous_sibling(STR("child")) == xml_node());
#ifdef PUGIXML_HAS_STRING_VIEW
CHECK(child3.previous_sibling(string_view_t(STR("child1"))) == child1);
CHECK(child3.previous_sibling(string_view_t(STR("child"))) == xml_node());
#endif
}
TEST_XML(dom_node_child_value, "<node><novalue/><child1>value1</child1><child2>value2<n/></child2><child3><![CDATA[value3]]></child3>value4</node>")
@ -1166,6 +1250,64 @@ TEST_XML(dom_node_attribute_hinted, "<node attr1='1' attr2='2' attr3='3' />")
CHECK(!node.attribute(STR("attr"), hint) && hint == attr2);
}
#ifdef PUGIXML_HAS_STRING_VIEW
TEST_XML(dom_node_attribute_hinted_stringview, "<node attr1='1' attr2='2' attr3='3' />")
{
xml_node node = doc.first_child();
string_view_t a1name = string_view_t(STR("attr1"));
string_view_t a2name = string_view_t(STR("attr2"));
string_view_t a3name = string_view_t(STR("attr3"));
xml_attribute attr1 = node.attribute(a1name);
xml_attribute attr2 = node.attribute(a2name);
xml_attribute attr3 = node.attribute(a3name);
xml_attribute hint;
CHECK(!xml_node().attribute(string_view_t(string_view_t(STR("test"))), hint) && !hint);
CHECK(node.attribute(a2name, hint) == attr2 && hint == attr3);
CHECK(node.attribute(a3name, hint) == attr3 && !hint);
CHECK(node.attribute(a1name, hint) == attr1 && hint == attr2);
CHECK(node.attribute(a2name, hint) == attr2 && hint == attr3);
CHECK(node.attribute(a1name, hint) == attr1 && hint == attr2);
CHECK(node.attribute(a1name, hint) == attr1 && hint == attr2);
CHECK(!node.attribute(string_view_t(), hint) && hint == attr2);
CHECK(!node.attribute(string_view_t(STR("attr1"), 4), hint) && hint == attr2); // "attr"
CHECK(node.attribute(string_view_t(STR("attr3_extra"), 5), hint) == attr3 && !hint); // "attr3"
}
TEST_XML(dom_node_attribute_hint_interior_null, "<node attr1='1' attr2='2' attr3='3' />")
{
xml_node node = doc.first_child();
xml_attribute attr1 = node.attribute(STR("attr1"));
xml_attribute attr2 = node.attribute(STR("attr2"));
xml_attribute attr3 = node.attribute(STR("attr3"));
CHECK(node && attr1 && attr2 && attr3);
const char_t name[] = STR("attr2\0extra");
size_t len = (sizeof(name) / sizeof(char_t)) - 1;
CHECK(len == 11);
xml_attribute hint;
CHECK(node.attribute(string_view_t(name, 5), hint) == attr2 && hint == attr3); // "attr2"
CHECK(node.attribute(string_view_t(name, 5), hint) == attr2 && hint == attr3); // "attr2"
CHECK(!node.attribute(string_view_t(name, 6), hint) && hint == attr3); // "attr2\0"
CHECK(!node.attribute(string_view_t(name, len), hint) && hint == attr3); // "attr2\0extra"
attr2.set_name(string_view_t(name, len)); // attr2\0extra
CHECK(node.attribute(string_view_t(name, 5), hint) == attr2 && hint == attr3); // "attr2"
CHECK(node.attribute(string_view_t(name, 5), hint) == attr2 && hint == attr3); // "attr2"
CHECK(!node.attribute(string_view_t(name, 6), hint) && hint == attr3); // "attr2\0"
CHECK(!node.attribute(string_view_t(name, len), hint) && hint == attr3); // "attr2\0extra"
}
#endif
TEST_XML(dom_as_int_overflow, "<node attr1='-2147483649' attr2='2147483648' attr3='-4294967296' />")
{
xml_node node = doc.child(STR("node"));
@ -1302,3 +1444,35 @@ TEST(dom_node_anonymous)
CHECK_STRING(doc.child_value(), STR(""));
CHECK_STRING(doc.last_child().child_value(), STR(""));
}
TEST_XML(dom_node_anonymous_child, "<node></node>")
{
xml_node node = doc.child(STR("node"));
CHECK_NAME_VALUE(node, STR("node"), STR(""));
node.set_name(STR(""));
CHECK_NODE(doc, STR("<:anonymous/>"));
CHECK(doc.first_child() != xml_node());
CHECK_NAME_VALUE(doc.first_child(), STR(""), STR(""));
// searching for empty string does not find a node with empty name
CHECK(doc.child(STR("")) == xml_node());
#ifdef PUGIXML_HAS_STRING_VIEW
CHECK(doc.child(string_view_t()) == xml_node());
CHECK(doc.child(string_view_t(STR("hi"), 0)) == xml_node());
#endif
}
TEST_XML(dom_node_anonymous_attribute, "<node attr='0'/>")
{
xml_attribute attr = doc.first_child().attribute(STR("attr"));
CHECK(attr != xml_attribute());
attr.set_name(STR(""));
CHECK_NODE(doc, STR("<node :anonymous=\"0\"/>"));
CHECK_NAME_VALUE(doc.first_child().first_attribute(), STR(""), STR("0"));
CHECK(doc.first_child().attribute(STR("")) == xml_attribute());
#ifdef PUGIXML_HAS_STRING_VIEW
CHECK(doc.first_child().attribute(string_view_t()) == xml_attribute());
CHECK(doc.first_child().attribute(string_view_t(STR("hi"), 0)) == xml_attribute());
#endif
}