1 /*
2  * Copyright (c) 2023 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 #include "xml_parser.h"
16 #include <algorithm>
17 
18 #include "config_policy_utils.h"
19 
20 namespace OHOS::Rosen {
LoadConfiguration(const char * fileDir)21 int32_t XMLParser::LoadConfiguration(const char* fileDir)
22 {
23     HGM_LOGI("XMLParser opening xml file");
24     xmlDocument_ = xmlReadFile(fileDir, nullptr, 0);
25     if (!xmlDocument_) {
26         HGM_LOGE("XMLParser xmlReadFile failed");
27         return XML_FILE_LOAD_FAIL;
28     }
29 
30     if (!mParsedData_) {
31         mParsedData_ = std::make_unique<PolicyConfigData>();
32     }
33 
34     return EXEC_SUCCESS;
35 }
36 
Parse()37 int32_t XMLParser::Parse()
38 {
39     HGM_LOGD("XMLParser Parse");
40     if (!xmlDocument_) {
41         HGM_LOGE("XMLParser xmlDocument_ is empty, should do LoadConfiguration first");
42         return HGM_ERROR;
43     }
44     xmlNode *root = xmlDocGetRootElement(xmlDocument_);
45     if (root == nullptr) {
46         HGM_LOGE("XMLParser xmlDocGetRootElement failed");
47         return XML_GET_ROOT_FAIL;
48     }
49 
50     if (ParseInternal(*root) == false) {
51         return XML_PARSE_INTERNAL_FAIL;
52     }
53     return EXEC_SUCCESS;
54 }
55 
Destroy()56 void XMLParser::Destroy()
57 {
58     HGM_LOGD("XMLParser Destroying the parser");
59     if (xmlDocument_ != nullptr) {
60         xmlFreeDoc(xmlDocument_);
61         xmlDocument_ = nullptr;
62     }
63 }
64 
GetHgmXmlNodeAsInt(xmlNode & node)65 int32_t XMLParser::GetHgmXmlNodeAsInt(xmlNode &node)
66 {
67     if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("Param"))) {
68         return HGM_XML_PARAM;
69     }
70     if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("Params"))) {
71         return HGM_XML_PARAMS;
72     }
73     HGM_LOGD("XMLParser failed to identify a xml node : %{public}s", node.name);
74     return HGM_XML_UNDEFINED;
75 }
76 
ParseInternal(xmlNode & node)77 bool XMLParser::ParseInternal(xmlNode &node)
78 {
79     HGM_LOGD("XMLParser parsing an internal node");
80     xmlNode *currNode = &node;
81     if (currNode->xmlChildrenNode == nullptr) {
82         HGM_LOGD("XMLParser stop parsing internal, no children nodes");
83         return false;
84     }
85     currNode = currNode->xmlChildrenNode;
86     int32_t parseSuccess = EXEC_SUCCESS;
87 
88     for (; currNode; currNode = currNode->next) {
89         if (currNode->type != XML_ELEMENT_NODE) {
90             continue;
91         }
92         if (parseSuccess != EXEC_SUCCESS) {
93             return false;
94         }
95         int xmlParamType = GetHgmXmlNodeAsInt(*currNode);
96         if (xmlParamType == HGM_XML_PARAM) {
97             parseSuccess = ParseParam(*currNode);
98         } else if (xmlParamType == HGM_XML_PARAMS) {
99             parseSuccess = ParseParams(*currNode);
100         }
101     }
102     return true;
103 }
104 
ParseParam(xmlNode & node)105 int32_t XMLParser::ParseParam(xmlNode &node)
106 {
107     HGM_LOGI("XMLParser parsing a parameter");
108     if (!mParsedData_) {
109         HGM_LOGE("XMLParser mParsedData_ is not initialized");
110         return HGM_ERROR;
111     }
112 
113     std::string paraName = ExtractPropertyValue("name", node);
114     if (paraName == "default_refreshrate_mode") {
115         HGM_LOGD("XMLParser parsing default_refreshrate_mode");
116         std::string mode = ExtractPropertyValue("value", node);
117         mParsedData_->defaultRefreshRateMode_ = mode;
118 
119         HGM_LOGI("HgmXMLParser ParseParam default_refreshrate_mode %{public}s",
120                  mParsedData_->defaultRefreshRateMode_.c_str());
121     }
122 
123     return EXEC_SUCCESS;
124 }
125 
ParseSubSequentParams(xmlNode & node,std::string & paraName)126 int32_t XMLParser::ParseSubSequentParams(xmlNode &node, std::string &paraName)
127 {
128     int32_t setResult = EXEC_SUCCESS;
129 
130     if (paraName == "additional_touch_rate_config") {
131         ParseAppBufferList(node);
132     } else if (paraName == "refreshRate_strategy_config") {
133         setResult = ParseStrategyConfig(node);
134     } else if (paraName == "refreshRate_virtual_display_config") {
135         if (ExtractPropertyValue("switch", node) == "1") {
136             setResult = ParseSimplex(node, mParsedData_->virtualDisplayConfigs_, "strategy");
137             mParsedData_->virtualDisplaySwitch_ = true;
138         } else {
139             mParsedData_->virtualDisplayConfigs_.clear();
140             mParsedData_->virtualDisplaySwitch_ = false;
141         }
142     } else if (paraName == "safe_vote") {
143         // "1": enable
144         mParsedData_->safeVoteEnabled = ExtractPropertyValue("switch", node) == "1";
145     } else if (paraName == "screen_strategy_config") {
146         setResult = ParseSimplex(node, mParsedData_->screenStrategyConfigs_, "type");
147     } else if (paraName == "screen_config") {
148         setResult = ParseScreenConfig(node);
149     } else if (paraName == "rs_video_frame_rate_vote_config") {
150         setResult = ParseVideoFrameVoteConfig(node);
151     } else if (paraName == "source_tuning_for_yuv420") {
152         setResult = ParseSimplex(node, mParsedData_->sourceTuningConfig_);
153     } else if (paraName == "rs_solid_color_layer_config") {
154         setResult = ParseSimplex(node, mParsedData_->solidLayerConfig_);
155     } else {
156         setResult = EXEC_SUCCESS;
157     }
158 
159     return setResult;
160 }
161 
ParseParams(xmlNode & node)162 int32_t XMLParser::ParseParams(xmlNode &node)
163 {
164     std::string paraName = ExtractPropertyValue("name", node);
165     if (paraName.empty()) {
166         return XML_PARSE_INTERNAL_FAIL;
167     }
168     if (!mParsedData_) {
169         HGM_LOGE("XMLParser mParsedData_ is not initialized");
170         return HGM_ERROR;
171     }
172 
173     int32_t setResult = EXEC_SUCCESS;
174     if (paraName == "refresh_rate_4settings") {
175         std::unordered_map<std::string, std::string> refreshRateForSettings;
176         setResult = ParseSimplex(node, refreshRateForSettings);
177         if (setResult != EXEC_SUCCESS) {
178             mParsedData_->xmlCompatibleMode_ = true;
179             setResult = ParseSimplex(node, refreshRateForSettings, "id");
180         }
181         mParsedData_->refreshRateForSettings_.clear();
182         for (auto &[name, id]: refreshRateForSettings) {
183             if (IsNumber(name) && IsNumber(id)) {
184                 mParsedData_->refreshRateForSettings_.emplace_back(
185                     std::pair<int32_t, int32_t>(std::stoi(name), std::stoi(id)));
186             }
187         }
188         std::sort(mParsedData_->refreshRateForSettings_.begin(), mParsedData_->refreshRateForSettings_.end(),
189             [=] (auto rateId0, auto rateId1) { return rateId0.first < rateId1.first; });
190     } else {
191         setResult = ParseSubSequentParams(node, paraName);
192     }
193 
194     if (setResult != EXEC_SUCCESS) {
195         HGM_LOGI("XMLParser failed to ParseParams %{public}s", paraName.c_str());
196     }
197     return EXEC_SUCCESS;
198 }
199 
ParseVideoFrameVoteConfig(xmlNode & node)200 int32_t XMLParser::ParseVideoFrameVoteConfig(xmlNode &node)
201 {
202     mParsedData_->videoFrameRateVoteSwitch_ = ExtractPropertyValue("switch", node) == "1";
203     return ParseSimplex(node, mParsedData_->videoFrameRateList_);
204 }
205 
ParseStrategyConfig(xmlNode & node)206 int32_t XMLParser::ParseStrategyConfig(xmlNode &node)
207 {
208     HGM_LOGD("XMLParser parsing strategyConfig");
209     xmlNode *currNode = &node;
210     if (currNode->xmlChildrenNode == nullptr) {
211         HGM_LOGD("XMLParser stop parsing strategyConfig, no children nodes");
212         return HGM_ERROR;
213     }
214 
215     // re-parse
216     mParsedData_->strategyConfigs_.clear();
217     currNode = currNode->xmlChildrenNode;
218     for (; currNode; currNode = currNode->next) {
219         if (currNode->type != XML_ELEMENT_NODE) {
220             continue;
221         }
222 
223         auto name = ExtractPropertyValue("name", *currNode);
224         auto min = ExtractPropertyValue("min", *currNode);
225         auto max = ExtractPropertyValue("max", *currNode);
226         auto dynamicMode = ExtractPropertyValue("dynamicMode", *currNode);
227         auto isFactor = ExtractPropertyValue("isFactor", *currNode) == "1"; // 1:true, other:false
228         auto drawMin = ExtractPropertyValue("drawMin", *currNode);
229         auto drawMax = ExtractPropertyValue("drawMax", *currNode);
230         auto down = ExtractPropertyValue("down", *currNode);
231         if (!IsNumber(min) || !IsNumber(max) || !IsNumber(dynamicMode)) {
232             return HGM_ERROR;
233         }
234 
235         PolicyConfigData::StrategyConfig strategy;
236         strategy.min = std::stoi(min);
237         strategy.max = std::stoi(max);
238         strategy.dynamicMode = static_cast<DynamicModeType>(std::stoi(dynamicMode));
239         strategy.isFactor = isFactor;
240         strategy.drawMin = IsNumber(drawMin) ? std::stoi(drawMin) : 0;
241         strategy.drawMax = IsNumber(drawMax) ? std::stoi(drawMax) : 0;
242         strategy.down = IsNumber(down) ? std::stoi(down) : strategy.max;
243         ParseBufferStrategyList(*currNode, strategy);
244         mParsedData_->strategyConfigs_[name] = strategy;
245         HGM_LOGI("HgmXMLParser ParseStrategyConfig name=%{public}s min=%{public}d drawMin=%{public}d",
246                  name.c_str(), mParsedData_->strategyConfigs_[name].min, mParsedData_->strategyConfigs_[name].drawMin);
247     }
248 
249     return EXEC_SUCCESS;
250 }
251 
ParseAppBufferList(xmlNode & node)252 void XMLParser::ParseAppBufferList(xmlNode &node)
253 {
254     HGM_LOGD("XMLParser parsing ParseAppBufferList");
255     xmlNode *currNode = &node;
256     if (currNode->xmlChildrenNode == nullptr) {
257         HGM_LOGD("XMLParser stop parsing ParseAppBufferList, no children nodes");
258         return;
259     }
260 
261     mParsedData_->appBufferList_.clear();
262     currNode = currNode->xmlChildrenNode;
263     for (; currNode; currNode = currNode->next) {
264         if (currNode->type != XML_ELEMENT_NODE) {
265             continue;
266         }
267         auto name = ExtractPropertyValue("name", *currNode);
268         mParsedData_->appBufferList_.push_back(name);
269     }
270 }
271 
ParseBufferStrategyList(xmlNode & node,PolicyConfigData::StrategyConfig & strategy)272 void XMLParser::ParseBufferStrategyList(xmlNode &node, PolicyConfigData::StrategyConfig &strategy)
273 {
274     if (mParsedData_->appBufferList_.empty()) {
275         return;
276     }
277     std::unordered_map<std::string, std::string> config;
278     for (auto &name : mParsedData_->appBufferList_) {
279         auto fps = ExtractPropertyValue(name, node);
280         if (IsNumber(fps)) {
281             config.insert(make_pair(name, fps));
282         }
283     }
284     if (config.empty()) {
285         return;
286     }
287     for (auto &it : config) {
288         if (std::stoi(it.second) == 0) {
289             strategy.appBufferBlackList.push_back(it.first);
290         } else {
291             strategy.appBufferList.push_back(make_pair(it.first, std::stoi(it.second)));
292         }
293     }
294     if (strategy.appBufferList.empty()) {
295         return;
296     }
297     std::sort(strategy.appBufferList.begin(), strategy.appBufferList.end(),
298         [](const std::pair<std::string, int32_t>& a, const std::pair<std::string, int32_t>& b) {
299         return a.second > b.second;
300     });
301 
302     return;
303 }
304 
ParseScreenConfig(xmlNode & node)305 int32_t XMLParser::ParseScreenConfig(xmlNode &node)
306 {
307     HGM_LOGD("XMLParser parsing screenConfig");
308     xmlNode *currNode = &node;
309     if (currNode->xmlChildrenNode == nullptr) {
310         HGM_LOGD("XMLParser stop parsing screenConfig, no children nodes");
311         return HGM_ERROR;
312     }
313 
314     auto type = ExtractPropertyValue("type", *currNode);
315     PolicyConfigData::ScreenConfig screenConfig;
316     currNode = currNode->xmlChildrenNode;
317     for (; currNode; currNode = currNode->next) {
318         if (currNode->type != XML_ELEMENT_NODE) {
319             continue;
320         }
321         PolicyConfigData::ScreenSetting screenSetting;
322         auto id = ExtractPropertyValue("id", *currNode);
323         screenSetting.strategy = ExtractPropertyValue("strategy", *currNode);
324         for (xmlNode *thresholdNode = currNode->xmlChildrenNode; thresholdNode; thresholdNode = thresholdNode->next) {
325             ParseSubScreenConfig(*thresholdNode, screenSetting);
326         }
327         screenConfig[id] = screenSetting;
328         HGM_LOGI("HgmXMLParser ParseScreenConfig id=%{public}s", id.c_str());
329     }
330     mParsedData_->screenConfigs_[type] = screenConfig;
331     return EXEC_SUCCESS;
332 }
333 
ParseSubScreenConfig(xmlNode & node,PolicyConfigData::ScreenSetting & screenSetting)334 int32_t XMLParser::ParseSubScreenConfig(xmlNode &node, PolicyConfigData::ScreenSetting& screenSetting)
335 {
336     xmlNode *thresholdNode = &node;
337     if (thresholdNode->type != XML_ELEMENT_NODE) {
338         return HGM_ERROR;
339     }
340     auto name = ExtractPropertyValue("name", *thresholdNode);
341     int32_t setResult = EXEC_SUCCESS;
342     if (name == "LTPO_config") {
343         setResult = ParseSimplex(*thresholdNode, screenSetting.ltpoConfig);
344     } else if (name == "property_animation_dynamic_settings") {
345         setResult = ParserDynamicSetting(*thresholdNode, screenSetting.animationDynamicSettings);
346     } else if (name == "ace_scene_dynamic_settings") {
347         setResult = ParserDynamicSetting(*thresholdNode, screenSetting.aceSceneDynamicSettings);
348     } else if (name == "scene_list") {
349         setResult = ParseSceneList(*thresholdNode, screenSetting.sceneList);
350     } else if (name == "game_scene_list") {
351         setResult = ParseSimplex(*thresholdNode, screenSetting.gameSceneList);
352     } else if (name == "anco_scene_list") {
353         setResult = ParseSceneList(*thresholdNode, screenSetting.ancoSceneList);
354     } else if (name == "app_list") {
355         ParseMultiAppStrategy(*thresholdNode, screenSetting);
356     } else if (name == "app_types") {
357         setResult = ParseAppTypes(*thresholdNode, screenSetting.appTypes);
358     } else if (name == "rs_animation_power_config") {
359         setResult = ParseSimplex(*thresholdNode, screenSetting.animationPowerConfig);
360     } else if (name == "ui_power_config") {
361         setResult = ParseSimplex(*thresholdNode, screenSetting.uiPowerConfig);
362     } else {
363         setResult = EXEC_SUCCESS;
364     }
365 
366     if (setResult != EXEC_SUCCESS) {
367         HGM_LOGI("XMLParser failed to ParseScreenConfig %{public}s", name.c_str());
368     }
369     return setResult;
370 }
371 
ParseSimplex(xmlNode & node,std::unordered_map<std::string,std::string> & config,const std::string & valueName,const std::string & keyName)372 int32_t XMLParser::ParseSimplex(xmlNode &node, std::unordered_map<std::string, std::string> &config,
373                                 const std::string &valueName, const std::string &keyName)
374 {
375     HGM_LOGD("XMLParser parsing simplex");
376     xmlNode *currNode = &node;
377     if (currNode->xmlChildrenNode == nullptr) {
378         HGM_LOGD("XMLParser stop parsing simplex, no children nodes");
379         return HGM_ERROR;
380     }
381 
382     // re-parse
383     config.clear();
384     currNode = currNode->xmlChildrenNode;
385     for (; currNode; currNode = currNode->next) {
386         if (currNode->type != XML_ELEMENT_NODE) {
387             continue;
388         }
389 
390         auto key = ExtractPropertyValue(keyName, *currNode);
391         auto value = ExtractPropertyValue(valueName, *currNode);
392         if (key.empty() || value.empty()) {
393             return XML_PARSE_INTERNAL_FAIL;
394         }
395         config[key] = value;
396 
397         HGM_LOGI("HgmXMLParser ParseSimplex %{public}s=%{public}s %{public}s=%{public}s",
398                  keyName.c_str(), key.c_str(), valueName.c_str(), config[key].c_str());
399     }
400 
401     return EXEC_SUCCESS;
402 }
403 
ParserDynamicSetting(xmlNode & node,PolicyConfigData::DynamicSettingMap & dynamicSettingMap)404 int32_t XMLParser::ParserDynamicSetting(xmlNode &node, PolicyConfigData::DynamicSettingMap &dynamicSettingMap)
405 {
406     HGM_LOGD("XMLParser parsing dynamicSetting");
407     xmlNode *currNode = &node;
408     if (currNode->xmlChildrenNode == nullptr) {
409         HGM_LOGD("XMLParser stop parsing dynamicSetting, no children nodes");
410         return HGM_ERROR;
411     }
412 
413     // re-parse
414     dynamicSettingMap.clear();
415     currNode = currNode->xmlChildrenNode;
416     for (; currNode; currNode = currNode->next) {
417         auto dynamicSettingType = ExtractPropertyValue("name", *currNode);
418         PolicyConfigData::DynamicSetting dynamicSetting;
419         dynamicSettingMap[dynamicSettingType] = dynamicSetting;
420         for (xmlNode *thresholdNode = currNode->xmlChildrenNode; thresholdNode; thresholdNode = thresholdNode->next) {
421             if (thresholdNode->type != XML_ELEMENT_NODE) {
422                 continue;
423             }
424             auto name = ExtractPropertyValue("name", *thresholdNode);
425             auto min = ExtractPropertyValue("min", *thresholdNode);
426             auto max = ExtractPropertyValue("max", *thresholdNode);
427             auto preferred_fps = ExtractPropertyValue("preferred_fps", *thresholdNode);
428             if (!IsNumber(min) || !IsNumber(max) || !IsNumber(preferred_fps)) {
429                 dynamicSettingMap[dynamicSettingType].clear();
430                 break;
431             }
432             PolicyConfigData::DynamicConfig dynamicConfig;
433             dynamicConfig.min = std::stoi(min);
434             dynamicConfig.max = std::stoi(max);
435             dynamicConfig.preferred_fps = std::stoi(preferred_fps);
436             dynamicSettingMap[dynamicSettingType][name] = dynamicConfig;
437 
438             HGM_LOGI("HgmXMLParser ParserDynamicSetting dynamicType=%{public}s name=%{public}s min=%{public}d",
439                      dynamicSettingType.c_str(), name.c_str(), dynamicSettingMap[dynamicSettingType][name].min);
440         }
441     }
442     return EXEC_SUCCESS;
443 }
444 
ParseSceneList(xmlNode & node,PolicyConfigData::SceneConfigMap & sceneList)445 int32_t XMLParser::ParseSceneList(xmlNode &node, PolicyConfigData::SceneConfigMap &sceneList)
446 {
447     HGM_LOGD("XMLParser parsing sceneList");
448     xmlNode *currNode = &node;
449     if (currNode->xmlChildrenNode == nullptr) {
450         HGM_LOGD("XMLParser stop parsing sceneList, no children nodes");
451         return HGM_ERROR;
452     }
453 
454     // re-parse
455     sceneList.clear();
456     currNode = currNode->xmlChildrenNode;
457     for (; currNode; currNode = currNode->next) {
458         if (currNode->type != XML_ELEMENT_NODE) {
459             continue;
460         }
461         PolicyConfigData::SceneConfig sceneConfig;
462         auto name = ExtractPropertyValue("name", *currNode);
463         sceneConfig.strategy = ExtractPropertyValue("strategy", *currNode);
464         sceneConfig.priority = ExtractPropertyValue("priority", *currNode);
465 
466         sceneList[name] = sceneConfig;
467         HGM_LOGI("HgmXMLParser ParseSceneList name=%{public}s strategy=%{public}s priority=%{public}s",
468                  name.c_str(), sceneList[name].strategy.c_str(), sceneList[name].priority.c_str());
469     }
470 
471     return EXEC_SUCCESS;
472 }
473 
ParseMultiAppStrategy(xmlNode & node,PolicyConfigData::ScreenSetting & screenSetting)474 int32_t XMLParser::ParseMultiAppStrategy(xmlNode &node, PolicyConfigData::ScreenSetting &screenSetting)
475 {
476     auto multiAppStrategy = ExtractPropertyValue("multi_app_strategy", node);
477     if (multiAppStrategy == "focus") {
478         screenSetting.multiAppStrategyType = MultiAppStrategyType::FOLLOW_FOCUS;
479     } else if (multiAppStrategy.find("strategy_") != std::string::npos) {
480         screenSetting.multiAppStrategyType = MultiAppStrategyType::USE_STRATEGY_NUM;
481         screenSetting.multiAppStrategyName = multiAppStrategy.substr(
482             std::string("strategy_").size(), multiAppStrategy.size());
483     } else {
484         screenSetting.multiAppStrategyType = MultiAppStrategyType::USE_MAX;
485     }
486     return ParseSimplex(node, screenSetting.appList, "strategy");
487 }
488 
489 
ParseAppTypes(xmlNode & node,std::unordered_map<int32_t,std::string> & appTypes)490 int32_t XMLParser::ParseAppTypes(xmlNode &node, std::unordered_map<int32_t, std::string> &appTypes)
491 {
492     HGM_LOGD("XMLParser parsing appTypes");
493     xmlNode *currNode = &node;
494     if (currNode->xmlChildrenNode == nullptr) {
495         HGM_LOGD("XMLParser stop parsing appTypes, no children nodes");
496         return HGM_ERROR;
497     }
498 
499     // re-parse
500     appTypes.clear();
501     currNode = currNode->xmlChildrenNode;
502     for (; currNode; currNode = currNode->next) {
503         if (currNode->type != XML_ELEMENT_NODE) {
504             continue;
505         }
506         auto name = ExtractPropertyValue("name", *currNode);
507         if (!IsNumber(name)) {
508             continue;
509         }
510         auto strategy = ExtractPropertyValue("strategy", *currNode);
511         appTypes[std::stoi(name)] = strategy;
512         HGM_LOGI("HgmXMLParser ParseAppTypes name=%{public}s strategy=%{public}s", name.c_str(), strategy.c_str());
513     }
514 
515     return EXEC_SUCCESS;
516 }
517 
ExtractPropertyValue(const std::string & propName,xmlNode & node)518 std::string XMLParser::ExtractPropertyValue(const std::string &propName, xmlNode &node)
519 {
520     HGM_LOGD("XMLParser extracting value : %{public}s", propName.c_str());
521     std::string propValue = "";
522     xmlChar *tempValue = nullptr;
523 
524     if (xmlHasProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()))) {
525         tempValue = xmlGetProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()));
526     }
527 
528     if (tempValue != nullptr) {
529         HGM_LOGD("XMLParser not aempty tempValue");
530         propValue = reinterpret_cast<const char*>(tempValue);
531         xmlFree(tempValue);
532         tempValue = nullptr;
533     }
534 
535     return propValue;
536 }
537 
IsNumber(const std::string & str)538 bool XMLParser::IsNumber(const std::string& str)
539 {
540     if (str.length() == 0) {
541         return false;
542     }
543     auto number = static_cast<uint32_t>(std::count_if(str.begin(), str.end(), [](unsigned char c) {
544         return std::isdigit(c);
545     }));
546     return number == str.length() || (str.compare(0, 1, "-") == 0 && number == str.length() - 1);
547 }
548 
549 } // namespace OHOS::Rosen