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 = 8;
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(std::string & fileDir)38 int32_t XMLParserBase::LoadSysConfiguration(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(std::string & fileDir)55 void XMLParserBase::LoadProdConfiguration(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(std::string & fileDir)64 int32_t XMLParserBase::LoadGraphicConfiguration(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 if (parseSuccess != PARSE_EXEC_SUCCESS) {
130 return false;
131 }
132
133 std::string featureName = ExtractPropertyValue("name", *currNode);
134 RS_LOGI("XMLParserBase featureName is: %{public}s", featureName.c_str());
135 if (featureName == "") {
136 return false;
137 }
138 auto parseMap = GraphicFeatureParamManager::GetInstance().featureParseMap_;
139 auto featureMap = GraphicFeatureParamManager::GetInstance().featureParamMap_;
140 auto iter = parseMap.find(featureName);
141 if (iter != parseMap.end()) {
142 auto featureObj = iter->second;
143 parseSuccess = featureObj->ParseFeatureParam(featureMap, *currNode);
144 } else {
145 RS_LOGD("XMLParserBase featureMap cannot find feature %{public}s", featureName.c_str());
146 }
147 }
148 return true;
149 }
150
ExtractPropertyValue(const std::string & propName,xmlNode & node)151 std::string XMLParserBase::ExtractPropertyValue(const std::string &propName, xmlNode &node)
152 {
153 RS_LOGD("XMLParserBase extracting value : %{public}s", propName.c_str());
154 std::string propValue = "";
155 xmlChar *tempValue = nullptr;
156
157 if (xmlHasProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()))) {
158 tempValue = xmlGetProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()));
159 }
160
161 if (tempValue != nullptr) {
162 RS_LOGD("XMLParserBase not a empty tempValue");
163 propValue = reinterpret_cast<const char*>(tempValue);
164 xmlFree(tempValue);
165 tempValue = nullptr;
166 }
167
168 return propValue;
169 }
170
GetXmlNodeAsInt(xmlNode & node)171 int32_t XMLParserBase::GetXmlNodeAsInt(xmlNode &node)
172 {
173 if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("FeatureSwitch"))) {
174 return PARSE_XML_FEATURE_SWITCH;
175 }
176 if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("FeatureSingleParam"))) {
177 return PARSE_XML_FEATURE_SINGLEPARAM;
178 }
179 if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("FeatureMultiParam"))) {
180 return PARSE_XML_FEATURE_MULTIPARAM;
181 }
182 RS_LOGD("XMLParserBase failed to identify a xml node : %{public}s", node.name);
183 return PARSE_XML_UNDEFINED;
184 }
185
IsNumber(const std::string & str)186 bool XMLParserBase::IsNumber(const std::string& str)
187 {
188 if (str.length() == 0 || str.length() > XML_STRING_MAX_LENGTH) {
189 return false;
190 }
191 auto number = static_cast<uint32_t>(std::count_if(str.begin(), str.end(), [](unsigned char c) {
192 return std::isdigit(c);
193 }));
194 return number == str.length() || (str.compare(0, 1, "-") == 0 && number == str.length() - 1);
195 }
196
ParseFeatureSwitch(std::string val)197 bool XMLParserBase::ParseFeatureSwitch(std::string val)
198 {
199 return val == "true";
200 }
201 } // namespace OHOS::Rosen