• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "xml_parse.h"
17 #include <algorithm>
18 #include <sstream>
19 #include <libxml/parser.h>
20 #include <libxml/tree.h>
21 
22 namespace utility {
23 struct XmlParse::impl {
24     xmlDocPtr doc_;
25     xmlNodePtr IntHasSection(const std::string &section, const std::string &subSection);
26     xmlNodePtr IntHasProperty(const std::string &section, const std::string &subSection, const std::string &property);
27     void ConstructPropertyNode(xmlNodePtr &sectionNode, xmlNodePtr &propertyNode, const std::string &property);
28     xmlNodePtr FindOrCreatePropertyNode(
29         const std::string &section, const std::string &subSection, const std::string &property);
30     bool GetValue(xmlNodePtr node, int &value);
31     bool GetValue(xmlNodePtr node, std::string &value);
32     bool GetValue(xmlNodePtr node, bool &value);
33     bool HasProperty(xmlNodePtr node, const std::string &property);
34     bool RemoveProperty(xmlNodePtr node, const std::string &property);
35 };
36 
IntHasSection(const std::string & section,const std::string & subSection)37 xmlNodePtr XmlParse::impl::IntHasSection(const std::string &section, const std::string &subSection)
38 {
39     xmlNodePtr rootNode = xmlDocGetRootElement(doc_);
40     xmlNodePtr getSectionNode = NULL;
41     if (rootNode == NULL) {
42         return NULL;
43     }
44     for (xmlNodePtr btSectionNode = rootNode->children; btSectionNode; btSectionNode = btSectionNode->next) {
45         xmlChar *btSectionNodeProp = xmlGetProp(btSectionNode, BAD_CAST "section");
46         if (xmlStrcmp((xmlChar *)section.c_str(), btSectionNodeProp) == 0) {
47             getSectionNode = btSectionNode;
48         }
49         xmlFree(btSectionNodeProp);
50     }
51 
52     if (subSection == "") {
53         return getSectionNode;
54     }
55     if (getSectionNode == NULL) {
56         return NULL;
57     }
58     for (xmlNodePtr btSubSectionNode = getSectionNode->children; btSubSectionNode;
59             btSubSectionNode = btSubSectionNode->next) {
60         xmlChar *btSubSectionNodeProp = xmlGetProp(btSubSectionNode, BAD_CAST "section");
61         if (xmlStrcmp((xmlChar *)subSection.c_str(), btSubSectionNodeProp) == 0) {
62             xmlFree(btSubSectionNodeProp);
63             return btSubSectionNode;
64         }
65         xmlFree(btSubSectionNodeProp);
66     }
67     return NULL;
68 }
69 
IntHasProperty(const std::string & section,const std::string & subSection,const std::string & property)70 xmlNodePtr XmlParse::impl::IntHasProperty(
71     const std::string &section, const std::string &subSection, const std::string &property)
72 {
73     xmlNodePtr sectionNode = IntHasSection(section, subSection);
74     if ((sectionNode != NULL) && (sectionNode->children)) {
75         for (xmlNodePtr btPropertyNode = sectionNode->children; btPropertyNode;
76                 btPropertyNode = btPropertyNode->next) {
77             xmlChar *btPropertyNodeProp = xmlGetProp(btPropertyNode, BAD_CAST "property");
78             if (xmlStrcmp((xmlChar *)property.c_str(), btPropertyNodeProp) == 0) {
79                 xmlFree(btPropertyNodeProp);
80                 return btPropertyNode;
81             }
82             xmlFree(btPropertyNodeProp);
83         }
84     }
85     return NULL;
86 }
87 
ConstructPropertyNode(xmlNodePtr & sectionNode,xmlNodePtr & propertyNode,const std::string & property)88 void XmlParse::impl::ConstructPropertyNode(
89     xmlNodePtr &sectionNode, xmlNodePtr &propertyNode, const std::string &property)
90 {
91     for (propertyNode = sectionNode->children; propertyNode; propertyNode = propertyNode->next) {
92         xmlChar *propertyNodeProp = xmlGetProp(propertyNode, BAD_CAST "property");
93         if (xmlStrcmp((xmlChar *)property.c_str(), propertyNodeProp) == 0) {
94             xmlFree(propertyNodeProp);
95             break;
96         }
97         xmlFree(propertyNodeProp);
98     }
99     if (propertyNode == NULL) {
100         propertyNode = xmlNewNode(NULL, BAD_CAST "T1");
101         xmlSetProp(propertyNode, BAD_CAST "property", (xmlChar *)property.c_str());
102         xmlAddChild(sectionNode, propertyNode);
103     }
104 }
105 
FindOrCreatePropertyNode(const std::string & section,const std::string & subSection,const std::string & property)106 xmlNodePtr XmlParse::impl::FindOrCreatePropertyNode(
107     const std::string &section, const std::string &subSection, const std::string &property)
108 {
109     xmlNodePtr rootNode = xmlDocGetRootElement(doc_);
110     xmlNodePtr sectionNode = NULL;
111     xmlNodePtr subSectionNode = NULL;
112     xmlNodePtr propertyNode = NULL;
113 
114     if (rootNode == NULL) {
115         return NULL;
116     }
117     if (rootNode->children != NULL) {
118         for (sectionNode = rootNode->children; sectionNode; sectionNode = sectionNode->next) {
119             xmlChar *sectionNodeProp = xmlGetProp(sectionNode, BAD_CAST "section");
120             if (xmlStrcmp((xmlChar *)section.c_str(), sectionNodeProp) == 0) {
121                 xmlFree(sectionNodeProp);
122                 break;
123             }
124             xmlFree(sectionNodeProp);
125         }
126     }
127 
128     if (sectionNode == NULL) {
129         sectionNode = xmlNewNode(NULL, BAD_CAST "T1");
130         xmlSetProp(sectionNode, BAD_CAST "section", (xmlChar *)section.c_str());
131         xmlAddChild(rootNode, sectionNode);
132     }
133 
134     if (subSection != "") {
135         for (subSectionNode = sectionNode->children; subSectionNode; subSectionNode = subSectionNode->next) {
136             xmlChar *subSectionNodeProp = xmlGetProp(subSectionNode, BAD_CAST "section");
137             if (xmlStrcmp((xmlChar *)subSection.c_str(), subSectionNodeProp) == 0) {
138                 xmlFree(subSectionNodeProp);
139                 break;
140             }
141             xmlFree(subSectionNodeProp);
142         }
143         if (!subSectionNode) {
144             subSectionNode = xmlNewNode(NULL, BAD_CAST "T1");
145             xmlSetProp(subSectionNode, BAD_CAST "section", (xmlChar *)subSection.c_str());
146             xmlAddChild(sectionNode, subSectionNode);
147         }
148         ConstructPropertyNode(subSectionNode, propertyNode, property);
149     } else {
150         ConstructPropertyNode(sectionNode, propertyNode, property);
151     }
152     return propertyNode;
153 }
154 
GetValue(xmlNodePtr node,int & value)155 bool XmlParse::impl::GetValue(xmlNodePtr node, int &value)
156 {
157     if (node == NULL) {
158         return false;
159     }
160     xmlChar *nodeContent = xmlNodeGetContent(node->children);
161     if (nodeContent == NULL) {
162         return false;
163     }
164     std::string nodeContentStr = (char *)nodeContent;
165     std::string sValue = nodeContentStr;
166     sValue = sValue.substr(SIZEOF_0X, sValue.size() - SIZEOF_0X);
167     value = std::stol(sValue, nullptr, BASE_16);
168     xmlFree(nodeContent);
169     return true;
170 }
171 
GetValue(xmlNodePtr node,std::string & value)172 bool XmlParse::impl::GetValue(xmlNodePtr node, std::string &value)
173 {
174     if (node == NULL) {
175         return false;
176     }
177     xmlChar *nodeContent = xmlNodeGetContent(node->children);
178     if (nodeContent == NULL) {
179         return false;
180     }
181     value = (char *)nodeContent;
182     xmlFree(nodeContent);
183     return true;
184 }
185 
GetValue(xmlNodePtr node,bool & value)186 bool XmlParse::impl::GetValue(xmlNodePtr node, bool &value)
187 {
188     if (node == NULL) {
189         return false;
190     }
191     xmlChar *nodeContent = xmlNodeGetContent(node->children);
192     if (nodeContent == NULL) {
193         return false;
194     }
195     bool retVal = true;
196     std::string sValue = (char *)nodeContent;
197     if (sValue == "true") {
198         value = true;
199     } else if (sValue == "false") {
200         value = false;
201     } else {
202         retVal = false;
203     }
204     xmlFree(nodeContent);
205     return retVal;
206 }
207 
HasProperty(xmlNodePtr node,const std::string & property)208 bool XmlParse::impl::HasProperty(xmlNodePtr node, const std::string &property)
209 {
210     if (node == NULL) {
211         return false;
212     }
213     for (xmlNodePtr btPropertyNode = node->children; btPropertyNode; btPropertyNode = btPropertyNode->next) {
214         xmlChar *btPropertyNodeProp = xmlGetProp(btPropertyNode, BAD_CAST "property");
215         if (xmlStrcmp((xmlChar *)property.c_str(), btPropertyNodeProp) == 0) {
216             xmlFree(btPropertyNodeProp);
217             return true;
218         }
219         xmlFree(btPropertyNodeProp);
220     }
221     return false;
222 }
223 
RemoveProperty(xmlNodePtr node,const std::string & property)224 bool XmlParse::impl::RemoveProperty(xmlNodePtr node, const std::string &property)
225 {
226     if (node == NULL) {
227         return false;
228     }
229     xmlNodePtr propertyNode = NULL;
230     for (propertyNode = node->children; propertyNode; propertyNode = propertyNode->next) {
231         xmlChar *propertyNodeProp = xmlGetProp(propertyNode, BAD_CAST "property");
232         if (xmlStrcmp((xmlChar *)property.c_str(), propertyNodeProp) == 0) {
233             xmlFree(propertyNodeProp);
234             break;
235         }
236         xmlFree(propertyNodeProp);
237     }
238     if (propertyNode == NULL) {
239         return false;
240     }
241     xmlUnlinkNode(propertyNode);
242     xmlFreeNode(propertyNode);
243     return true;
244 }
245 
XmlParse()246 XmlParse::XmlParse() : pimpl()
247 {
248     pimpl = std::make_unique<impl>();
249     pimpl->doc_ = NULL;
250 }
251 
~XmlParse()252 XmlParse::~XmlParse()
253 {
254     xmlFreeDoc(pimpl->doc_);
255 }
256 
Load(const std::string & path)257 bool XmlParse::Load(const std::string &path)
258 {
259     this->filePath_ = path;
260     return Parse();
261 }
262 
Parse()263 bool XmlParse::Parse()
264 {
265     if (pimpl->doc_ != NULL) {
266         xmlFreeDoc(pimpl->doc_);
267     }
268     pimpl->doc_ = xmlReadFile(this->filePath_.c_str(), "UTF-8", XML_PARSE_NOBLANKS);
269     if (pimpl->doc_ == NULL) {
270         return false;
271     }
272     return true;
273 }
274 
Save()275 bool XmlParse::Save()
276 {
277     int result = xmlSaveFormatFileEnc(this->filePath_.c_str(), pimpl->doc_, "UTF-8", 1);
278     if (result == -1) {
279         return false;
280     }
281     return true;
282 }
283 
GetValue(const std::string & section,const std::string & subSection,const std::string & property,int & value)284 bool XmlParse::GetValue(
285     const std::string &section, const std::string &subSection, const std::string &property, int &value)
286 {
287     xmlNodePtr getPropertyNode = pimpl->IntHasProperty(section, subSection, property);
288     return pimpl->GetValue(getPropertyNode, value);
289 }
290 
GetValue(const std::string & section,const std::string & subSection,const std::string & property,std::string & value)291 bool XmlParse::GetValue(
292     const std::string &section, const std::string &subSection, const std::string &property, std::string &value)
293 {
294     xmlNodePtr getPropertyNode = pimpl->IntHasProperty(section, subSection, property);
295     return pimpl->GetValue(getPropertyNode, value);
296 }
297 
GetValue(const std::string & section,const std::string & subSection,const std::string & property,bool & value)298 bool XmlParse::GetValue(
299     const std::string &section, const std::string &subSection, const std::string &property, bool &value)
300 {
301     xmlNodePtr getPropertyNode = pimpl->IntHasProperty(section, subSection, property);
302     return pimpl->GetValue(getPropertyNode, value);
303 }
304 
SetValue(const std::string & section,const std::string & subSection,const std::string & property,const int & value)305 bool XmlParse::SetValue(
306     const std::string &section, const std::string &subSection, const std::string &property, const int &value)
307 {
308     xmlNodePtr propertyNode = pimpl->FindOrCreatePropertyNode(section, subSection, property);
309     std::string storeVal = "0x";
310     std::stringstream ss;
311     ss << std::hex << value;
312     std::string convertVal = ss.str();
313     std::transform(convertVal.begin(), convertVal.end(), convertVal.begin(), ::toupper);
314     storeVal += convertVal;
315     xmlNodeSetContent(propertyNode, (xmlChar *)storeVal.c_str());
316     return true;
317 }
318 
SetValue(const std::string & section,const std::string & subSection,const std::string & property,const std::string & value)319 bool XmlParse::SetValue(
320     const std::string &section, const std::string &subSection, const std::string &property, const std::string &value)
321 {
322     xmlNodePtr propertyNode = pimpl->FindOrCreatePropertyNode(section, subSection, property);
323     xmlNodeSetContent(propertyNode, (xmlChar *)value.c_str());
324     return true;
325 }
326 
SetValue(const std::string & section,const std::string & subSection,const std::string & property,const bool & value)327 bool XmlParse::SetValue(
328     const std::string &section, const std::string &subSection, const std::string &property, const bool &value)
329 {
330     xmlNodePtr propertyNode = pimpl->FindOrCreatePropertyNode(section, subSection, property);
331     if (propertyNode == NULL) {
332         return false;
333     }
334     if (value) {
335         xmlNodeSetContent(propertyNode, BAD_CAST "true");
336     } else {
337         xmlNodeSetContent(propertyNode, BAD_CAST "false");
338     }
339     return true;
340 }
341 
HasProperty(const std::string & section,const std::string & subSection,const std::string & property)342 bool XmlParse::HasProperty(const std::string &section, const std::string &subSection, const std::string &property)
343 {
344     xmlNodePtr sectionNode = pimpl->IntHasSection(section, subSection);
345     return pimpl->HasProperty(sectionNode, property);
346 }
347 
HasSection(const std::string & section,const std::string & subSection)348 bool XmlParse::HasSection(const std::string &section, const std::string &subSection)
349 {
350     xmlNodePtr rootNode = xmlDocGetRootElement(pimpl->doc_);
351     if (rootNode == NULL) {
352         return false;
353     }
354     xmlNodePtr btSectionNode = rootNode->children;
355     xmlNodePtr btSubSectionNode = NULL;
356     for (; btSectionNode; btSectionNode = btSectionNode->next) {
357         xmlChar *btSectionNodeProp = xmlGetProp(btSectionNode, BAD_CAST "section");
358         if (xmlStrcmp((xmlChar *)section.c_str(), btSectionNodeProp) == 0) {
359             btSubSectionNode = btSectionNode->children;
360             xmlFree(btSectionNodeProp);
361             break;
362         }
363         xmlFree(btSectionNodeProp);
364     }
365     if (btSectionNode != NULL) {
366         for (; btSubSectionNode; btSubSectionNode = btSubSectionNode->next) {
367             xmlChar *btSubSectionNodeProp = xmlGetProp(btSubSectionNode, BAD_CAST "section");
368             if (xmlStrcmp((xmlChar *)subSection.c_str(), btSubSectionNodeProp) == 0) {
369                 xmlFree(btSubSectionNodeProp);
370                 return true;
371             }
372             xmlFree(btSubSectionNodeProp);
373         }
374     }
375     return false;
376 }
377 
GetSubSections(const std::string & section,std::vector<std::string> & subSections)378 bool XmlParse::GetSubSections(const std::string &section, std::vector<std::string> &subSections)
379 {
380     std::string btSubSectionNodePropStr;
381     xmlNodePtr rootNode = xmlDocGetRootElement(pimpl->doc_);
382     if (rootNode == NULL) {
383         return false;
384     }
385     for (xmlNodePtr btSectionNode = rootNode->children; btSectionNode; btSectionNode = btSectionNode->next) {
386         xmlChar *btSectionNodeProp = xmlGetProp(btSectionNode, BAD_CAST "section");
387         if (xmlStrcmp((xmlChar *)section.c_str(), btSectionNodeProp) == 0) {
388             if (btSectionNode == NULL) {
389                 return false;
390             }
391             for (xmlNodePtr btSubSectionNode = btSectionNode->children; btSubSectionNode;
392                  btSubSectionNode = btSubSectionNode->next) {
393                 xmlChar *btSubSectionNodeProp = xmlGetProp(btSubSectionNode, BAD_CAST "section");
394                 if (btSubSectionNodeProp == NULL) {
395                     continue;
396                 }
397                 btSubSectionNodePropStr = (char *)btSubSectionNodeProp;
398                 subSections.push_back(btSubSectionNodePropStr);
399                 xmlFree(btSubSectionNodeProp);
400             }
401         }
402         xmlFree(btSectionNodeProp);
403     }
404     if (subSections.size() == 0) {
405         return false;
406     }
407     return true;
408 }
409 
RemoveSection(const std::string & section,const std::string & subSection)410 bool XmlParse::RemoveSection(const std::string &section, const std::string &subSection)
411 {
412     xmlNodePtr rootNode = xmlDocGetRootElement(pimpl->doc_);
413     xmlNodePtr sectionNode = NULL;
414 
415     if (rootNode == NULL) {
416         return false;
417     }
418     for (sectionNode = rootNode->children; sectionNode; sectionNode = sectionNode->next) {
419         xmlChar *sectionNodeProp = xmlGetProp(sectionNode, BAD_CAST "section");
420         if (xmlStrcmp((xmlChar *)section.c_str(), sectionNodeProp) == 0) {
421             xmlFree(sectionNodeProp);
422             break;
423         }
424         xmlFree(sectionNodeProp);
425     }
426 
427     if (sectionNode == NULL) {
428         return false;
429     }
430 
431     xmlNodePtr subSectionNode = NULL;
432 
433     for (subSectionNode = sectionNode->children; subSectionNode; subSectionNode = subSectionNode->next) {
434         xmlChar *subSectionNodeProp = xmlGetProp(subSectionNode, BAD_CAST "section");
435         if (xmlStrcmp((xmlChar *)subSection.c_str(), subSectionNodeProp) == 0) {
436             xmlFree(subSectionNodeProp);
437             break;
438         }
439         xmlFree(subSectionNodeProp);
440     }
441     if (subSectionNode == NULL) {
442         return false;
443     }
444     xmlUnlinkNode(subSectionNode);
445     xmlFreeNode(subSectionNode);
446     return true;
447 }
448 
RemoveProperty(const std::string & section,const std::string & subSection,const std::string & property)449 bool XmlParse::RemoveProperty(const std::string &section, const std::string &subSection, const std::string &property)
450 {
451     xmlNodePtr sectionNode = pimpl->IntHasSection(section, subSection);
452     return pimpl->RemoveProperty(sectionNode, property);
453 }
454 
GetValue(const std::string & section,const std::string & property,int & value)455 bool XmlParse::GetValue(const std::string &section, const std::string &property, int &value)
456 {
457     xmlNodePtr getPropertyNode = pimpl->IntHasProperty(section, "", property);
458     return pimpl->GetValue(getPropertyNode, value);
459 }
460 
GetValue(const std::string & section,const std::string & property,std::string & value)461 bool XmlParse::GetValue(const std::string &section, const std::string &property, std::string &value)
462 {
463     xmlNodePtr getPropertyNode = pimpl->IntHasProperty(section, "", property);
464     return pimpl->GetValue(getPropertyNode, value);
465 }
466 
GetValue(const std::string & section,const std::string & property,bool & value)467 bool XmlParse::GetValue(const std::string &section, const std::string &property, bool &value)
468 {
469     xmlNodePtr getPropertyNode = pimpl->IntHasProperty(section, "", property);
470     return pimpl->GetValue(getPropertyNode, value);
471 }
472 
SetValue(const std::string & section,const std::string & property,const int & value)473 bool XmlParse::SetValue(const std::string &section, const std::string &property, const int &value)
474 {
475     xmlNodePtr propertyNode = pimpl->FindOrCreatePropertyNode(section, "", property);
476     std::string storeVal = "0x";
477     std::stringstream ss;
478     ss << std::hex << value;
479     std::string convertVal = ss.str();
480     std::transform(convertVal.begin(), convertVal.end(), convertVal.begin(), ::toupper);
481     storeVal += convertVal;
482     xmlNodeSetContent(propertyNode, (xmlChar *)storeVal.c_str());
483     return true;
484 }
485 
SetValue(const std::string & section,const std::string & property,const std::string & value)486 bool XmlParse::SetValue(const std::string &section, const std::string &property, const std::string &value)
487 {
488     xmlNodePtr propertyNode = pimpl->FindOrCreatePropertyNode(section, "", property);
489     xmlNodeSetContent(propertyNode, (xmlChar *)value.c_str());
490     return true;
491 }
492 
SetValue(const std::string & section,const std::string & property,const bool & value)493 bool XmlParse::SetValue(const std::string &section, const std::string &property, const bool &value)
494 {
495     xmlNodePtr propertyNode = pimpl->FindOrCreatePropertyNode(section, "", property);
496     if (propertyNode == NULL) {
497         return false;
498     }
499     if (value) {
500         xmlNodeSetContent(propertyNode, BAD_CAST "true");
501     } else {
502         xmlNodeSetContent(propertyNode, BAD_CAST "false");
503     }
504     return true;
505 }
506 
HasProperty(const std::string & section,const std::string & property)507 bool XmlParse::HasProperty(const std::string &section, const std::string &property)
508 {
509     xmlNodePtr sectionNode = pimpl->IntHasSection(section, "");
510     return pimpl->HasProperty(sectionNode, property);
511 }
512 
HasSection(const std::string & section)513 bool XmlParse::HasSection(const std::string &section)
514 {
515     xmlNodePtr rootNode = xmlDocGetRootElement(pimpl->doc_);
516     if (rootNode == NULL) {
517         return false;
518     }
519     for (xmlNodePtr btSectionNode = rootNode->children; btSectionNode; btSectionNode = btSectionNode->next) {
520         xmlChar *btSectionNodeProp = xmlGetProp(btSectionNode, BAD_CAST "section");
521         if (xmlStrcmp((xmlChar *)section.c_str(), btSectionNodeProp) == 0) {
522             xmlFree(btSectionNodeProp);
523             return true;
524         }
525         xmlFree(btSectionNodeProp);
526     }
527 
528     return false;
529 }
530 
RemoveSection(const std::string & section)531 bool XmlParse::RemoveSection(const std::string &section)
532 {
533     xmlNodePtr rootNode = xmlDocGetRootElement(pimpl->doc_);
534     xmlNodePtr sectionNode = NULL;
535 
536     if (rootNode == NULL) {
537         return false;
538     }
539     for (sectionNode = rootNode->children; sectionNode; sectionNode = sectionNode->next) {
540         xmlChar *sectionNodeProp = xmlGetProp(sectionNode, BAD_CAST "section");
541         if (xmlStrcmp((xmlChar *)section.c_str(), sectionNodeProp) == 0) {
542             xmlFree(sectionNodeProp);
543             break;
544         }
545         xmlFree(sectionNodeProp);
546     }
547     if (sectionNode == NULL) {
548         return false;
549     }
550     xmlUnlinkNode(sectionNode);
551     xmlFreeNode(sectionNode);
552     return true;
553 }
554 
RemoveProperty(const std::string & section,const std::string & property)555 bool XmlParse::RemoveProperty(const std::string &section, const std::string &property)
556 {
557     xmlNodePtr sectionNode = pimpl->IntHasSection(section, "");
558     return pimpl->RemoveProperty(sectionNode, property);
559 }
560 }  // namespace utility