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