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 ¶Name)
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 if (paraName == "hfbc_config") {
156 setResult = ParseSimplex(node, mParsedData_->hfbcConfig_);
157 } else {
158 setResult = EXEC_SUCCESS;
159 }
160
161 return setResult;
162 }
163
ParseParams(xmlNode & node)164 int32_t XMLParser::ParseParams(xmlNode &node)
165 {
166 std::string paraName = ExtractPropertyValue("name", node);
167 if (paraName.empty()) {
168 return XML_PARSE_INTERNAL_FAIL;
169 }
170 if (!mParsedData_) {
171 HGM_LOGE("XMLParser mParsedData_ is not initialized");
172 return HGM_ERROR;
173 }
174
175 int32_t setResult = EXEC_SUCCESS;
176 if (paraName == "refresh_rate_4settings") {
177 std::unordered_map<std::string, std::string> refreshRateForSettings;
178 setResult = ParseSimplex(node, refreshRateForSettings);
179 if (setResult != EXEC_SUCCESS) {
180 mParsedData_->xmlCompatibleMode_ = true;
181 setResult = ParseSimplex(node, refreshRateForSettings, "id");
182 }
183 mParsedData_->refreshRateForSettings_.clear();
184 for (auto &[name, id]: refreshRateForSettings) {
185 if (IsNumber(name) && IsNumber(id)) {
186 mParsedData_->refreshRateForSettings_.emplace_back(
187 std::pair<int32_t, int32_t>(std::stoi(name), std::stoi(id)));
188 }
189 }
190 std::sort(mParsedData_->refreshRateForSettings_.begin(), mParsedData_->refreshRateForSettings_.end(),
191 [=] (auto rateId0, auto rateId1) { return rateId0.first < rateId1.first; });
192 } else {
193 setResult = ParseSubSequentParams(node, paraName);
194 }
195
196 if (setResult != EXEC_SUCCESS) {
197 HGM_LOGI("XMLParser failed to ParseParams %{public}s", paraName.c_str());
198 }
199 return EXEC_SUCCESS;
200 }
201
ParseVideoFrameVoteConfig(xmlNode & node)202 int32_t XMLParser::ParseVideoFrameVoteConfig(xmlNode &node)
203 {
204 mParsedData_->videoFrameRateVoteSwitch_ = ExtractPropertyValue("switch", node) == "1";
205 return ParseSimplex(node, mParsedData_->videoFrameRateList_);
206 }
207
ParseStrategyConfig(xmlNode & node)208 int32_t XMLParser::ParseStrategyConfig(xmlNode &node)
209 {
210 HGM_LOGD("XMLParser parsing strategyConfig");
211 xmlNode *currNode = &node;
212 if (currNode->xmlChildrenNode == nullptr) {
213 HGM_LOGD("XMLParser stop parsing strategyConfig, no children nodes");
214 return HGM_ERROR;
215 }
216
217 // re-parse
218 mParsedData_->strategyConfigs_.clear();
219 currNode = currNode->xmlChildrenNode;
220 for (; currNode; currNode = currNode->next) {
221 if (currNode->type != XML_ELEMENT_NODE) {
222 continue;
223 }
224
225 auto name = ExtractPropertyValue("name", *currNode);
226 auto min = ExtractPropertyValue("min", *currNode);
227 auto max = ExtractPropertyValue("max", *currNode);
228 auto dynamicMode = ExtractPropertyValue("dynamicMode", *currNode);
229 auto isFactor = ExtractPropertyValue("isFactor", *currNode) == "1"; // 1:true, other:false
230 auto drawMin = ExtractPropertyValue("drawMin", *currNode);
231 auto drawMax = ExtractPropertyValue("drawMax", *currNode);
232 auto down = ExtractPropertyValue("down", *currNode);
233 if (!IsNumber(min) || !IsNumber(max) || !IsNumber(dynamicMode)) {
234 return HGM_ERROR;
235 }
236
237 PolicyConfigData::StrategyConfig strategy;
238 strategy.min = std::stoi(min);
239 strategy.max = std::stoi(max);
240 strategy.dynamicMode = static_cast<DynamicModeType>(std::stoi(dynamicMode));
241 strategy.isFactor = isFactor;
242 strategy.drawMin = IsNumber(drawMin) ? std::stoi(drawMin) : 0;
243 strategy.drawMax = IsNumber(drawMax) ? std::stoi(drawMax) : 0;
244 strategy.down = IsNumber(down) ? std::stoi(down) : strategy.max;
245 ParseBufferStrategyList(*currNode, strategy);
246 mParsedData_->strategyConfigs_[name] = strategy;
247 HGM_LOGI("HgmXMLParser ParseStrategyConfig name=%{public}s min=%{public}d drawMin=%{public}d",
248 name.c_str(), mParsedData_->strategyConfigs_[name].min, mParsedData_->strategyConfigs_[name].drawMin);
249 }
250
251 return EXEC_SUCCESS;
252 }
253
ParseAppBufferList(xmlNode & node)254 void XMLParser::ParseAppBufferList(xmlNode &node)
255 {
256 HGM_LOGD("XMLParser parsing ParseAppBufferList");
257 xmlNode *currNode = &node;
258 if (currNode->xmlChildrenNode == nullptr) {
259 HGM_LOGD("XMLParser stop parsing ParseAppBufferList, no children nodes");
260 return;
261 }
262
263 mParsedData_->appBufferList_.clear();
264 currNode = currNode->xmlChildrenNode;
265 for (; currNode; currNode = currNode->next) {
266 if (currNode->type != XML_ELEMENT_NODE) {
267 continue;
268 }
269 auto name = ExtractPropertyValue("name", *currNode);
270 mParsedData_->appBufferList_.push_back(name);
271 }
272 }
273
ParseBufferStrategyList(xmlNode & node,PolicyConfigData::StrategyConfig & strategy)274 void XMLParser::ParseBufferStrategyList(xmlNode &node, PolicyConfigData::StrategyConfig &strategy)
275 {
276 if (mParsedData_->appBufferList_.empty()) {
277 return;
278 }
279 std::unordered_map<std::string, std::string> config;
280 for (auto &name : mParsedData_->appBufferList_) {
281 auto fps = ExtractPropertyValue(name, node);
282 if (IsNumber(fps)) {
283 config.insert(make_pair(name, fps));
284 }
285 }
286 if (config.empty()) {
287 return;
288 }
289 for (auto &it : config) {
290 if (std::stoi(it.second) == 0) {
291 strategy.appBufferBlackList.push_back(it.first);
292 } else {
293 strategy.appBufferList.push_back(make_pair(it.first, std::stoi(it.second)));
294 }
295 }
296 if (strategy.appBufferList.empty()) {
297 return;
298 }
299 std::sort(strategy.appBufferList.begin(), strategy.appBufferList.end(),
300 [](const std::pair<std::string, int32_t>& a, const std::pair<std::string, int32_t>& b) {
301 return a.second > b.second;
302 });
303
304 return;
305 }
306
ParseScreenConfig(xmlNode & node)307 int32_t XMLParser::ParseScreenConfig(xmlNode &node)
308 {
309 HGM_LOGD("XMLParser parsing screenConfig");
310 xmlNode *currNode = &node;
311 if (currNode->xmlChildrenNode == nullptr) {
312 HGM_LOGD("XMLParser stop parsing screenConfig, no children nodes");
313 return HGM_ERROR;
314 }
315
316 auto type = ExtractPropertyValue("type", *currNode);
317 PolicyConfigData::ScreenConfig screenConfig;
318 currNode = currNode->xmlChildrenNode;
319 for (; currNode; currNode = currNode->next) {
320 if (currNode->type != XML_ELEMENT_NODE) {
321 continue;
322 }
323 PolicyConfigData::ScreenSetting screenSetting;
324 auto id = ExtractPropertyValue("id", *currNode);
325 screenSetting.strategy = ExtractPropertyValue("strategy", *currNode);
326 for (xmlNode *thresholdNode = currNode->xmlChildrenNode; thresholdNode; thresholdNode = thresholdNode->next) {
327 ParseSubScreenConfig(*thresholdNode, screenSetting);
328 }
329 screenConfig[id] = screenSetting;
330 HGM_LOGI("HgmXMLParser ParseScreenConfig id=%{public}s", id.c_str());
331 }
332 mParsedData_->screenConfigs_[type] = screenConfig;
333 return EXEC_SUCCESS;
334 }
335
ParseSubScreenConfig(xmlNode & node,PolicyConfigData::ScreenSetting & screenSetting)336 int32_t XMLParser::ParseSubScreenConfig(xmlNode &node, PolicyConfigData::ScreenSetting& screenSetting)
337 {
338 xmlNode *thresholdNode = &node;
339 if (thresholdNode->type != XML_ELEMENT_NODE) {
340 return HGM_ERROR;
341 }
342 auto name = ExtractPropertyValue("name", *thresholdNode);
343 int32_t setResult = EXEC_SUCCESS;
344 if (name == "LTPO_config") {
345 setResult = ParseSimplex(*thresholdNode, screenSetting.ltpoConfig);
346 } else if (name == "property_animation_dynamic_settings") {
347 setResult = ParserDynamicSetting(*thresholdNode, screenSetting.animationDynamicSettings);
348 } else if (name == "ace_scene_dynamic_settings") {
349 setResult = ParserDynamicSetting(*thresholdNode, screenSetting.aceSceneDynamicSettings);
350 } else if (name == "scene_list") {
351 setResult = ParseSceneList(*thresholdNode, screenSetting.sceneList);
352 } else if (name == "game_scene_list") {
353 setResult = ParseSimplex(*thresholdNode, screenSetting.gameSceneList);
354 } else if (name == "anco_scene_list") {
355 setResult = ParseSceneList(*thresholdNode, screenSetting.ancoSceneList);
356 } else if (name == "app_list") {
357 ParseMultiAppStrategy(*thresholdNode, screenSetting);
358 } else if (name == "app_types") {
359 setResult = ParseAppTypes(*thresholdNode, screenSetting.appTypes);
360 } else if (name == "rs_animation_power_config") {
361 setResult = ParseSimplex(*thresholdNode, screenSetting.animationPowerConfig);
362 } else if (name == "ui_power_config") {
363 setResult = ParseSimplex(*thresholdNode, screenSetting.uiPowerConfig);
364 } else {
365 setResult = EXEC_SUCCESS;
366 }
367
368 if (setResult != EXEC_SUCCESS) {
369 HGM_LOGI("XMLParser failed to ParseScreenConfig %{public}s", name.c_str());
370 }
371 return setResult;
372 }
373
ParseSimplex(xmlNode & node,std::unordered_map<std::string,std::string> & config,const std::string & valueName,const std::string & keyName)374 int32_t XMLParser::ParseSimplex(xmlNode &node, std::unordered_map<std::string, std::string> &config,
375 const std::string &valueName, const std::string &keyName)
376 {
377 HGM_LOGD("XMLParser parsing simplex");
378 xmlNode *currNode = &node;
379 if (currNode->xmlChildrenNode == nullptr) {
380 HGM_LOGD("XMLParser stop parsing simplex, no children nodes");
381 return HGM_ERROR;
382 }
383
384 // re-parse
385 config.clear();
386 currNode = currNode->xmlChildrenNode;
387 for (; currNode; currNode = currNode->next) {
388 if (currNode->type != XML_ELEMENT_NODE) {
389 continue;
390 }
391
392 auto key = ExtractPropertyValue(keyName, *currNode);
393 auto value = ExtractPropertyValue(valueName, *currNode);
394 if (key.empty() || value.empty()) {
395 return XML_PARSE_INTERNAL_FAIL;
396 }
397 config[key] = value;
398
399 HGM_LOGI("HgmXMLParser ParseSimplex %{public}s=%{public}s %{public}s=%{public}s",
400 keyName.c_str(), key.c_str(), valueName.c_str(), config[key].c_str());
401 }
402
403 return EXEC_SUCCESS;
404 }
405
ParserDynamicSetting(xmlNode & node,PolicyConfigData::DynamicSettingMap & dynamicSettingMap)406 int32_t XMLParser::ParserDynamicSetting(xmlNode &node, PolicyConfigData::DynamicSettingMap &dynamicSettingMap)
407 {
408 HGM_LOGD("XMLParser parsing dynamicSetting");
409 xmlNode *currNode = &node;
410 if (currNode->xmlChildrenNode == nullptr) {
411 HGM_LOGD("XMLParser stop parsing dynamicSetting, no children nodes");
412 return HGM_ERROR;
413 }
414
415 // re-parse
416 dynamicSettingMap.clear();
417 currNode = currNode->xmlChildrenNode;
418 for (; currNode; currNode = currNode->next) {
419 auto dynamicSettingType = ExtractPropertyValue("name", *currNode);
420 PolicyConfigData::DynamicSetting dynamicSetting;
421 dynamicSettingMap[dynamicSettingType] = dynamicSetting;
422 for (xmlNode *thresholdNode = currNode->xmlChildrenNode; thresholdNode; thresholdNode = thresholdNode->next) {
423 if (thresholdNode->type != XML_ELEMENT_NODE) {
424 continue;
425 }
426 auto name = ExtractPropertyValue("name", *thresholdNode);
427 auto min = ExtractPropertyValue("min", *thresholdNode);
428 auto max = ExtractPropertyValue("max", *thresholdNode);
429 auto preferred_fps = ExtractPropertyValue("preferred_fps", *thresholdNode);
430 if (!IsNumber(min) || !IsNumber(max) || !IsNumber(preferred_fps)) {
431 dynamicSettingMap[dynamicSettingType].clear();
432 break;
433 }
434 PolicyConfigData::DynamicConfig dynamicConfig;
435 dynamicConfig.min = std::stoi(min);
436 dynamicConfig.max = std::stoi(max);
437 dynamicConfig.preferred_fps = std::stoi(preferred_fps);
438 dynamicSettingMap[dynamicSettingType][name] = dynamicConfig;
439
440 HGM_LOGI("HgmXMLParser ParserDynamicSetting dynamicType=%{public}s name=%{public}s min=%{public}d",
441 dynamicSettingType.c_str(), name.c_str(), dynamicSettingMap[dynamicSettingType][name].min);
442 }
443 }
444 return EXEC_SUCCESS;
445 }
446
ParseSceneList(xmlNode & node,PolicyConfigData::SceneConfigMap & sceneList)447 int32_t XMLParser::ParseSceneList(xmlNode &node, PolicyConfigData::SceneConfigMap &sceneList)
448 {
449 HGM_LOGD("XMLParser parsing sceneList");
450 xmlNode *currNode = &node;
451 if (currNode->xmlChildrenNode == nullptr) {
452 HGM_LOGD("XMLParser stop parsing sceneList, no children nodes");
453 return HGM_ERROR;
454 }
455
456 // re-parse
457 sceneList.clear();
458 currNode = currNode->xmlChildrenNode;
459 for (; currNode; currNode = currNode->next) {
460 if (currNode->type != XML_ELEMENT_NODE) {
461 continue;
462 }
463 PolicyConfigData::SceneConfig sceneConfig;
464 auto name = ExtractPropertyValue("name", *currNode);
465 sceneConfig.strategy = ExtractPropertyValue("strategy", *currNode);
466 sceneConfig.priority = ExtractPropertyValue("priority", *currNode);
467
468 sceneList[name] = sceneConfig;
469 HGM_LOGI("HgmXMLParser ParseSceneList name=%{public}s strategy=%{public}s priority=%{public}s",
470 name.c_str(), sceneList[name].strategy.c_str(), sceneList[name].priority.c_str());
471 }
472
473 return EXEC_SUCCESS;
474 }
475
ParseMultiAppStrategy(xmlNode & node,PolicyConfigData::ScreenSetting & screenSetting)476 int32_t XMLParser::ParseMultiAppStrategy(xmlNode &node, PolicyConfigData::ScreenSetting &screenSetting)
477 {
478 auto multiAppStrategy = ExtractPropertyValue("multi_app_strategy", node);
479 if (multiAppStrategy == "focus") {
480 screenSetting.multiAppStrategyType = MultiAppStrategyType::FOLLOW_FOCUS;
481 } else if (multiAppStrategy.find("strategy_") != std::string::npos) {
482 screenSetting.multiAppStrategyType = MultiAppStrategyType::USE_STRATEGY_NUM;
483 screenSetting.multiAppStrategyName = multiAppStrategy.substr(
484 std::string("strategy_").size(), multiAppStrategy.size());
485 } else {
486 screenSetting.multiAppStrategyType = MultiAppStrategyType::USE_MAX;
487 }
488 return ParseSimplex(node, screenSetting.appList, "strategy");
489 }
490
491
ParseAppTypes(xmlNode & node,std::unordered_map<int32_t,std::string> & appTypes)492 int32_t XMLParser::ParseAppTypes(xmlNode &node, std::unordered_map<int32_t, std::string> &appTypes)
493 {
494 HGM_LOGD("XMLParser parsing appTypes");
495 xmlNode *currNode = &node;
496 if (currNode->xmlChildrenNode == nullptr) {
497 HGM_LOGD("XMLParser stop parsing appTypes, no children nodes");
498 return HGM_ERROR;
499 }
500
501 // re-parse
502 appTypes.clear();
503 currNode = currNode->xmlChildrenNode;
504 for (; currNode; currNode = currNode->next) {
505 if (currNode->type != XML_ELEMENT_NODE) {
506 continue;
507 }
508 auto name = ExtractPropertyValue("name", *currNode);
509 if (!IsNumber(name)) {
510 continue;
511 }
512 auto strategy = ExtractPropertyValue("strategy", *currNode);
513 appTypes[std::stoi(name)] = strategy;
514 HGM_LOGI("HgmXMLParser ParseAppTypes name=%{public}s strategy=%{public}s", name.c_str(), strategy.c_str());
515 }
516
517 return EXEC_SUCCESS;
518 }
519
ExtractPropertyValue(const std::string & propName,xmlNode & node)520 std::string XMLParser::ExtractPropertyValue(const std::string &propName, xmlNode &node)
521 {
522 HGM_LOGD("XMLParser extracting value : %{public}s", propName.c_str());
523 std::string propValue = "";
524 xmlChar *tempValue = nullptr;
525
526 if (xmlHasProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()))) {
527 tempValue = xmlGetProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()));
528 }
529
530 if (tempValue != nullptr) {
531 HGM_LOGD("XMLParser not aempty tempValue");
532 propValue = reinterpret_cast<const char*>(tempValue);
533 xmlFree(tempValue);
534 tempValue = nullptr;
535 }
536
537 return propValue;
538 }
539
IsNumber(const std::string & str)540 bool XMLParser::IsNumber(const std::string& str)
541 {
542 if (str.length() == 0) {
543 return false;
544 }
545 auto number = static_cast<uint32_t>(std::count_if(str.begin(), str.end(), [](unsigned char c) {
546 return std::isdigit(c);
547 }));
548 return number == str.length() || (str.compare(0, 1, "-") == 0 && number == str.length() - 1);
549 }
550
551 } // namespace OHOS::Rosen