1 /*
2 * Copyright (c) 2021-2022 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 "base/resource/ace_res_key_parser.h"
17
18 #ifdef WINDOWS_PLATFORM
19 #include <cstdio>
20 #else
21 #include "securec.h"
22 #endif
23 #include <algorithm>
24 #include <functional>
25 #include <regex>
26 #include <string>
27 #include <type_traits>
28 #include <unordered_map>
29 #include <utility>
30 #include <vector>
31
32 #include "base/log/log.h"
33 #include "base/utils/string_utils.h"
34
35 namespace OHOS::Ace {
36 namespace {
37
38 constexpr int32_t MCC_MNC_KEYWORD_LEN = 3;
39 constexpr int32_t MCC_MNC_VALUE_LEN = 3;
40 constexpr int32_t MAX_MCC_MNC_LEN = 8;
41
42 const std::unordered_map<std::string, ResolutionType> RES_RESOLUTION = {
43 { "ldpi", ResolutionType::RESOLUTION_LDPI },
44 { "mdpi", ResolutionType::RESOLUTION_MDPI },
45 { "hdpi", ResolutionType::RESOLUTION_HDPI },
46 { "xhdpi", ResolutionType::RESOLUTION_XHDPI },
47 { "xxhdpi", ResolutionType::RESOLUTION_XXHDPI },
48 { "xxxhdpi", ResolutionType::RESOLUTION_XXXHDPI },
49 };
50
51 const std::unordered_map<std::string, DeviceOrientation> RES_ORIENTATION = {
52 { "horizontal", DeviceOrientation::LANDSCAPE }, { "vertical", DeviceOrientation::PORTRAIT }
53 };
54
55 const std::unordered_map<std::string, ColorMode> RES_COLOR_MODE = {
56 { "dark", ColorMode::DARK },
57 };
58
59 const std::unordered_map<std::string, ColorMode> DECLARATIVE_RES_COLOR_MODE = {
60 { "dark", ColorMode::DARK },
61 { "light", ColorMode::LIGHT },
62 };
63
64 const std::unordered_map<std::string, DeviceType> RES_DEVICE_TYPE = {
65 { "phone", DeviceType::PHONE },
66 { "tablet", DeviceType::TABLET },
67 { "tv", DeviceType::TV },
68 { "wearable", DeviceType::WATCH },
69 };
70
71 const std::unordered_map<std::string, ScreenShape> RES_SCREEN_SHAPE = {
72 { "round", ScreenShape::ROUND },
73 { "notround", ScreenShape::NOT_ROUND },
74 };
75
76 const std::unordered_map<std::string, LongScreenType> RES_LONG_SCREEN = {
77 { "long", LongScreenType::LONG },
78 { "notlong", LongScreenType::NOT_LONG },
79 };
80
81 } // namespace
82
83 AceResKeyParser::AceResKeyParser() = default;
84 AceResKeyParser::~AceResKeyParser() = default;
85
Parse(const std::string & deviceResConfigTag,std::vector<KeyParam> & keyParams,bool styleRes)86 bool AceResKeyParser::Parse(const std::string& deviceResConfigTag, std::vector<KeyParam>& keyParams, bool styleRes)
87 {
88 std::vector<std::string> keyParts;
89 StringUtils::StringSplitter(deviceResConfigTag, '-', keyParts);
90
91 static parse_key_function functions[] = {
92 ParseMcc,
93 ParseMnc,
94 ParseOrientation,
95 ParseColorMode,
96 ParseDeviceType,
97 ParseResolution,
98 ParseDefaults,
99 };
100 const int32_t FUNC_LEN = static_cast<int32_t>(sizeof(functions) / sizeof(functions[0]));
101 if (!keyParts.empty()) {
102 if (!ParseMatch(keyParts, keyParams, functions, FUNC_LEN, styleRes)) {
103 LOGE("Invalid config:%{public}s", deviceResConfigTag.c_str());
104 return false;
105 }
106 return true;
107 }
108 return false;
109 }
110
DeclarativeParse(const std::string & deviceResConfigTag,std::vector<KeyParam> & keyParams)111 bool AceResKeyParser::DeclarativeParse(const std::string& deviceResConfigTag, std::vector<KeyParam>& keyParams)
112 {
113 std::vector<std::string> reskeyParts;
114 std::string resConfigTag(deviceResConfigTag);
115 StringUtils::StringSplitter(resConfigTag, '-', reskeyParts);
116
117 static parse_key_function functions[] = {
118 ParseLongScreen,
119 ParseScreenShape,
120 ParseOrientation,
121 ParseDeclarativeColorMode,
122 ParseDeviceType,
123 ParseResolution,
124 ParseDefaults,
125 };
126 const int32_t FUNC_LEN = static_cast<int32_t>(sizeof(functions) / sizeof(functions[0]));
127 if (!reskeyParts.empty()) {
128 if (!ParseMatch(reskeyParts, keyParams, functions, FUNC_LEN, true)) {
129 LOGE("Invalid config:%{public}s", resConfigTag.c_str());
130 return false;
131 }
132 return true;
133 }
134 return false;
135 }
136
ParseMatch(const std::vector<std::string> & keys,std::vector<KeyParam> & keyParams,parse_key_function functions[],int32_t funcLen,bool styleRes) const137 bool AceResKeyParser::ParseMatch(const std::vector<std::string>& keys, std::vector<KeyParam>& keyParams,
138 parse_key_function functions[], int32_t funcLen, bool styleRes) const
139 {
140 for (auto iter = keys.begin(); iter != keys.end(); iter++) {
141 if (iter == keys.begin() && !styleRes) {
142 if (*iter == "res") {
143 continue;
144 } else {
145 LOGE("Invalid first key part:%{private}s", iter->c_str());
146 return false;
147 }
148 }
149 bool parseRet = false;
150 for (int32_t k = 0; k < funcLen; k++) {
151 if (functions[k](*iter, keyParams)) {
152 parseRet = true;
153 break;
154 }
155 }
156 if (!parseRet) {
157 LOGE("Invalid key:%{private}s", iter->c_str());
158 return false;
159 }
160 }
161 return true;
162 }
163
ParseMcc(const std::string & key,std::vector<KeyParam> & keyParams)164 bool AceResKeyParser::ParseMcc(const std::string& key, std::vector<KeyParam>& keyParams)
165 {
166 std::regex mcc("mcc(\\d{3})");
167 if (regex_match(key, mcc)) {
168 KeyParam keyParam;
169 keyParam.value = StringUtils::StringToInt(key.substr(MCC_MNC_KEYWORD_LEN));
170 keyParam.keyType = KeyType::MCC;
171 keyParams.emplace_back(keyParam);
172 return true;
173 }
174 return false;
175 }
176
ParseMnc(const std::string & key,std::vector<KeyParam> & keyParams)177 bool AceResKeyParser::ParseMnc(const std::string& key, std::vector<KeyParam>& keyParams)
178 {
179 std::regex mnc("mnc(\\d{2,3})");
180 if (regex_match(key, mnc)) {
181 KeyParam keyParam;
182 keyParam.value = StringUtils::StringToInt(key.substr(MCC_MNC_KEYWORD_LEN));
183 if (key.substr(MCC_MNC_KEYWORD_LEN).length() == MCC_MNC_VALUE_LEN) {
184 keyParam.keyType = KeyType::MNC;
185 } else {
186 keyParam.keyType = KeyType::MNC_SHORT_LEN;
187 }
188 keyParams.emplace_back(keyParam);
189 return true;
190 }
191 return false;
192 }
193
ParseScreenShape(const std::string & key,std::vector<KeyParam> & keyParams)194 bool AceResKeyParser::ParseScreenShape(const std::string& key, std::vector<KeyParam>& keyParams)
195 {
196 auto iter = RES_SCREEN_SHAPE.find(key);
197 if (iter != RES_SCREEN_SHAPE.end()) {
198 KeyParam keyParam;
199 keyParam.keyType = KeyType::SCREENSHAPE;
200 keyParam.value = static_cast<int32_t>(iter->second);
201 keyParams.emplace_back(keyParam);
202 return true;
203 }
204 return false;
205 }
206
ParseLongScreen(const std::string & key,std::vector<KeyParam> & keyParams)207 bool AceResKeyParser::ParseLongScreen(const std::string& key, std::vector<KeyParam>& keyParams)
208 {
209 auto iter = RES_LONG_SCREEN.find(key);
210 if (iter != RES_LONG_SCREEN.end()) {
211 KeyParam keyParam;
212 keyParam.keyType = KeyType::LONGSCREEN;
213 keyParam.value = static_cast<int32_t>(iter->second);
214 keyParams.emplace_back(keyParam);
215 return true;
216 }
217 return false;
218 }
219
ParseOrientation(const std::string & key,std::vector<KeyParam> & keyParams)220 bool AceResKeyParser::ParseOrientation(const std::string& key, std::vector<KeyParam>& keyParams)
221 {
222 auto iter = RES_ORIENTATION.find(key);
223 if (iter != RES_ORIENTATION.end()) {
224 KeyParam keyParam;
225 keyParam.keyType = KeyType::ORIENTATION;
226 keyParam.value = static_cast<int32_t>(iter->second);
227 keyParams.emplace_back(keyParam);
228 return true;
229 }
230 return false;
231 }
232
ParseColorMode(const std::string & key,std::vector<KeyParam> & keyParams)233 bool AceResKeyParser::ParseColorMode(const std::string& key, std::vector<KeyParam>& keyParams)
234 {
235 auto iter = RES_COLOR_MODE.find(key);
236 if (iter != RES_COLOR_MODE.end()) {
237 KeyParam keyParam;
238 keyParam.keyType = KeyType::COLOR_MODE;
239 keyParam.value = static_cast<int32_t>(iter->second);
240 keyParams.emplace_back(keyParam);
241 return true;
242 }
243 return false;
244 }
245
ParseDeclarativeColorMode(const std::string & key,std::vector<KeyParam> & keyParams)246 bool AceResKeyParser::ParseDeclarativeColorMode(const std::string& key, std::vector<KeyParam>& keyParams)
247 {
248 auto iter = DECLARATIVE_RES_COLOR_MODE.find(key);
249 if (iter != DECLARATIVE_RES_COLOR_MODE.end()) {
250 KeyParam keyParam;
251 keyParam.keyType = KeyType::DECLARATIVE_COLOR_MODE;
252 keyParam.value = static_cast<int32_t>(iter->second);
253 keyParams.emplace_back(keyParam);
254 return true;
255 }
256 return false;
257 }
258
ParseDeviceType(const std::string & key,std::vector<KeyParam> & keyParams)259 bool AceResKeyParser::ParseDeviceType(const std::string& key, std::vector<KeyParam>& keyParams)
260 {
261 auto iter = RES_DEVICE_TYPE.find(key);
262 if (iter != RES_DEVICE_TYPE.end()) {
263 KeyParam keyParam;
264 keyParam.keyType = KeyType::DEVICETYPE;
265 keyParam.value = static_cast<int32_t>(iter->second);
266 keyParams.emplace_back(keyParam);
267 return true;
268 }
269 return false;
270 }
271
ParseResolution(const std::string & key,std::vector<KeyParam> & keyParams)272 bool AceResKeyParser::ParseResolution(const std::string& key, std::vector<KeyParam>& keyParams)
273 {
274 auto iter = RES_RESOLUTION.find(key);
275 if (iter != RES_RESOLUTION.end()) {
276 KeyParam keyParam;
277 keyParam.keyType = KeyType::RESOLUTION;
278 keyParam.value = static_cast<int32_t>(iter->second);
279 keyParams.emplace_back(keyParam);
280 return true;
281 }
282 return false;
283 }
284
ParseDefaults(const std::string & key,std::vector<KeyParam> & keyParams)285 bool AceResKeyParser::ParseDefaults(const std::string& key, std::vector<KeyParam>& keyParams)
286 {
287 return key == "defaults" || key == "default";
288 }
289
GetMccByValue(uint32_t value) const290 std::string AceResKeyParser::GetMccByValue(uint32_t value) const
291 {
292 char mccStr[MAX_MCC_MNC_LEN] = { 0 };
293 if (sprintf_s(mccStr, MAX_MCC_MNC_LEN, "mcc%03u", value) < 0) {
294 LOGE("output mcc exception");
295 return "";
296 }
297 return std::string(mccStr);
298 }
299
GetMncShortLenByValue(uint32_t value) const300 std::string AceResKeyParser::GetMncShortLenByValue(uint32_t value) const
301 {
302 char mncStr[MAX_MCC_MNC_LEN] = { 0 };
303 if (sprintf_s(mncStr, MAX_MCC_MNC_LEN, "mnc%02u", value) < 0) {
304 LOGE("output mnc short len exception");
305 return "";
306 }
307 return std::string(mncStr);
308 }
309
GetMncByValue(uint32_t value) const310 std::string AceResKeyParser::GetMncByValue(uint32_t value) const
311 {
312 char mncStr[MAX_MCC_MNC_LEN] = { 0 };
313 if (sprintf_s(mncStr, MAX_MCC_MNC_LEN, "mnc%03u", value) < 0) {
314 LOGE("output mnc len exception");
315 return "";
316 }
317 return std::string(mncStr);
318 }
319
GetOrientationByType(DeviceOrientation type) const320 std::string AceResKeyParser::GetOrientationByType(DeviceOrientation type) const
321 {
322 auto item =
323 find_if(RES_ORIENTATION.begin(), RES_ORIENTATION.end(), [type](auto iter) { return iter.second == type; });
324 if (item != RES_ORIENTATION.end()) {
325 return item->first;
326 }
327 return "";
328 }
329
GetColorModeByType(ColorMode type) const330 std::string AceResKeyParser::GetColorModeByType(ColorMode type) const
331 {
332 auto item =
333 find_if(RES_COLOR_MODE.begin(), RES_COLOR_MODE.end(), [type](auto iter) { return iter.second == type; });
334 if (item != RES_COLOR_MODE.end()) {
335 return item->first;
336 }
337 return "";
338 }
339
GetDeclarativeColorModeByType(ColorMode type) const340 std::string AceResKeyParser::GetDeclarativeColorModeByType(ColorMode type) const
341 {
342 auto item = find_if(DECLARATIVE_RES_COLOR_MODE.begin(), DECLARATIVE_RES_COLOR_MODE.end(),
343 [type](auto iter) { return iter.second == type; });
344 if (item != DECLARATIVE_RES_COLOR_MODE.end()) {
345 return item->first;
346 }
347 return "";
348 }
349
GetDeviceByType(DeviceType type) const350 std::string AceResKeyParser::GetDeviceByType(DeviceType type) const
351 {
352 auto deviceTypeItem =
353 find_if(RES_DEVICE_TYPE.begin(), RES_DEVICE_TYPE.end(), [type](auto iter) { return iter.second == type; });
354 if (deviceTypeItem != RES_DEVICE_TYPE.end()) {
355 return deviceTypeItem->first;
356 }
357 return "";
358 }
359
GetResolutionByType(ResolutionType type) const360 std::string AceResKeyParser::GetResolutionByType(ResolutionType type) const
361 {
362 auto resolutionItem =
363 find_if(RES_RESOLUTION.begin(), RES_RESOLUTION.end(), [type](auto iter) { return iter.second == type; });
364 if (resolutionItem != RES_RESOLUTION.end()) {
365 return resolutionItem->first;
366 }
367 return "";
368 }
GetScreenShapeByType(ScreenShape type) const369 std::string AceResKeyParser::GetScreenShapeByType(ScreenShape type) const
370 {
371 auto shapeItem =
372 find_if(RES_SCREEN_SHAPE.begin(), RES_SCREEN_SHAPE.end(), [type](auto iter) { return iter.second == type; });
373 if (shapeItem != RES_SCREEN_SHAPE.end()) {
374 return shapeItem->first;
375 }
376 return "";
377 }
378
GetScreenLongByType(LongScreenType type) const379 std::string AceResKeyParser::GetScreenLongByType(LongScreenType type) const
380 {
381 auto longItem =
382 find_if(RES_LONG_SCREEN.begin(), RES_LONG_SCREEN.end(), [type](auto iter) { return iter.second == type; });
383 if (longItem != RES_LONG_SCREEN.end()) {
384 return longItem->first;
385 }
386 return "";
387 }
388
389 } // namespace OHOS::Ace