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
16 #include "configuration_helper.h"
17
18 #include <functional>
19
20 #include <securec.h>
21 #include <unistd.h>
22
23 #include "vpe_log.h"
24
25 using namespace OHOS::Media::VideoProcessingEngine;
26
27 namespace {
GetElementInfo(const xmlNode & parent,const std::string & tag,std::function<const std::string (const xmlNode &)> && getter)28 inline const std::string GetElementInfo(const xmlNode& parent, const std::string& tag,
29 std::function<const std::string(const xmlNode&)>&& getter)
30 {
31 const xmlNode* node = parent.children;
32 CHECK_AND_RETURN_RET_LOG(node != nullptr, "", "No children when finding <%{public}s>!", tag.c_str());
33 CHECK_AND_RETURN_RET_LOG(xmlStrcmp(node->name, reinterpret_cast<const xmlChar*>(tag.c_str())) == 0, "",
34 "Element <%{public}s> is not found!", tag.c_str());
35 return getter(*node);
36 }
37
GetElement(const xmlNode & parent,const std::string & tag,std::function<bool (const xmlNode &)> && checker,const std::string & notFoundLog)38 inline const xmlNode* GetElement(const xmlNode& parent, const std::string& tag,
39 std::function<bool(const xmlNode&)>&& checker, const std::string& notFoundLog)
40 {
41 for (const xmlNode* node = parent.children; node != nullptr; node = node->next) {
42 if (xmlStrcmp(node->name, reinterpret_cast<const xmlChar*>(tag.c_str())) != 0) {
43 continue;
44 }
45 if (checker(*node)) {
46 return node;
47 }
48 }
49 VPE_LOGW("%{public}s is NOT found!", notFoundLog.c_str());
50 return nullptr;
51 }
52 }
53
LoadConfigurationFromXml(const std::string & xmlFilePath)54 bool ConfigurationHelper::LoadConfigurationFromXml(const std::string& xmlFilePath)
55 {
56 if (access(xmlFilePath.c_str(), R_OK) != 0) [[unlikely]] {
57 VPE_LOGW("Invalid input: %{public}s is NOT exist!", xmlFilePath.c_str());
58 return false;
59 }
60
61 xmlDocPtr doc = xmlParseFile(xmlFilePath.c_str());
62 if (doc == nullptr) [[unlikely]] {
63 VPE_LOGW("Failed to parse %{public}s!", xmlFilePath.c_str());
64 return false;
65 }
66
67 xmlNode* root = xmlDocGetRootElement(doc);
68 if (root == nullptr) [[unlikely]] {
69 VPE_LOGW("Failed to parse %{public}s: there is no root element!", xmlFilePath.c_str());
70 xmlFreeDoc(doc);
71 return false;
72 }
73
74 auto ret = ParseXml(*root);
75 if (!ret) {
76 VPE_LOGW("Failed to parse %{public}s: Content is invalid!", xmlFilePath.c_str());
77 }
78 xmlFreeDoc(doc);
79 return ret;
80 }
81
ParseXml(const xmlNode & root)82 bool ConfigurationHelper::ParseXml([[maybe_unused]] const xmlNode& root)
83 {
84 return true;
85 }
86
GetElement(const xmlNode & parent,const std::string & tag) const87 const xmlNode* ConfigurationHelper::GetElement(const xmlNode& parent, const std::string& tag) const
88 {
89 return ::GetElement(parent, tag, [](const xmlNode&) { return true; }, "<" + tag + ">");
90 }
91
GetElementByName(const xmlNode & parent,const std::string & tag,const std::string & name) const92 const xmlNode* ConfigurationHelper::GetElementByName(const xmlNode& parent,
93 const std::string& tag, const std::string& name) const
94 {
95 return ::GetElement(parent, tag, [&tag, &name](const xmlNode& node) {
96 const xmlChar* nameText = xmlGetProp(&node, reinterpret_cast<const xmlChar*>("name"));
97 if (nameText == nullptr) {
98 VPE_LOGD("name of <%{public}s> is null!", tag.c_str());
99 return false;
100 }
101 return name.compare(reinterpret_cast<const char*>(nameText)) == 0;
102 }, "<" + tag + " name=\"" + name + "\">");
103 }
104
GetElementName(const xmlNode & parent,const std::string & tag) const105 const std::string ConfigurationHelper::GetElementName(const xmlNode& parent, const std::string& tag) const
106 {
107 return GetElementInfo(parent, tag, [this](const xmlNode& node) { return GetElementName(node); });
108 }
109
GetElementName(const xmlNode & myself) const110 const std::string ConfigurationHelper::GetElementName(const xmlNode& myself) const
111 {
112 const char* nameText = reinterpret_cast<char*>(xmlGetProp(&myself, reinterpret_cast<const xmlChar*>("name")));
113 CHECK_AND_RETURN_RET_LOG(nameText != nullptr, "", "name of <%{public}s> is null!", myself.name);
114 return std::string(nameText);
115 }
116
GetElementText(const xmlNode & parent,const std::string & tag) const117 const std::string ConfigurationHelper::GetElementText(const xmlNode& parent, const std::string& tag) const
118 {
119 return GetElementInfo(parent, tag, [this](const xmlNode& node) { return GetElementText(node); });
120 }
121
GetElementText(const xmlNode & myself) const122 const std::string ConfigurationHelper::GetElementText(const xmlNode& myself) const
123 {
124 const char* text = reinterpret_cast<char*>(xmlNodeGetContent(&myself));
125 CHECK_AND_RETURN_RET_LOG(text != nullptr, "", "Element <%{public}s> is empty!", myself.name);
126 return std::string(text);
127 }
128
GetElementValue(const xmlNode & parent,const std::string & tag,uint32_t & value) const129 bool ConfigurationHelper::GetElementValue(const xmlNode& parent, const std::string& tag, uint32_t& value) const
130 {
131 value = 0;
132 const std::string& text = GetElementText(parent, tag);
133 if (text.empty()) {
134 return false;
135 }
136 return sscanf_s(text.c_str(), "%u", &value) == 1;
137 }
138
GetElementValue(const xmlNode & parent,const std::string & tag,int & value) const139 bool ConfigurationHelper::GetElementValue(const xmlNode& parent, const std::string& tag, int& value) const
140 {
141 value = 0;
142 const std::string& text = GetElementText(parent, tag);
143 if (text.empty()) {
144 return false;
145 }
146 return sscanf_s(text.c_str(), "%d", &value) == 1;
147 }
148
GetElementValue(const xmlNode & parent,const std::string & tag,uint64_t & value) const149 bool ConfigurationHelper::GetElementValue(const xmlNode& parent, const std::string& tag, uint64_t& value) const
150 {
151 value = 0;
152 const std::string& text = GetElementText(parent, tag);
153 if (text.empty()) {
154 return false;
155 }
156 return sscanf_s(text.c_str(), "%lu", &value) == 1;
157 }
158
GetElementValue(const xmlNode & parent,const std::string & tag,bool & value) const159 bool ConfigurationHelper::GetElementValue(const xmlNode& parent, const std::string& tag, bool& value) const
160 {
161 const std::string& text = GetElementText(parent, tag);
162 if (text.empty()) {
163 value = false;
164 return false;
165 }
166 value = (text.compare("true") == 0);
167 return true;
168 }
169
GetElementValue(const xmlNode & parent,const std::string & tag,float & value) const170 bool ConfigurationHelper::GetElementValue(const xmlNode& parent, const std::string& tag, float& value) const
171 {
172 value = 0;
173 const std::string& text = GetElementText(parent, tag);
174 if (text.empty()) {
175 return false;
176 }
177 return sscanf_s(text.c_str(), "%f", &value) == 1;
178 }
179
GetElementValue(const xmlNode & parent,const std::string & tag,std::string & value) const180 bool ConfigurationHelper::GetElementValue(const xmlNode& parent, const std::string& tag, std::string& value) const
181 {
182 value = GetElementText(parent, tag);
183 return !value.empty();
184 }
185
GetElementValue(const xmlNode & myself,std::string & value) const186 bool ConfigurationHelper::GetElementValue(const xmlNode& myself, std::string& value) const
187 {
188 value = GetElementText(myself);
189 return !value.empty();
190 }
191