LCOV - code coverage report
Current view: top level - xml - xml_pugi.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 101 208 48.6 %
Date: 2026-06-11 01:56:02 Functions: 19 36 52.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include <boost/algorithm/string/replace.hpp>
       6             : #include "xml/xml_base.h"
       7             : #include "xml/xml_pugi.h"
       8             : #include "base/logging.h"
       9             : 
      10             : // This is internal implementation detail specific to this lib to make
      11             : // exposed methods efficient.
      12             : 
      13             : //XmlPugi::tmp_("");
      14             : pugi::xml_attribute XmlPugi::GAttr;
      15             : pugi::xml_node XmlPugi::GNode;
      16             : 
      17     4221214 : XmlPugi::XmlPugi() : writer_(this), node_(GNode), attrib_(GAttr) {
      18     4221178 : }
      19             : 
      20     8442464 : XmlPugi::~XmlPugi() {
      21     4221232 :     doc_.reset();
      22     8442468 : }
      23             : 
      24           0 : pugi::xml_node XmlPugi::RootNode() {
      25           0 :     return(doc_.root());
      26             : }
      27             : 
      28     1965116 : const char *XmlPugi::ReadNode(const std::string &name) {
      29     1965116 :     PugiPredicate p1(name);
      30             : 
      31     1965098 :     pugi::xml_node node = doc_.find_node(p1);
      32     1965102 :     if (IsNull(node)) {
      33       14385 :         return NULL;
      34             :     }
      35             : 
      36     1950711 :     SetContext(node);
      37     1950709 :     if (node.type() != pugi::node_pi) {
      38     3777324 :         for (node = node.first_child(); node; node = node.next_sibling()) {
      39             :             // traverse to first plain character data or char data,
      40             :             // skipping XML comments
      41     3653257 :             if (node.type() == pugi::node_pcdata ||
      42     1826623 :                 node.type() == pugi::node_cdata)
      43          15 :                break;
      44             :         }
      45             :     }
      46             : 
      47     1950616 :     return node.value();
      48             : 
      49     1965059 : }
      50             : 
      51     3201376 : pugi::xml_node XmlPugi::FindNode(const std::string &name) {
      52     3201376 :     PugiPredicate p1(name);
      53             : 
      54     3201375 :     pugi::xml_node node = doc_.find_node(p1);
      55     3201368 :     return node;
      56     3201369 : }
      57             : 
      58           0 : const char *XmlPugi::ReadNodeName(const std::string &name) {
      59           0 :     PugiPredicate p1(name);
      60             : 
      61           0 :     pugi::xml_node node = doc_.find_node(p1);
      62           0 :     SetContext(node);
      63             : 
      64           0 :     return node.name();
      65           0 : }
      66             : 
      67           0 : const char *XmlPugi::ReadNodeValue() {
      68           0 :     pugi::xml_node node = node_;
      69             : 
      70           0 :     if (node.type() != pugi::node_pi) {
      71           0 :         for (node = node.first_child(); node; node = node.next_sibling()) {
      72             :             // traverse to first plain character data or char data,
      73             :             // skipping XML comments
      74           0 :             if (node.type() == pugi::node_pcdata ||
      75           0 :                 node.type() == pugi::node_cdata)
      76           0 :                break;
      77             :         }
      78             :     }
      79           0 :     return node.value();
      80             : }
      81             : 
      82           0 : const char *XmlPugi::ReadChildNode() {
      83           0 :     pugi::xml_node tmp = (node_ == GNode) ? doc_.first_child() :
      84           0 :                           node_.first_child();
      85           0 :     SetContext(tmp);
      86           0 :     return tmp.value();
      87             : }
      88             : 
      89       98525 : const char *XmlPugi::ReadChildNodeName() {
      90       98525 :     pugi::xml_node tmp = (node_ == GNode) ? doc_.first_child() :
      91       98528 :                           node_.first_child();
      92       98528 :     SetContext(tmp);
      93      197056 :     return tmp.name();
      94             : }
      95             : 
      96           0 : const char *XmlPugi::ReadNextNode() {
      97           0 :     pugi::xml_node tmp = node_.next_sibling();
      98             : 
      99           0 :     SetContext(tmp);
     100           0 :     return tmp.value();
     101             : }
     102             : 
     103           0 : const char *XmlPugi::ReadNextNodeName() {
     104           0 :     pugi::xml_node tmp = node_.next_sibling();
     105             : 
     106           0 :     SetContext(tmp);
     107           0 :     return tmp.name();
     108             : }
     109             : 
     110           0 : void XmlPugi::RewindNode() {
     111           0 :     SetContext(node_);
     112           0 : }
     113             : 
     114     3909346 : const char *XmlPugi::ReadAttrib(const std::string &str) {
     115     3909346 :     pugi::xml_attribute tmp = node_.attribute(str.c_str());
     116     3909374 :     SetContext(node_, tmp);
     117     7818713 :     return tmp.value();
     118             : }
     119             : 
     120           0 : const char *XmlPugi::ReadFirstAttrib() {
     121           0 :     pugi::xml_attribute tmp = node_.first_attribute();
     122           0 :     SetContext(node_, tmp);
     123           0 :     return tmp.value();
     124             : }
     125             : 
     126           0 : const char *XmlPugi::ReadNextAttrib() {
     127           0 :     pugi::xml_attribute tmp = attrib_.next_attribute();
     128           0 :     SetContext(node_, tmp);
     129           0 :     return tmp.value();
     130             : }
     131             : 
     132           0 : void XmlPugi::RewindAttrib() {
     133           0 :     SetContext(node_, GAttr);
     134           0 : }
     135             : 
     136           0 : const char *XmlPugi::ReadParentName() {
     137           0 :     pugi::xml_node tmp = node_.parent();
     138           0 :     SetContext(tmp);
     139           0 :     return tmp.name();
     140             : }
     141             : 
     142        4445 : int XmlPugi::WriteDoc(uint8_t *buf) {
     143        4445 :     buf_tmp_ = buf; // this will be used by writer_->write
     144        4445 :     ts_ = 0;
     145        4445 :     doc_.save(writer_, "", pugi::format_default, pugi::encoding_utf8);
     146             : 
     147        4444 :     if (ts_ == 0) return -1;
     148        4444 :     return static_cast<int>(ts_);
     149             : }
     150             : 
     151           0 : int XmlPugi::WriteRawDoc(uint8_t *buf) {
     152           0 :     buf_tmp_ = buf; // this will be used by writer_->write
     153           0 :     ts_ = 0;
     154           0 :     doc_.save(writer_, "", pugi::format_raw | pugi::format_no_declaration);
     155             : 
     156           0 :     if (ts_ == 0) return -1;
     157           0 :     return static_cast<int>(ts_);
     158             : }
     159             : 
     160       15877 : void XmlPugi::PrintDoc(std::ostream& os) const {
     161       15877 :     doc_.print(os, " ", pugi::format_raw | pugi::format_no_declaration);
     162       15878 : }
     163             : 
     164           0 : void XmlPugi::PrintDocFormatted(std::ostream& os) const {
     165           0 :     doc_.print(os, " ", pugi::format_indent | pugi::format_no_declaration);
     166           0 : }
     167             : 
     168     7746415 : void XmlPugi::SetContext(pugi::xml_node node, pugi::xml_attribute attrib) {
     169     7746415 :     node_ = node;
     170     7746415 :     attrib_ = attrib;
     171     7746415 : }
     172             : 
     173     1704241 : int XmlPugi::LoadDoc(const std::string &document) {
     174     1704241 :     RewindDoc();
     175     1704236 :     doc_.reset();
     176             : 
     177     1704220 :     pugi::xml_parse_result ret = doc_.load_buffer(document.c_str(), document.size(),
     178             :                                                  pugi::parse_default,
     179             :                                                  pugi::encoding_utf8);
     180     1704254 :     if (ret == false) {
     181           0 :         LOG(DEBUG, "XML doc load failed, code: " << ret << " " << ret.description());
     182           0 :         LOG(DEBUG, "Error offset: " << ret.offset << " (error at [..." << (document.c_str() + ret.offset) << "]");
     183           0 :         LOG(DEBUG, "Document: " << document);
     184           0 :         return -1;
     185             :     }
     186     1704254 :     return 0;
     187             : }
     188             : 
     189     1704243 : void XmlPugi::RewindDoc() {
     190     1704243 :     SetContext();
     191     1704238 : }
     192             : 
     193           0 : void XmlPugi::AppendDoc(const std::string &node_name, XmlBase *a_doc) {
     194           0 :     std::string str;
     195           0 :     pugi::xml_node node_s;
     196           0 :     pugi::xml_node node1;
     197           0 :     pugi::xml_node node2;
     198             : 
     199           0 :     PugiPredicate p1(node_name);
     200           0 :     node1 = doc_.find_node(p1);
     201           0 :     SetContext(node1);
     202             : 
     203           0 :     XmlPugi *xp = static_cast<XmlPugi *>(a_doc);
     204           0 :     node_s = xp->doc_.first_child();
     205           0 :     if (!IsNull(node1)) {
     206           0 :         node2 = node1.parent().append_copy(node_s);
     207           0 :         SetContext(node2);
     208             :     }
     209             : 
     210           0 : }
     211             : 
     212         139 : int XmlPugi::AddNode(const std::string &key, const std::string &value) {
     213         139 :     pugi::xml_node node;
     214             : 
     215         139 :     if (IsNull(node_)) {
     216         139 :         node = doc_.append_child(key.c_str());
     217             :     } else {
     218           0 :         node = node_.parent().append_child(key.c_str());
     219             :     }
     220         139 :     if (value != "") {
     221           0 :         node.text().set(value.c_str());
     222             :     }
     223             : 
     224         139 :     SetContext(node);
     225         139 :     return 0;
     226             : }
     227             : 
     228         126 : int XmlPugi::DeleteNode(const std::string &key) {
     229         126 :     PugiPredicate p1(key);
     230         126 :     pugi::xml_node node = doc_.find_node(p1);
     231         126 :     if (IsNull(node))
     232           0 :         return -1;
     233             : 
     234         126 :     node.parent().remove_child(key.c_str());
     235         126 :     return 0;
     236         126 : }
     237             : 
     238           0 : int XmlPugi::ModifyNode(const std::string &key, const std::string &value) {
     239           0 :     PugiPredicate p1(key);
     240           0 :     pugi::xml_node node = doc_.find_node(p1);
     241           0 :     if (IsNull(node))
     242           0 :         return -1;
     243             : 
     244           0 :     node.text().set(value.c_str());
     245             : 
     246           0 :     SetContext(node);
     247           0 :     return 0;
     248           0 : }
     249             : 
     250         806 : int XmlPugi::AddChildNode(const std::string &key, const std::string &value) {
     251         806 :     pugi::xml_node node;
     252             : 
     253         806 :     if (IsNull(node_)) {
     254           0 :         node = doc_.append_child(key.c_str());
     255             :     } else {
     256         806 :         node = node_.append_child(key.c_str());
     257             :     }
     258         806 :     if (value != "") {
     259          12 :         node.text().set(value.c_str());
     260             :     }
     261             : 
     262         806 :     SetContext(node);
     263         806 :     return 0;
     264             : }
     265             : 
     266           0 : int XmlPugi::AddChildNodeAfter(const std::string &node_name,
     267             :                                const std::string &key,
     268             :                                const std::string &value) {
     269             : 
     270           0 :     PugiPredicate p1(node_name);
     271           0 :     pugi::xml_node node1 = doc_.find_node(p1);
     272           0 :     SetContext(node1);
     273             : 
     274           0 :     if (!IsNull(node1)) {
     275           0 :         AddChildNode(key, value);
     276             :     }
     277             : 
     278           0 :     return 0;
     279           0 : }
     280             : 
     281             : 
     282        1211 : int XmlPugi::AddAttribute(const std::string &key, const std::string &value) {
     283        1211 :     if (IsNull(node_))
     284           0 :         return -1;
     285             : 
     286        1211 :     pugi::xml_attribute attrib;
     287             : 
     288        1211 :     if (IsNull(attrib_) ) {
     289         795 :         attrib = node_.append_attribute(key.c_str()) = value.c_str();
     290             :     } else {
     291         416 :         attrib =
     292         416 :             node_.insert_attribute_after(key.c_str(), attrib_) = value.c_str();
     293             :     }
     294             : 
     295        1211 :     SetContext(node_, attrib);
     296        1211 :     return 0;
     297             : }
     298             : 
     299           0 : int XmlPugi::DeleteAttribute(const std::string &key) {
     300           0 :     if (IsNull(node_))
     301           0 :         return -1;
     302           0 :     pugi::xml_attribute tmp = node_.attribute(key.c_str());
     303             :     bool res;
     304           0 :     if (IsNull(tmp)) {
     305           0 :         return -1;
     306             :     } else {
     307           0 :          pugi::xml_attribute attrib = tmp.next_attribute();
     308           0 :          res = node_.remove_attribute(tmp);
     309           0 :          SetContext(node_, attrib);
     310           0 :          return (res ? -1 : 0);
     311             :     }
     312             :     return 0;
     313             : }
     314             : 
     315       81586 : int XmlPugi::ModifyAttribute(const std::string &key, const std::string &value) {
     316       81586 :     if (node_.type() == pugi::node_null)
     317           0 :         return -1;
     318             : 
     319             :     //ReadAttrib(key);
     320       81586 :     pugi::xml_attribute tmp = node_.attribute(key.c_str());
     321       81590 :     if (IsNull(tmp)) {
     322          28 :         return -1;
     323             :     } else {
     324       81562 :         tmp.set_value(value.c_str());
     325       81559 :         SetContext(node_, tmp);
     326             :     }
     327             : 
     328       81559 :     return 0;
     329             : }
     330             : 
     331        4444 : void XmlPugi::xmpp_buf_write::write(const void *data, size_t sz) {
     332        4444 :     ref->SetBuf(data, sz);
     333        4444 : }
     334             : 
     335        4444 : void XmlPugi::SetBuf(const void *buf, size_t sz) {
     336        4444 :     memcpy(buf_tmp_ + ts_, buf, sz);
     337        4444 :     ts_ += sz;
     338        4444 :     *(buf_tmp_+ts_) = '\0';
     339        4444 : }

Generated by: LCOV version 1.14