@@ -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