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 #include "utils/utils.h"
16 
17 #include <cctype>
18 #include <cstddef>
19 #include <cstring>
20 
21 #include "utils/common.h"
22 
23 namespace OHOS {
24 namespace Global {
25 namespace Resource {
IsAlphaString(const char * s,int32_t len)26 bool Utils::IsAlphaString(const char *s, int32_t len)
27 {
28     if (s == nullptr) {
29         return false;
30     }
31     int32_t i;
32     for (i = 0; i < len; i++) {
33         char c = *(s + i);
34         if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) {
35             return false;
36         }
37     }
38     return true;
39 }
40 
IsNumericString(const char * s,int32_t len)41 bool Utils::IsNumericString(const char *s, int32_t len)
42 {
43     if (s == nullptr) {
44         return false;
45     }
46     int32_t i;
47     for (i = 0; i < len; i++) {
48         char c = *(s + i);
49         if (!(c >= '0' && c <= '9')) {
50             return false;
51         }
52     }
53 
54     return true;
55 }
56 
57 /**
58  * @brief decode 32 bits as script array.
59  * 31-24 bits is script[0]
60  * 23-16 bits is script[1]
61  * 15-8 bits is script[2]
62  * 0-7 bits is script[3]
63  *
64  * @param encodeScript
65  * @param outValue
66  */
DecodeScript(uint32_t encodeScript,char * outValue)67 void Utils::DecodeScript(uint32_t encodeScript, char *outValue)
68 {
69     if (outValue == nullptr) {
70         return;
71     }
72     outValue[0] = (encodeScript & 0xFF000000) >> 24;
73     outValue[1] = (encodeScript & 0x00FF0000) >> 16;
74     outValue[2] = (encodeScript & 0x0000FF00) >> 8;
75     outValue[3] = (encodeScript & 0x000000FF);
76 }
77 
IsStrEmpty(const char * s)78 bool Utils::IsStrEmpty(const char *s)
79 {
80     return (s == nullptr || *s == '\0');
81 }
82 
StrLen(const char * s)83 size_t Utils::StrLen(const char *s)
84 {
85     if (s == nullptr) {
86         return 0;
87     }
88     return strlen(s);
89 }
90 
EncodeLanguage(const char * language)91 uint16_t Utils::EncodeLanguage(const char *language)
92 {
93     if (Utils::IsStrEmpty(language)) {
94         return NULL_LANGUAGE;
95     }
96     return Utils::EncodeLanguageOrRegion(language, 'a');
97 }
98 
99 /**
100  * @brief  locale compose of language,script and region,encode as 64bits.
101  * 63-48 bits represent language,detail format see EncodeLanguageOrRegion method
102  * 47-16 bits represent script,detail format see EncodeScript method
103  * 15-0 bits represent region,detail format see EncodeLanguageOrRegion method
104  *
105  * @param language
106  * @param script
107  * @param region
108  * @return uint64_t
109  */
EncodeLocale(const char * language,const char * script,const char * region)110 uint64_t Utils::EncodeLocale(const char *language,
111                              const char *script,
112                              const char *region)
113 {
114     uint16_t languageData = Utils::EncodeLanguage(language);
115     uint32_t scriptData = Utils::EncodeScript(script);
116     uint16_t regionData = Utils::EncodeRegion(region);
117 
118     return (uint64_t)(0xffff000000000000 & (((uint64_t)languageData) << 48)) |
119            (0x0000ffffffff0000 & (((uint64_t)scriptData) << 16)) | (0x000000000000ffff & (uint64_t)(regionData));
120 }
121 
EncodeRegionByResLocale(const ResLocale * locale)122 uint16_t Utils::EncodeRegionByResLocale(const ResLocale *locale)
123 {
124     if (locale == nullptr) {
125         return NULL_REGION;
126     }
127     return Utils::EncodeRegion(locale->GetRegion());
128 }
129 
EncodeLanguageByResLocale(const ResLocale * locale)130 uint16_t Utils::EncodeLanguageByResLocale(const ResLocale *locale)
131 {
132     if (locale == nullptr) {
133         return NULL_LANGUAGE;
134     }
135     return Utils::EncodeLanguage(locale->GetLanguage());
136 }
137 
EncodeScriptByResLocale(const ResLocale * locale)138 uint32_t Utils::EncodeScriptByResLocale(const ResLocale *locale)
139 {
140     if (locale == nullptr) {
141         return NULL_SCRIPT;
142     }
143     return Utils::EncodeScript(locale->GetScript());
144 }
145 
EncodeRegion(const char * region)146 uint16_t Utils::EncodeRegion(const char *region)
147 {
148     if (Utils::IsStrEmpty(region)) {
149         return NULL_REGION;
150     }
151     if (region[0] >= '0' && region[0] <= '9') {
152         return Utils::EncodeLanguageOrRegion(region, '0');
153     }
154     return Utils::EncodeLanguageOrRegion(region, 'A');
155 }
156 
157 /**
158  * @brief script is four letter array.encode script array as four bytes.Encode format.
159  * 31-24 bits represent script[0]
160  * 23-16 bits represent script[1]
161  * 15-8 bits represent script[2]
162  * 0-7 bits represent script[3]
163  *
164  * @param script
165  * @return uint32_t
166  */
EncodeScript(const char * script)167 uint32_t Utils::EncodeScript(const char *script)
168 {
169     if (Utils::IsStrEmpty(script)) {
170         return NULL_SCRIPT;
171     }
172     return ((uint8_t)script[0] << 24) | ((uint8_t)script[1] << 16) | ((uint8_t)script[2] << 8) | (uint8_t)script[3];
173 }
174 
175 /**
176  * @brief encode language or region str as two byte.
177  * language is two or three lowercase.
178  * region is two capital  letter or three digit.
179  *
180  * two char,encode format
181  * 15-8 bits is the first char
182  * 7-0 bits is the second char
183  *
184  * three chars,encode format
185  * 15 bit is 1
186  * 14-10 bits represent the value of  the first char subtract base char,
187  * 9-5 bits represent the value of the second char subtract base char  .
188  * 4-0 bits represent the value of the third char subtract base char.
189  * base char is 'a','A','0'.
190  * example when base is 'a',max value('z' - 'a') is 26,so five bits can represent a char.
191  *
192  * @param str
193  * @param base is '0' or 'a' or 'A'
194  * @return uint16_t
195  */
EncodeLanguageOrRegion(const char * str,char base)196 uint16_t Utils::EncodeLanguageOrRegion(const char *str, char base)
197 {
198     if (str[2] == 0 || str[2] == '-' || str[2] == '_') {
199         return ((uint8_t)str[0] << 8) | ((uint8_t)str[1]);
200     }
201     uint8_t first = ((uint8_t)(str[0] - base)) & 0x7f;
202     uint8_t second = ((uint8_t)(str[1] - base)) & 0x7f;
203     uint8_t third = ((uint8_t)(str[2] - base)) & 0x7f;
204     return ((0x80 | (first << 2) | (second >> 3)) << 8) | ((second << 5) | third);
205 };
206 
StrCompare(const char * left,const char * right,size_t len,bool isCaseSensitive)207 bool Utils::StrCompare(const char *left, const char *right, size_t len, bool isCaseSensitive)
208 {
209     if (left == nullptr && right == nullptr) {
210         return true;
211     }
212     if (left == nullptr || right == nullptr) {
213         return false;
214     }
215     int rc;
216     unsigned char c1;
217     unsigned char c2;
218     while (len--) {
219         c1 = (unsigned char)*left;
220         c2 = (unsigned char)*right;
221         if (c1 == 0 && c2 == 0) {
222             return true;
223         }
224         if (c1 == 0 || c2 == 0) {
225             return false;
226         }
227         if (isCaseSensitive) {
228             rc = (int)(c1) - (int)(c2);
229         } else {
230             rc = tolower(c1) - tolower(c2);
231         }
232         if (rc != 0) {
233             return false;
234         }
235         ++left;
236         ++right;
237     }
238     return true;
239 }
240 
241 /**
242  * @brief convert hex char as int value
243  *
244  * @param c
245  * @param state
246  * @return uint32_t
247  */
ParseHex(char c,RState & state)248 static uint32_t ParseHex(char c, RState &state)
249 {
250     if (c >= '0' && c <= '9') {
251         return (c - '0');
252     } else if (c >= 'a' && c <= 'f') {
253         return (c - 'a' + 0xa);
254     } else if (c >= 'A' && c <= 'F') {
255         return (c - 'A' + 0xa);
256     }
257     state = INVALID_FORMAT;
258 
259     return -1;
260 }
261 
262 /**
263  * @brief  convert color string to 32 bits value 0xaarrggbb.
264  * color string format is
265  * #rgb  red (0-f) greed(0-f) blue(0-f)
266  * #argb transparency(0-f)  red (0-f) greed(0-f) blue(0-f)
267  * #rrggbb red (00-ff) greed(00-ff) blue(00-ff)
268  * #aarrggbb transparency(00-ff) red (00-ff) greed(00-ff) blue(00-ff)
269  *
270  * @param s
271  * @param outValue
272  * @return RState
273  */
ConvertColorToUInt32(const char * s,uint32_t & outValue)274 RState Utils::ConvertColorToUInt32(const char *s, uint32_t &outValue)
275 {
276     if (s == nullptr) {
277         return INVALID_FORMAT;
278     }
279     uint32_t color = 0;
280     RState parseState = SUCCESS;
281     size_t len = strlen(s);
282     if (*s == '#') {
283         if (len == 4) { // 4 means #rgb
284             color |= 0xFF000000;
285             color |= ParseHex(s[1], parseState) << 20;
286             color |= ParseHex(s[1], parseState) << 16;
287             color |= ParseHex(s[2], parseState) << 12;
288             color |= ParseHex(s[2], parseState) << 8;
289             // 3 means the subscript of parameter s
290             // 4 means the bits shifted left, and increment at 4-bit intervals base len
291             color |= ParseHex(s[3], parseState) << 4;
292             color |= ParseHex(s[3], parseState);
293         } else if (len == 5) { // 5 means #argb
294             color |= ParseHex(s[1], parseState) << 28;
295             color |= ParseHex(s[1], parseState) << 24;
296             color |= ParseHex(s[2], parseState) << 20;
297             color |= ParseHex(s[2], parseState) << 16;
298             color |= ParseHex(s[3], parseState) << 12;
299             color |= ParseHex(s[3], parseState) << 8;
300             color |= ParseHex(s[4], parseState) << 4;
301             color |= ParseHex(s[4], parseState);
302         } else if (len == 7) { // 7 means #rrggbb
303             color |= 0xFF000000;
304             color |= ParseHex(s[1], parseState) << 20;
305             color |= ParseHex(s[2], parseState) << 16;
306             color |= ParseHex(s[3], parseState) << 12;
307             color |= ParseHex(s[4], parseState) << 8;
308             color |= ParseHex(s[5], parseState) << 4;
309             color |= ParseHex(s[6], parseState);
310         } else if (len == 9) { // 9 means #aarrggbb
311             color |= ParseHex(s[1], parseState) << 28;
312             color |= ParseHex(s[2], parseState) << 24;
313             color |= ParseHex(s[3], parseState) << 20;
314             color |= ParseHex(s[4], parseState) << 16;
315             color |= ParseHex(s[5], parseState) << 12;
316             color |= ParseHex(s[6], parseState) << 8;
317             color |= ParseHex(s[7], parseState) << 4;
318             color |= ParseHex(s[8], parseState);
319         }
320     } else {
321         parseState = INVALID_FORMAT;
322     }
323     outValue = color;
324     return parseState;
325 }
326 } // namespace Resource
327 } // namespace Global
328 } // namespace OHOS
329