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 §ion, const std::string &subSection);
26 xmlNodePtr IntHasProperty(const std::string §ion, const std::string &subSection, const std::string &property);
27 void ConstructPropertyNode(xmlNodePtr §ionNode, xmlNodePtr &propertyNode, const std::string &property);
28 xmlNodePtr FindOrCreatePropertyNode(
29 const std::string §ion, 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 §ion, 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 §ion, 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 §ionNode, 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 §ion, 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 §ion, 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 §ion, 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 §ion, 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 §ion, 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 §ion, 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 §ion, 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 §ion, 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 §ion, 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 §ion, 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 §ion, 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 §ion, 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 §ion, 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 §ion, 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 §ion, 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 §ion, 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 §ion, 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 §ion, 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 §ion, 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 §ion)
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 §ion)
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 §ion, const std::string &property)
556 {
557 xmlNodePtr sectionNode = pimpl->IntHasSection(section, "");
558 return pimpl->RemoveProperty(sectionNode, property);
559 }
560 } // namespace utility