• 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             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