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