1 /*
2 * Copyright (c) 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 "utils/psue_manager.h"
17
18 #include <algorithm>
19 #include <cctype>
20 #include <cstdlib>
21 #include <iostream>
22 #include <string>
23 #include <unzip.h>
24 #include <vector>
25 #include "hilog_wrapper.h"
26 #include "map"
27 #include "utils/errors.h"
28 #ifdef __WINNT__
29 #include <windows.h>
30 #undef ERROR
31 #endif
32
33 namespace OHOS {
34 namespace Global {
35 namespace Resource {
36 using namespace std;
37
38 namespace {
39 const float DEFAULT_EXTEND_RATIO = 0.3f;
40
41 struct ExtendRatioTable {
42 int32_t count;
43 float ratio;
44 };
45
46 const ExtendRatioTable EXTEND_RATIO_RABLE[] = {
47 {10, 2.0f},
48 {20, 1.0f},
49 {30, 0.8f},
50 {50, 0.6f},
51 {70, 0.4f},
52 };
53 const std::wstring PSUE_CONFIG_CHARS = {L"ReÇÉÄßÑ¿ÃóèìжДﺥ"};
54
55 const map<wchar_t, wchar_t> REPLACE_TABLE {
56 {L'a', L'à'},
57 {L'A', L'À'},
58 {L'c', L'ć'},
59 {L'C', L'Ć'},
60 {L'i', L'ì'},
61 {L'I', L'Ì'},
62 {L'o', L'ó'},
63 {L'O', L'Ó'},
64 {L'u', L'ü'},
65 {L'U', L'Ü'},
66 {L'y', L'ÿ'},
67 {L'Y', L'Ÿ'},
68 {L'z', L'ž'},
69 {L'Z', L'Ž'},
70 };
71 }
72
PsueManager()73 PsueManager::PsueManager()
74 {
75 }
76
~PsueManager()77 PsueManager::~PsueManager()
78 {
79 }
80
81 /**
82 PsuedoTranslation level default value is 3
83 1. Enclosed in brackets
84 2. Letter replacement
85 3. Lengthen string
86 */
87 int g_fakeLocaleLevel = 3;
88
89 int g_levelForReplace = 2;
90 int g_levelForAppend = 3;
91 int g_levelForAddBracket = 1;
92
Convert(const std::string & src,std::string & dest)93 std::string PsueManager::Convert(const std::string &src, std::string &dest)
94 {
95 if (isDigit(src)) {
96 return "";
97 }
98 std::wstring ws;
99 std::string wsStr = ToWstring(ws, src);
100 if (wsStr != "") {
101 return wsStr;
102 }
103 if (g_fakeLocaleLevel >= g_levelForReplace) {
104 // char replace
105 ToAccent(ws);
106 }
107 if (g_fakeLocaleLevel == g_levelForAppend) {
108 // enhance length
109 unsigned int len = src.length();
110 unsigned int extendCount = len * GetExtendRatio(len);
111 unsigned int loop = extendCount / PSUE_CONFIG_CHARS.length();
112 unsigned int left = extendCount % PSUE_CONFIG_CHARS.length();
113 for (unsigned int i = 0; i < loop ; i++) {
114 ws += PSUE_CONFIG_CHARS;
115 }
116 if (left > 0) {
117 ws += PSUE_CONFIG_CHARS.substr(0, left);
118 }
119 }
120 std::string tsStr = ToString(dest, ws);
121 if (tsStr != "") {
122 return tsStr;
123 }
124 if (g_fakeLocaleLevel >= g_levelForAddBracket) {
125 // add brackets
126 dest = '[' + dest + ']';
127 }
128 return "";
129 }
130
isDigit(const std::string src)131 bool PsueManager::isDigit(const std::string src)
132 {
133 for (unsigned int i = 0 ; i < src.size() ; i++) {
134 if (!isdigit(src[i])) {
135 return false;
136 }
137 }
138 return true;
139 }
140
GetExtendRatio(int32_t len) const141 float PsueManager::GetExtendRatio(int32_t len) const
142 {
143 for (size_t i = 0; i < sizeof(EXTEND_RATIO_RABLE) / sizeof(EXTEND_RATIO_RABLE[0]) ; i++) {
144 if (len <= EXTEND_RATIO_RABLE[i].count) {
145 return EXTEND_RATIO_RABLE[i].ratio;
146 }
147 }
148 return DEFAULT_EXTEND_RATIO;
149 }
150
151 // letter replace
ToAccent(wstring & ws) const152 void PsueManager::ToAccent(wstring &ws) const
153 {
154 for (std::wstring::size_type i = 0 ; i < ws.length(); i++) {
155 if (ws[i] == L'%') {
156 i++;
157 } else if (ws[i] == L'{') {
158 while ((i + 1 < ws.length()) && (ws[++i] != L'}')) {}
159 } else {
160 auto iter = REPLACE_TABLE.find(ws[i]);
161 if (iter != REPLACE_TABLE.end()) {
162 ws[i] = iter->second;
163 }
164 }
165 }
166 }
167
ToWstring(std::wstring & dest,const std::string & src)168 std::string PsueManager::ToWstring(std::wstring &dest, const std::string &src)
169 {
170 std::string result = setlocale(LC_CTYPE, "");
171 size_t destSize = mbstowcs(NULL, src.c_str(), 0);
172 if (destSize == size_t(-1)) {
173 cout << result << endl;
174 return "get widechar size fail ";
175 }
176 vector<wchar_t> buf(destSize + 1);
177 if (mbstowcs(&buf[0], src.c_str(), src.size()) == static_cast<size_t>(-1)) {
178 return "convert to widechar fail";
179 }
180
181 dest.assign(buf.begin(), buf.end() - 1);
182 return "";
183 }
184
ToString(std::string & dest,const std::wstring & src)185 std::string PsueManager::ToString(std::string &dest, const std::wstring &src)
186 {
187 size_t destSize = wcstombs(NULL, src.c_str(), 0);
188 if (destSize == size_t(-1)) {
189 return "get multibyte size fail";
190 }
191 vector<char> buf(destSize + 1);
192 if (wcstombs(&buf[0], src.c_str(), buf.size()) == static_cast<size_t>(-1)) {
193 return "convert to multibyte fail";
194 }
195
196 dest.assign(buf.begin(), buf.end() - 1);
197 return "";
198 }
199
SetFakeLocaleLevel(const int level)200 void PsueManager::SetFakeLocaleLevel(const int level)
201 {
202 if (level <= g_levelForAppend && level >= g_levelForAddBracket) {
203 g_fakeLocaleLevel = level;
204 }
205 }
206
IsAsciiString(const std::string & src)207 bool PsueManager::IsAsciiString(const std::string &src)
208 {
209 bool isAscii = true;
210 for (size_t i = 0; i < src.length(); i++) {
211 if (src[i] < 0 || src[i] > 127) { // 127 is the max value of ascii
212 isAscii = false;
213 break;
214 }
215 }
216 return isAscii;
217 }
218
BidirectionConvert(std::string & src)219 std::string PsueManager::BidirectionConvert(std::string &src)
220 {
221 if (!IsAsciiString(src)) {
222 return src;
223 }
224 std::string result;
225 size_t start = 0;
226 size_t end = 0;
227 while (start < src.length()) {
228 while (start < src.length() && isspace(src[start])) {
229 start++;
230 }
231 if (start > end) {
232 result += src.substr(end, start - end);
233 }
234 end = start;
235 while (end < src.length() && !isspace(src[end])) {
236 end++;
237 }
238 if (start < src.length()) {
239 result += directionHead;
240 result += src.substr(start, end - start);
241 result += directionTail;
242 }
243 start = end;
244 }
245 return result;
246 }
247 } // namespace Resource
248 } // namespace Global
249 } // namespace OHOS