1 /*
2 * Copyright (c) 2025 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_base.h"
16
17 #include <algorithm>
18 #include "graphic_feature_param_manager.h"
19
20 namespace OHOS::Rosen {
21 namespace {
22 constexpr uint32_t XML_STRING_MAX_LENGTH = 20;
23 }
24
Destroy()25 void XMLParserBase::Destroy()
26 {
27 RS_LOGD("XMLParserBase Destroying the parser");
28 if (xmlSysDocument_ != nullptr) {
29 xmlFreeDoc(xmlSysDocument_);
30 xmlSysDocument_ = nullptr;
31 }
32 if (xmlProdDocument_ != nullptr) {
33 xmlFreeDoc(xmlProdDocument_);
34 xmlProdDocument_ = nullptr;
35 }
36 }
37
LoadSysConfiguration(const std::string & fileDir)38 int32_t XMLParserBase::LoadSysConfiguration(const std::string& fileDir)
39 {
40 for (const std::string& configPath : sysPaths_) {
41 std::string graphicFilePath = configPath + fileDir;
42 xmlSysDocument_ = xmlReadFile(graphicFilePath.c_str(), nullptr, 0);
43 if (xmlSysDocument_ != nullptr) {
44 RS_LOGD("XMLParserBase success to get sys graphic config: %{public}s", graphicFilePath.c_str());
45 break;
46 }
47 }
48 if (!xmlSysDocument_) {
49 RS_LOGE("XMLParserBase read system file failed");
50 return PARSE_SYS_FILE_LOAD_FAIL;
51 }
52 return PARSE_EXEC_SUCCESS;
53 }
54
LoadProdConfiguration(const std::string & fileDir)55 void XMLParserBase::LoadProdConfiguration(const std::string& fileDir)
56 {
57 std::string graphicFilePath = prodPath_ + fileDir;
58 xmlProdDocument_ = xmlReadFile(graphicFilePath.c_str(), nullptr, 0);
59 if (!xmlProdDocument_) {
60 RS_LOGD("XMLParserBase not have prod graphic config: %{public}s", graphicFilePath.c_str());
61 }
62 }
63
LoadGraphicConfiguration(const std::string & fileDir)64 int32_t XMLParserBase::LoadGraphicConfiguration(const std::string& fileDir)
65 {
66 RS_LOGI("XMLParserBase opening xml file");
67 // System base config file read
68 if (LoadSysConfiguration(fileDir) != PARSE_EXEC_SUCCESS) {
69 return PARSE_SYS_FILE_LOAD_FAIL;
70 }
71 // For different feature settings in variant products
72 LoadProdConfiguration(fileDir);
73 return PARSE_EXEC_SUCCESS;
74 }
75
ParseSysDoc()76 int32_t XMLParserBase::ParseSysDoc()
77 {
78 RS_LOGI("XMLParserBase Parse SysDoc Start");
79 if (!xmlSysDocument_) {
80 RS_LOGE("XMLParserBase xmlSysDocument_ is empty, should do LoadGraphicConfiguration first");
81 return PARSE_SYS_FILE_LOAD_FAIL;
82 }
83 xmlNode *root = xmlDocGetRootElement(xmlSysDocument_);
84 if (root == nullptr) {
85 RS_LOGE("XMLParserBase xmlDocGetRootElement failed");
86 return PARSE_GET_ROOT_FAIL;
87 }
88
89 if (ParseInternal(*root) == false) {
90 return PARSE_INTERNAL_FAIL;
91 }
92 return PARSE_EXEC_SUCCESS;
93 }
94
ParseProdDoc()95 int32_t XMLParserBase::ParseProdDoc()
96 {
97 RS_LOGI("XMLParserBase Parse ProdDoc Start");
98 if (!xmlProdDocument_) {
99 RS_LOGD("XMLParserBase xmlProdDocument_ is empty, check if need product config first");
100 return PARSE_PROD_FILE_LOAD_FAIL;
101 }
102 xmlNode *root = xmlDocGetRootElement(xmlProdDocument_);
103 if (root == nullptr) {
104 RS_LOGE("XMLParserBase xmlDocGetRootElement failed");
105 return PARSE_GET_ROOT_FAIL;
106 }
107
108 if (ParseInternal(*root) == false) {
109 return PARSE_INTERNAL_FAIL;
110 }
111 return PARSE_EXEC_SUCCESS;
112 }
113
ParseInternal(xmlNode & node)114 bool XMLParserBase::ParseInternal(xmlNode &node)
115 {
116 RS_LOGI("XMLParserBase ParseInternal Start");
117 xmlNode *currNode = &node;
118 if (currNode->xmlChildrenNode == nullptr) {
119 RS_LOGD("XMLParserBase stop parsing internal, no children nodes");
120 return false;
121 }
122 currNode = currNode->xmlChildrenNode;
123 int32_t parseSuccess = PARSE_EXEC_SUCCESS;
124
125 for (; currNode; currNode = currNode->next) {
126 if (currNode->type != XML_ELEMENT_NODE) {
127 continue;
128 }
129
130 std::string featureName = ExtractPropertyValue("name", *currNode);
131 RS_LOGI("XMLParserBase featureName is: %{public}s", featureName.c_str());
132 if (featureName == "") {
133 RS_LOGE("XMLParserBase featureName is empty");
134 continue;
135 }
136 auto parseMap = GraphicFeatureParamManager::GetInstance().featureParseMap_;
137 auto featureMap = GraphicFeatureParamManager::GetInstance().featureParamMap_;
138 auto iter = parseMap.find(featureName);
139 if (iter != parseMap.end()) {
140 auto featureObj = iter->second;
141 parseSuccess = featureObj->ParseFeatureParam(featureMap, *currNode);
142 if (parseSuccess != PARSE_EXEC_SUCCESS) {
143 RS_LOGE("XMLParserBase current feature : %{public}s parse fail", featureName.c_str());
144 continue;
145 }
146 } else {
147 RS_LOGD("XMLParserBase featureMap cannot find feature %{public}s", featureName.c_str());
148 }
149 }
150 return true;
151 }
152
ExtractPropertyValue(const std::string & propName,xmlNode & node)153 std::string XMLParserBase::ExtractPropertyValue(const std::string &propName, xmlNode &node)
154 {
155 RS_LOGD("XMLParserBase extracting value : %{public}s", propName.c_str());
156 std::string propValue = "";
157 xmlChar *tempValue = nullptr;
158
159 if (xmlHasProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()))) {
160 tempValue = xmlGetProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()));
161 }
162
163 if (tempValue != nullptr) {
164 RS_LOGD("XMLParserBase not a empty tempValue");
165 propValue = reinterpret_cast<const char*>(tempValue);
166 xmlFree(tempValue);
167 tempValue = nullptr;
168 }
169
170 return propValue;
171 }
172
GetXmlNodeAsInt(xmlNode & node)173 int32_t XMLParserBase::GetXmlNodeAsInt(xmlNode &node)
174 {
175 if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("FeatureSwitch"))) {
176 return PARSE_XML_FEATURE_SWITCH;
177 }
178 if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("FeatureSingleParam"))) {
179 return PARSE_XML_FEATURE_SINGLEPARAM;
180 }
181 if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("FeatureMultiParam"))) {
182 return PARSE_XML_FEATURE_MULTIPARAM;
183 }
184 RS_LOGD("XMLParserBase failed to identify a xml node : %{public}s", node.name);
185 return PARSE_XML_UNDEFINED;
186 }
187
IsNumber(const std::string & str)188 bool XMLParserBase::IsNumber(const std::string& str)
189 {
190 if (str.length() == 0 || str.length() > XML_STRING_MAX_LENGTH) {
191 return false;
192 }
193 auto number = static_cast<uint32_t>(std::count_if(str.begin(), str.end(), [](unsigned char c) {
194 return std::isdigit(c);
195 }));
196 return number == str.length() || (str.compare(0, 1, "-") == 0 && number == str.length() - 1);
197 }
198
ParseFeatureSwitch(std::string val)199 bool XMLParserBase::ParseFeatureSwitch(std::string val)
200 {
201 return val == "true";
202 }
203 } // namespace OHOS::Rosen
204