Skip to content

Commit 13beda2

Browse files
authored
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.
1 parent 7e70274 commit 13beda2

File tree

5 files changed

+578
-10
lines changed

5 files changed

+578
-10
lines changed

src/pugixml.cpp

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,24 @@ PUGI_IMPL_NS_BEGIN
252252
#endif
253253
}
254254

255+
#ifdef PUGIXML_HAS_STRING_VIEW
256+
// Check if the null-terminated dst string is equal to the entire contents of srcview
257+
PUGI_IMPL_FN bool stringview_equal(string_view_t srcview, const char_t* dst)
258+
{
259+
// std::basic_string_view::compare(const char*) has the right behavior, but it performs an
260+
// extra traversal of dst to compute its length.
261+
assert(dst);
262+
const char_t* src = srcview.data();
263+
size_t srclen = srcview.size();
264+
265+
while (srclen && *dst && *src == *dst)
266+
{
267+
--srclen; ++dst; ++src;
268+
}
269+
return srclen == 0 && *dst == 0;
270+
}
271+
#endif
272+
255273
// Compare lhs with [rhs_begin, rhs_end)
256274
PUGI_IMPL_FN bool strequalrange(const char_t* lhs, const char_t* rhs, size_t count)
257275
{
@@ -5413,6 +5431,14 @@ namespace pugi
54135431
return *this;
54145432
}
54155433

5434+
#ifdef PUGIXML_HAS_STRING_VIEW
5435+
PUGI_IMPL_FN xml_attribute& xml_attribute::operator=(string_view_t rhs)
5436+
{
5437+
set_value(rhs);
5438+
return *this;
5439+
}
5440+
#endif
5441+
54165442
#ifdef PUGIXML_HAS_LONG_LONG
54175443
PUGI_IMPL_FN xml_attribute& xml_attribute::operator=(long long rhs)
54185444
{
@@ -5736,6 +5762,64 @@ namespace pugi
57365762
return xml_node();
57375763
}
57385764

5765+
#ifdef PUGIXML_HAS_STRING_VIEW
5766+
PUGI_IMPL_FN xml_node xml_node::child(string_view_t name_) const
5767+
{
5768+
if (!_root) return xml_node();
5769+
5770+
for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
5771+
{
5772+
const char_t* iname = i->name;
5773+
if (iname && impl::stringview_equal(name_, iname))
5774+
return xml_node(i);
5775+
}
5776+
5777+
return xml_node();
5778+
}
5779+
5780+
PUGI_IMPL_FN xml_attribute xml_node::attribute(string_view_t name_) const
5781+
{
5782+
if (!_root) return xml_attribute();
5783+
5784+
for (xml_attribute_struct* i = _root->first_attribute; i; i = i->next_attribute)
5785+
{
5786+
const char_t* iname = i->name;
5787+
if (iname && impl::stringview_equal(name_, iname))
5788+
return xml_attribute(i);
5789+
}
5790+
5791+
return xml_attribute();
5792+
}
5793+
5794+
PUGI_IMPL_FN xml_node xml_node::next_sibling(string_view_t name_) const
5795+
{
5796+
if (!_root) return xml_node();
5797+
5798+
for (xml_node_struct* i = _root->next_sibling; i; i = i->next_sibling)
5799+
{
5800+
const char_t* iname = i->name;
5801+
if (iname && impl::stringview_equal(name_, iname))
5802+
return xml_node(i);
5803+
}
5804+
5805+
return xml_node();
5806+
}
5807+
5808+
PUGI_IMPL_FN xml_node xml_node::previous_sibling(string_view_t name_) const
5809+
{
5810+
if (!_root) return xml_node();
5811+
5812+
for (xml_node_struct* i = _root->prev_sibling_c; i->next_sibling; i = i->prev_sibling_c)
5813+
{
5814+
const char_t* iname = i->name;
5815+
if (iname && impl::stringview_equal(name_, iname))
5816+
return xml_node(i);
5817+
}
5818+
5819+
return xml_node();
5820+
}
5821+
#endif
5822+
57395823
PUGI_IMPL_FN xml_attribute xml_node::attribute(const char_t* name_, xml_attribute& hint_) const
57405824
{
57415825
xml_attribute_struct* hint = hint_._attr;
@@ -5775,6 +5859,47 @@ namespace pugi
57755859
return xml_attribute();
57765860
}
57775861

5862+
#ifdef PUGIXML_HAS_STRING_VIEW
5863+
PUGI_IMPL_FN xml_attribute xml_node::attribute(string_view_t name_, xml_attribute& hint_) const
5864+
{
5865+
xml_attribute_struct* hint = hint_._attr;
5866+
5867+
// if hint is not an attribute of node, behavior is not defined
5868+
assert(!hint || (_root && impl::is_attribute_of(hint, _root)));
5869+
5870+
if (!_root) return xml_attribute();
5871+
5872+
// optimistically search from hint up until the end
5873+
for (xml_attribute_struct* i = hint; i; i = i->next_attribute)
5874+
{
5875+
const char_t* iname = i->name;
5876+
if (iname && impl::stringview_equal(name_, iname))
5877+
{
5878+
// update hint to maximize efficiency of searching for consecutive attributes
5879+
hint_._attr = i->next_attribute;
5880+
5881+
return xml_attribute(i);
5882+
}
5883+
}
5884+
5885+
// wrap around and search from the first attribute until the hint
5886+
// 'j' null pointer check is technically redundant, but it prevents a crash in case the assertion above fails
5887+
for (xml_attribute_struct* j = _root->first_attribute; j && j != hint; j = j->next_attribute)
5888+
{
5889+
const char_t* jname = j->name;
5890+
if (jname && impl::stringview_equal(name_, jname))
5891+
{
5892+
// update hint to maximize efficiency of searching for consecutive attributes
5893+
hint_._attr = j->next_attribute;
5894+
5895+
return xml_attribute(j);
5896+
}
5897+
}
5898+
5899+
return xml_attribute();
5900+
}
5901+
#endif
5902+
57785903
PUGI_IMPL_FN xml_node xml_node::previous_sibling() const
57795904
{
57805905
if (!_root) return xml_node();
@@ -5980,6 +6105,78 @@ namespace pugi
59806105
return a;
59816106
}
59826107

6108+
#ifdef PUGIXML_HAS_STRING_VIEW
6109+
PUGI_IMPL_FN xml_attribute xml_node::append_attribute(string_view_t name_)
6110+
{
6111+
if (!impl::allow_insert_attribute(type())) return xml_attribute();
6112+
6113+
impl::xml_allocator& alloc = impl::get_allocator(_root);
6114+
if (!alloc.reserve()) return xml_attribute();
6115+
6116+
xml_attribute a(impl::allocate_attribute(alloc));
6117+
if (!a) return xml_attribute();
6118+
6119+
impl::append_attribute(a._attr, _root);
6120+
6121+
a.set_name(name_);
6122+
6123+
return a;
6124+
}
6125+
6126+
PUGI_IMPL_FN xml_attribute xml_node::prepend_attribute(string_view_t name_)
6127+
{
6128+
if (!impl::allow_insert_attribute(type())) return xml_attribute();
6129+
6130+
impl::xml_allocator& alloc = impl::get_allocator(_root);
6131+
if (!alloc.reserve()) return xml_attribute();
6132+
6133+
xml_attribute a(impl::allocate_attribute(alloc));
6134+
if (!a) return xml_attribute();
6135+
6136+
impl::prepend_attribute(a._attr, _root);
6137+
6138+
a.set_name(name_);
6139+
6140+
return a;
6141+
}
6142+
6143+
PUGI_IMPL_FN xml_attribute xml_node::insert_attribute_after(string_view_t name_, const xml_attribute& attr)
6144+
{
6145+
if (!impl::allow_insert_attribute(type())) return xml_attribute();
6146+
if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute();
6147+
6148+
impl::xml_allocator& alloc = impl::get_allocator(_root);
6149+
if (!alloc.reserve()) return xml_attribute();
6150+
6151+
xml_attribute a(impl::allocate_attribute(alloc));
6152+
if (!a) return xml_attribute();
6153+
6154+
impl::insert_attribute_after(a._attr, attr._attr, _root);
6155+
6156+
a.set_name(name_);
6157+
6158+
return a;
6159+
}
6160+
6161+
PUGI_IMPL_FN xml_attribute xml_node::insert_attribute_before(string_view_t name_, const xml_attribute& attr)
6162+
{
6163+
if (!impl::allow_insert_attribute(type())) return xml_attribute();
6164+
if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute();
6165+
6166+
impl::xml_allocator& alloc = impl::get_allocator(_root);
6167+
if (!alloc.reserve()) return xml_attribute();
6168+
6169+
xml_attribute a(impl::allocate_attribute(alloc));
6170+
if (!a) return xml_attribute();
6171+
6172+
impl::insert_attribute_before(a._attr, attr._attr, _root);
6173+
6174+
a.set_name(name_);
6175+
6176+
return a;
6177+
}
6178+
#endif
6179+
59836180
PUGI_IMPL_FN xml_attribute xml_node::append_copy(const xml_attribute& proto)
59846181
{
59856182
if (!proto) return xml_attribute();
@@ -6156,6 +6353,44 @@ namespace pugi
61566353
return result;
61576354
}
61586355

6356+
#ifdef PUGIXML_HAS_STRING_VIEW
6357+
PUGI_IMPL_FN xml_node xml_node::append_child(string_view_t name_)
6358+
{
6359+
xml_node result = append_child(node_element);
6360+
6361+
result.set_name(name_);
6362+
6363+
return result;
6364+
}
6365+
6366+
PUGI_IMPL_FN xml_node xml_node::prepend_child(string_view_t name_)
6367+
{
6368+
xml_node result = prepend_child(node_element);
6369+
6370+
result.set_name(name_);
6371+
6372+
return result;
6373+
}
6374+
6375+
PUGI_IMPL_FN xml_node xml_node::insert_child_after(string_view_t name_, const xml_node& node)
6376+
{
6377+
xml_node result = insert_child_after(node_element, node);
6378+
6379+
result.set_name(name_);
6380+
6381+
return result;
6382+
}
6383+
6384+
PUGI_IMPL_FN xml_node xml_node::insert_child_before(string_view_t name_, const xml_node& node)
6385+
{
6386+
xml_node result = insert_child_before(node_element, node);
6387+
6388+
result.set_name(name_);
6389+
6390+
return result;
6391+
}
6392+
#endif
6393+
61596394
PUGI_IMPL_FN xml_node xml_node::append_copy(const xml_node& proto)
61606395
{
61616396
xml_node_type type_ = proto.type();
@@ -6299,6 +6534,13 @@ namespace pugi
62996534
return remove_attribute(attribute(name_));
63006535
}
63016536

6537+
#ifdef PUGIXML_HAS_STRING_VIEW
6538+
PUGI_IMPL_FN bool xml_node::remove_attribute(string_view_t name_)
6539+
{
6540+
return remove_attribute(attribute(name_));
6541+
}
6542+
#endif
6543+
63026544
PUGI_IMPL_FN bool xml_node::remove_attribute(const xml_attribute& a)
63036545
{
63046546
if (!_root || !a._attr) return false;
@@ -6339,6 +6581,13 @@ namespace pugi
63396581
return remove_child(child(name_));
63406582
}
63416583

6584+
#ifdef PUGIXML_HAS_STRING_VIEW
6585+
PUGI_IMPL_FN bool xml_node::remove_child(string_view_t name_)
6586+
{
6587+
return remove_child(child(name_));
6588+
}
6589+
#endif
6590+
63426591
PUGI_IMPL_FN bool xml_node::remove_child(const xml_node& n)
63436592
{
63446593
if (!_root || !n._root || n._root->parent != _root) return false;
@@ -6935,6 +7184,14 @@ namespace pugi
69357184
return *this;
69367185
}
69377186

7187+
#ifdef PUGIXML_HAS_STRING_VIEW
7188+
PUGI_IMPL_FN xml_text& xml_text::operator=(string_view_t rhs)
7189+
{
7190+
set(rhs);
7191+
return *this;
7192+
}
7193+
#endif
7194+
69387195
#ifdef PUGIXML_HAS_LONG_LONG
69397196
PUGI_IMPL_FN xml_text& xml_text::operator=(long long rhs)
69407197
{

0 commit comments

Comments
 (0)