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