• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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