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 LOGW("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 LOGW("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 return false;
146 }
147 }
148 bool parseRet = false;
149 for (int32_t k = 0; k < funcLen; k++) {
150 if (functions[k](*iter, keyParams)) {
151 parseRet = true;
152 break;
153 }
154 }
155 if (!parseRet) {
156 return false;
157 }
158 }
159 return true;
160 }
161
ParseMcc(const std::string & key,std::vector<KeyParam> & keyParams)162 bool AceResKeyParser::ParseMcc(const std::string& key, std::vector<KeyParam>& keyParams)
163 {
164 std::regex mcc("mcc(\\d{3})");
165 if (regex_match(key, mcc)) {
166 KeyParam keyParam;
167 keyParam.value = StringUtils::StringToInt(key.substr(MCC_MNC_KEYWORD_LEN));
168 keyParam.keyType = KeyType::MCC;
169 keyParams.emplace_back(keyParam);
170 return true;
171 }
172 return false;
173 }
174
ParseMnc(const std::string & key,std::vector<KeyParam> & keyParams)175 bool AceResKeyParser::ParseMnc(const std::string& key, std::vector<KeyParam>& keyParams)
176 {
177 std::regex mnc("mnc(\\d{2,3})");
178 if (regex_match(key, mnc)) {
179 KeyParam keyParam;
180 keyParam.value = StringUtils::StringToInt(key.substr(MCC_MNC_KEYWORD_LEN));
181 if (key.substr(MCC_MNC_KEYWORD_LEN).length() == MCC_MNC_VALUE_LEN) {
182 keyParam.keyType = KeyType::MNC;
183 } else {
184 keyParam.keyType = KeyType::MNC_SHORT_LEN;
185 }
186 keyParams.emplace_back(keyParam);
187 return true;
188 }
189 return false;
190 }
191
ParseScreenShape(const std::string & key,std::vector<KeyParam> & keyParams)192 bool AceResKeyParser::ParseScreenShape(const std::string& key, std::vector<KeyParam>& keyParams)
193 {
194 auto iter = RES_SCREEN_SHAPE.find(key);
195 if (iter != RES_SCREEN_SHAPE.end()) {
196 KeyParam keyParam;
197 keyParam.keyType = KeyType::SCREENSHAPE;
198 keyParam.value = static_cast<int32_t>(iter->second);
199 keyParams.emplace_back(keyParam);
200 return true;
201 }
202 return false;
203 }
204
ParseLongScreen(const std::string & key,std::vector<KeyParam> & keyParams)205 bool AceResKeyParser::ParseLongScreen(const std::string& key, std::vector<KeyParam>& keyParams)
206 {
207 auto iter = RES_LONG_SCREEN.find(key);
208 if (iter != RES_LONG_SCREEN.end()) {
209 KeyParam keyParam;
210 keyParam.keyType = KeyType::LONGSCREEN;
211 keyParam.value = static_cast<int32_t>(iter->second);
212 keyParams.emplace_back(keyParam);
213 return true;
214 }
215 return false;
216 }
217
ParseOrientation(const std::string & key,std::vector<KeyParam> & keyParams)218 bool AceResKeyParser::ParseOrientation(const std::string& key, std::vector<KeyParam>& keyParams)
219 {
220 auto iter = RES_ORIENTATION.find(key);
221 if (iter != RES_ORIENTATION.end()) {
222 KeyParam keyParam;
223 keyParam.keyType = KeyType::ORIENTATION;
224 keyParam.value = static_cast<int32_t>(iter->second);
225 keyParams.emplace_back(keyParam);
226 return true;
227 }
228 return false;
229 }
230
ParseColorMode(const std::string & key,std::vector<KeyParam> & keyParams)231 bool AceResKeyParser::ParseColorMode(const std::string& key, std::vector<KeyParam>& keyParams)
232 {
233 auto iter = RES_COLOR_MODE.find(key);
234 if (iter != RES_COLOR_MODE.end()) {
235 KeyParam keyParam;
236 keyParam.keyType = KeyType::COLOR_MODE;
237 keyParam.value = static_cast<int32_t>(iter->second);
238 keyParams.emplace_back(keyParam);
239 return true;
240 }
241 return false;
242 }
243
ParseDeclarativeColorMode(const std::string & key,std::vector<KeyParam> & keyParams)244 bool AceResKeyParser::ParseDeclarativeColorMode(const std::string& key, std::vector<KeyParam>& keyParams)
245 {
246 auto iter = DECLARATIVE_RES_COLOR_MODE.find(key);
247 if (iter != DECLARATIVE_RES_COLOR_MODE.end()) {
248 KeyParam keyParam;
249 keyParam.keyType = KeyType::DECLARATIVE_COLOR_MODE;
250 keyParam.value = static_cast<int32_t>(iter->second);
251 keyParams.emplace_back(keyParam);
252 return true;
253 }
254 return false;
255 }
256
ParseDeviceType(const std::string & key,std::vector<KeyParam> & keyParams)257 bool AceResKeyParser::ParseDeviceType(const std::string& key, std::vector<KeyParam>& keyParams)
258 {
259 auto iter = RES_DEVICE_TYPE.find(key);
260 if (iter != RES_DEVICE_TYPE.end()) {
261 KeyParam keyParam;
262 keyParam.keyType = KeyType::DEVICETYPE;
263 keyParam.value = static_cast<int32_t>(iter->second);
264 keyParams.emplace_back(keyParam);
265 return true;
266 }
267 return false;
268 }
269
ParseResolution(const std::string & key,std::vector<KeyParam> & keyParams)270 bool AceResKeyParser::ParseResolution(const std::string& key, std::vector<KeyParam>& keyParams)
271 {
272 auto iter = RES_RESOLUTION.find(key);
273 if (iter != RES_RESOLUTION.end()) {
274 KeyParam keyParam;
275 keyParam.keyType = KeyType::RESOLUTION;
276 keyParam.value = static_cast<int32_t>(iter->second);
277 keyParams.emplace_back(keyParam);
278 return true;
279 }
280 return false;
281 }
282
ParseDefaults(const std::string & key,std::vector<KeyParam> & keyParams)283 bool AceResKeyParser::ParseDefaults(const std::string& key, std::vector<KeyParam>& keyParams)
284 {
285 return key == "defaults" || key == "default";
286 }
287
GetMccByValue(uint32_t value) const288 std::string AceResKeyParser::GetMccByValue(uint32_t value) const
289 {
290 char mccStr[MAX_MCC_MNC_LEN] = { 0 };
291 if (sprintf_s(mccStr, MAX_MCC_MNC_LEN, "mcc%03u", value) < 0) {
292 return "";
293 }
294 return std::string(mccStr);
295 }
296
GetMncShortLenByValue(uint32_t value) const297 std::string AceResKeyParser::GetMncShortLenByValue(uint32_t value) const
298 {
299 char mncStr[MAX_MCC_MNC_LEN] = { 0 };
300 if (sprintf_s(mncStr, MAX_MCC_MNC_LEN, "mnc%02u", value) < 0) {
301 return "";
302 }
303 return std::string(mncStr);
304 }
305
GetMncByValue(uint32_t value) const306 std::string AceResKeyParser::GetMncByValue(uint32_t value) const
307 {
308 char mncStr[MAX_MCC_MNC_LEN] = { 0 };
309 if (sprintf_s(mncStr, MAX_MCC_MNC_LEN, "mnc%03u", value) < 0) {
310 return "";
311 }
312 return std::string(mncStr);
313 }
314
GetOrientationByType(DeviceOrientation type) const315 std::string AceResKeyParser::GetOrientationByType(DeviceOrientation type) const
316 {
317 auto item =
318 find_if(RES_ORIENTATION.begin(), RES_ORIENTATION.end(), [type](auto iter) { return iter.second == type; });
319 if (item != RES_ORIENTATION.end()) {
320 return item->first;
321 }
322 return "";
323 }
324
GetColorModeByType(ColorMode type) const325 std::string AceResKeyParser::GetColorModeByType(ColorMode type) const
326 {
327 auto item =
328 find_if(RES_COLOR_MODE.begin(), RES_COLOR_MODE.end(), [type](auto iter) { return iter.second == type; });
329 if (item != RES_COLOR_MODE.end()) {
330 return item->first;
331 }
332 return "";
333 }
334
GetDeclarativeColorModeByType(ColorMode type) const335 std::string AceResKeyParser::GetDeclarativeColorModeByType(ColorMode type) const
336 {
337 auto item = find_if(DECLARATIVE_RES_COLOR_MODE.begin(), DECLARATIVE_RES_COLOR_MODE.end(),
338 [type](auto iter) { return iter.second == type; });
339 if (item != DECLARATIVE_RES_COLOR_MODE.end()) {
340 return item->first;
341 }
342 return "";
343 }
344
GetDeviceByType(DeviceType type) const345 std::string AceResKeyParser::GetDeviceByType(DeviceType type) const
346 {
347 auto deviceTypeItem =
348 find_if(RES_DEVICE_TYPE.begin(), RES_DEVICE_TYPE.end(), [type](auto iter) { return iter.second == type; });
349 if (deviceTypeItem != RES_DEVICE_TYPE.end()) {
350 return deviceTypeItem->first;
351 }
352 return "";
353 }
354
GetResolutionByType(ResolutionType type) const355 std::string AceResKeyParser::GetResolutionByType(ResolutionType type) const
356 {
357 auto resolutionItem =
358 find_if(RES_RESOLUTION.begin(), RES_RESOLUTION.end(), [type](auto iter) { return iter.second == type; });
359 if (resolutionItem != RES_RESOLUTION.end()) {
360 return resolutionItem->first;
361 }
362 return "";
363 }
GetScreenShapeByType(ScreenShape type) const364 std::string AceResKeyParser::GetScreenShapeByType(ScreenShape type) const
365 {
366 auto shapeItem =
367 find_if(RES_SCREEN_SHAPE.begin(), RES_SCREEN_SHAPE.end(), [type](auto iter) { return iter.second == type; });
368 if (shapeItem != RES_SCREEN_SHAPE.end()) {
369 return shapeItem->first;
370 }
371 return "";
372 }
373
GetScreenLongByType(LongScreenType type) const374 std::string AceResKeyParser::GetScreenLongByType(LongScreenType type) const
375 {
376 auto longItem =
377 find_if(RES_LONG_SCREEN.begin(), RES_LONG_SCREEN.end(), [type](auto iter) { return iter.second == type; });
378 if (longItem != RES_LONG_SCREEN.end()) {
379 return longItem->first;
380 }
381 return "";
382 }
383
384 } // namespace OHOS::Ace