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

Generated by: LCOV version 1.14