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 "locale_util.h"
16
17namespace OHOS {
18namespace Global {
19namespace I18n {
20bool LocaleUtil::IsRTL(const std::string &locale)
21{
22    icu::Locale curLocale(locale.c_str());
23    return curLocale.isRightToLeft();
24}
25
26uint16_t LocaleUtil::EncodeLanguageByLocaleInfo(const LocaleInfo *locale)
27{
28    if (locale == nullptr) {
29        return NULL_LANGUAGE;
30    }
31    return EncodeLanguage(locale->GetLanguage().c_str());
32}
33
34uint32_t LocaleUtil::EncodeScriptByLocaleInfo(const LocaleInfo *locale)
35{
36    if (locale == nullptr) {
37        return NULL_SCRIPT;
38    }
39    return EncodeScript(locale->GetScript().c_str());
40}
41
42uint16_t LocaleUtil::EncodeRegionByLocaleInfo(const LocaleInfo *locale)
43{
44    if (locale == nullptr) {
45        return NULL_REGION;
46    }
47    return EncodeRegion(locale->GetRegion().c_str());
48}
49
50uint16_t LocaleUtil::EncodeLanguage(const char *language)
51{
52    if (IsStrEmpty(language)) {
53            return NULL_LANGUAGE;
54        }
55    return EncodeLanguageOrRegion(language, 'a');
56}
57
58uint32_t LocaleUtil::EncodeScript(const char *script)
59{
60    if (IsStrEmpty(script)) {
61        return NULL_SCRIPT;
62    }
63    // 0, 1, 2, 3 is index of characters in script, 24, 16, 8 is offset.
64    return ((uint8_t)script[0] << 24) | ((uint8_t)script[1] << 16) | ((uint8_t)script[2] << 8) | (uint8_t)script[3];
65}
66
67uint16_t LocaleUtil::EncodeRegion(const char *region)
68{
69    if (IsStrEmpty(region)) {
70        return NULL_REGION;
71    }
72    if (region[0] >= '0' && region[0] <= '9') {
73        return EncodeLanguageOrRegion(region, '0');
74    }
75    return EncodeLanguageOrRegion(region, 'A');
76}
77
78uint64_t LocaleUtil::EncodeLocale(const char *language, const char *script, const char *region)
79{
80    uint16_t languageData = EncodeLanguage(language);
81    uint32_t scriptData = EncodeScript(script);
82    uint16_t regionData = EncodeRegion(region);
83    // 48 is the offset of language.
84    uint32_t languageOffset = 48;
85    uint32_t scriptOffset = 16;
86    return (uint64_t)(0xffff000000000000 & (((uint64_t)languageData) << languageOffset)) |
87        (0x0000ffffffff0000 & (((uint64_t)scriptData) << scriptOffset)) |(0x000000000000ffff & (uint64_t)(regionData));
88}
89
90bool LocaleUtil::IsStrEmpty(const char *s)
91{
92    return (s == nullptr || *s == '\0');
93}
94
95void LocaleUtil::DecodeScript(uint32_t encodeScript, char *outValue)
96{
97    if (outValue == nullptr) {
98        return;
99    }
100    outValue[0] = (encodeScript & 0xFF000000) >> 24; // 0 is index, 24 is first script character offset
101    outValue[1] = (encodeScript & 0x00FF0000) >> 16; // 1 is index, 16 is second script character offset
102    outValue[2] = (encodeScript & 0x0000FF00) >> 8; // 2 is index, 8 is third script character offset
103    outValue[3] = (encodeScript & 0x000000FF); // 3 is index
104}
105
106bool LocaleUtil::IsAlphaString(const char *s, int32_t len)
107{
108    if (s == nullptr) {
109        return false;
110    }
111    int32_t i;
112    for (i = 0; i < len; i++) {
113        char c = *(s + i);
114        if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) {
115            return false;
116        }
117    }
118    return true;
119}
120
121bool LocaleUtil::IsNumericString(const char *s, int32_t len)
122{
123    if (s == nullptr) {
124        return false;
125    }
126    int32_t i;
127    for (i = 0; i < len; i++) {
128        char c = *(s + i);
129        if (!(c >= '0' && c <= '9')) {
130            return false;
131        }
132    }
133
134    return true;
135}
136
137uint16_t LocaleUtil::EncodeLanguageOrRegion(const char *str, char base)
138{
139    // 2 is index of splitor
140    if (str[2] == 0 || str[2] == '-' || str[2] == '_') {
141        // 0, 1 is index, 8 is offset
142        return ((uint8_t)str[0] << 8) | ((uint8_t)str[1]);
143    }
144    uint8_t first = ((uint8_t)(str[0] - base)) & 0x7f; // 0 is index
145    uint8_t second = ((uint8_t)(str[1] - base)) & 0x7f; // 1 is index
146    uint8_t third = ((uint8_t)(str[2] - base)) & 0x7f; // 2 is index
147    // 2, 3, 5, 8 is offset.
148    return ((0x80 | (first << 2) | (second >> 3)) << 8) | ((second << 5) | third);
149}
150} // namespace I18n
151} // namespace Global
152} // namespace OHOS