• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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