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 "ecmascript/base/utf_helper.h"
17 #include "ecmascript/tests/test_helper.h"
18
19 using namespace panda::ecmascript;
20 using namespace panda::ecmascript::base;
21 using namespace panda::ecmascript::base::utf_helper;
22
23 namespace panda::test {
24 class UtfHelperTest : public testing::Test {
25 public:
SetUpTestCase()26 static void SetUpTestCase()
27 {
28 GTEST_LOG_(INFO) << "SetUpTestCase";
29 }
30
TearDownTestCase()31 static void TearDownTestCase()
32 {
33 GTEST_LOG_(INFO) << "TearDownCase";
34 }
35
SetUp()36 void SetUp() override
37 {
38 TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
39 }
40
TearDown()41 void TearDown() override
42 {
43 TestHelper::DestroyEcmaVMWithScope(instance, scope);
44 }
45
46 EcmaVM *instance {nullptr};
47 EcmaHandleScope *scope {nullptr};
48 JSThread *thread {nullptr};
49 };
50
51 /*
52 * @tc.name: CombineTwoU16
53 * @tc.desc: Enter a pair of UTF16-encoded surrogate pair corresponding to the lead surrogates and trail surrogates,
54 * and return the corresponding Unicode codepoint value.
55 * @tc.type: FUNC
56 */
HWTEST_F_L0(UtfHelperTest,CombineTwoU16)57 HWTEST_F_L0(UtfHelperTest, CombineTwoU16)
58 {
59 uint16_t leadSur= 0xD800;
60 uint16_t trailSur = 0xDC00;
61 uint32_t codePoint = static_cast<uint32_t>(((leadSur - 0xD800U) << 10)|(trailSur - 0xDc00U)) + 0x10000U;
62 uint32_t utfHelperCodePoint = CombineTwoU16(leadSur, trailSur);
63 EXPECT_EQ(codePoint, utfHelperCodePoint);
64 EXPECT_EQ(codePoint, static_cast<uint32_t>(0x10000));
65 trailSur = 0xDFFF;
66 codePoint = static_cast<uint32_t>(((leadSur - 0xD800U) << 10) | (trailSur - 0xDC00U))+ 0x10000U;
67 utfHelperCodePoint = CombineTwoU16(leadSur, trailSur);
68 EXPECT_EQ(codePoint, utfHelperCodePoint);
69 EXPECT_EQ(codePoint, static_cast<uint32_t>(0x103FF));
70 leadSur = 0xDBFF;
71 codePoint = static_cast<uint32_t>(((leadSur - 0xD800U) << 10) | (trailSur - 0xDC00U)) + 0x10000U;
72 utfHelperCodePoint = CombineTwoU16(leadSur, trailSur);
73 EXPECT_EQ(codePoint, utfHelperCodePoint);
74 EXPECT_EQ(codePoint, static_cast<uint32_t>(0x10FFFF));
75 trailSur = 0xDC00;
76 codePoint = static_cast<uint32_t>(((leadSur - 0xD800U) << 10) | (trailSur - 0xDC00U)) + 0x10000U;
77 utfHelperCodePoint = CombineTwoU16(leadSur, trailSur);
78 EXPECT_EQ(codePoint, utfHelperCodePoint);
79 EXPECT_EQ(codePoint, static_cast<uint32_t>(0x10FC00));
80 leadSur= 0xD950;
81 trailSur= 0xDF21;
82 codePoint = static_cast<uint32_t>(((leadSur - 0xD800U)<< 10) | (trailSur - 0xDC00U)) + 0x10000U;
83 utfHelperCodePoint = CombineTwoU16(leadSur, trailSur);
84 EXPECT_EQ(codePoint, utfHelperCodePoint);
85 EXPECT_EQ(codePoint, static_cast<uint32_t>(0x64321));
86 }
87
88 /*
89 * @tc.name: UTF16Decode
90 * @tc.desc: Enter a pair of UTF16-encoded surrogate pair corresponding to the lead surrogates and trail surrogates,
91 Decodes them into corresponding Unicode codepoint values and returns.
92 * @tc.type: FUNC
93 */
HWTEST_F_L0(UtfHelperTest,UTF16Decode)94 HWTEST_F_L0(UtfHelperTest, UTF16Decode)
95 {
96 uint16_t lead = 0xD950;
97 uint16_t trail = 0xDF21;
98 EXPECT_TRUE(lead >= DECODE_LEAD_LOW && lead <= DECODE_LEAD_HIGH);
99 EXPECT_TRUE(trail >= DECODE_TRAIL_LOW && trail <= DECODE_TRAIL_HIGH);
100 uint32_t codePoint = utf_helper::UTF16Decode(lead, trail);
101 EXPECT_EQ(codePoint, 0x64321U);
102 lead = 0xD85D;
103 trail = 0xDFCC;
104 EXPECT_TRUE(lead >= DECODE_LEAD_LOW && lead <= DECODE_LEAD_HIGH);
105 EXPECT_TRUE(trail >= DECODE_TRAIL_LOW && trail <= DECODE_TRAIL_HIGH);
106 codePoint = utf_helper::UTF16Decode(lead, trail);
107 EXPECT_EQ(codePoint, 0x277CCU);
108 }
109
110 /*
111 * @tc.name: IsValidUTF8
112 * @tc.desc: Judge whether an input group of symbols is a valid UTF8 coding sequence.
113 * @tc.type: FUNC
114 */
HWTEST_F_L0(UtfHelperTest,IsValidUTF8)115 HWTEST_F_L0(UtfHelperTest, IsValidUTF8)
116 {
117 const std::vector<uint8_t> utfDataOneBitVaild1 = {0x00}; // //0xxxxxxx
118 const std::vector<uint8_t> utfDataOneBitVaild2 = {BIT_MASK_1 - 0x01};
119 const std::vector<uint8_t> utfDataOneBitUnvaild = {BIT_MASK_1};
120 EXPECT_TRUE(utf_helper::IsValidUTF8(utfDataOneBitVaild1));
121 EXPECT_TRUE(utf_helper::IsValidUTF8(utfDataOneBitVaild2));
122 EXPECT_FALSE(utf_helper::IsValidUTF8(utfDataOneBitUnvaild));
123 const std::vector<uint8_t> utfDataTwoBitVaild1 = {BIT_MASK_2, BIT_MASK_1}; // 110xxxxx 10xxxxxx
124 const std::vector<uint8_t> utfDataTwoBitVaild2 = {BIT_MASK_3 - 0x01, BIT_MASK_2 - 0x01};
125 const std::vector<uint8_t> utfDataTwoBitUnvaild1 = {BIT_MASK_2, BIT_MASK_2};
126 const std::vector<uint8_t> utfDataTwoBitUnvaild2 = {BIT_MASK_3, BIT_MASK_1};
127 EXPECT_TRUE(utf_helper::IsValidUTF8(utfDataTwoBitVaild1));
128 EXPECT_TRUE(utf_helper::IsValidUTF8(utfDataTwoBitVaild2));
129 EXPECT_FALSE(utf_helper::IsValidUTF8(utfDataTwoBitUnvaild1));
130 EXPECT_FALSE(utf_helper::IsValidUTF8(utfDataTwoBitUnvaild2));
131 const std::vector<uint8_t> utfDataThreeBitVaild1 = {BIT_MASK_3, BIT_MASK_1, BIT_MASK_1};
132 const std::vector<uint8_t>utfDataThreeBitVaild2 = {BIT_MASK_4 - 0x01, BIT_MASK_2 - 0x01, BIT_MASK_2 - 0x01};
133 const std::vector<uint8_t>utfDataThreeBitUnvaild1 = {BIT_MASK_3, BIT_MASK_1, BIT_MASK_2};
134 const std::vector<uint8_t>utfDataThreeBitUnvaild2 = {BIT_MASK_3, BIT_MASK_2, BIT_MASK_1};
135 const std::vector<uint8_t>utfDataThreeBitUnvaild3 = {BIT_MASK_4, BIT_MASK_1, BIT_MASK_1};
136 const std::vector<uint8_t>utfDataThreeBitUnvaild4 = {BIT_MASK_4, BIT_MASK_2, BIT_MASK_2};
137 EXPECT_TRUE(utf_helper::IsValidUTF8(utfDataThreeBitVaild1));
138 EXPECT_TRUE(utf_helper::IsValidUTF8(utfDataThreeBitVaild2));
139 EXPECT_FALSE(utf_helper::IsValidUTF8(utfDataThreeBitUnvaild1));
140 EXPECT_FALSE(utf_helper::IsValidUTF8(utfDataThreeBitUnvaild2));
141 EXPECT_FALSE(utf_helper::IsValidUTF8(utfDataThreeBitUnvaild3));
142 EXPECT_FALSE(utf_helper::IsValidUTF8(utfDataThreeBitUnvaild4));
143 const std::vector<uint8_t>utfDataFourBitVaild1 = {BIT_MASK_4, BIT_MASK_1, BIT_MASK_1, BIT_MASK_1};
144 const std::vector<uint8_t> utfDataFourBitVaild2 =
145 {BIT_MASK_5 - 0x01, BIT_MASK_2 - 0x01, BIT_MASK_2 - 0x01, BIT_MASK_2 - 0x01};
146 const std::vector<uint8_t>utfDataFourBitUnvaild1 = {BIT_MASK_4, BIT_MASK_1, BIT_MASK_1, BIT_MASK_2};
147 const std::vector<uint8_t>utfDataFourBitUnvaild2 = {BIT_MASK_4, BIT_MASK_1, BIT_MASK_2, BIT_MASK_1};
148 const std::vector<uint8_t>utfDataFourBitUnvaild3 = {BIT_MASK_4, BIT_MASK_2, BIT_MASK_1, BIT_MASK_1};
149 const std::vector<uint8_t>utfDataFourBitUnvaild4 = {BIT_MASK_5, BIT_MASK_1, BIT_MASK_1, BIT_MASK_1};
150 const std::vector<uint8_t>utfDataFourBitUnvaild5 = {BIT_MASK_5, BIT_MASK_2, BIT_MASK_2, BIT_MASK_2};
151 EXPECT_TRUE(utf_helper::IsValidUTF8(utfDataFourBitVaild1));
152 EXPECT_TRUE(utf_helper::IsValidUTF8(utfDataFourBitVaild2));
153 EXPECT_FALSE(utf_helper::IsValidUTF8(utfDataFourBitUnvaild1));
154 EXPECT_FALSE(utf_helper::IsValidUTF8(utfDataFourBitUnvaild2));
155 EXPECT_FALSE(utf_helper::IsValidUTF8(utfDataFourBitUnvaild3));
156 EXPECT_FALSE(utf_helper::IsValidUTF8(utfDataFourBitUnvaild4));
157 EXPECT_FALSE(utf_helper::IsValidUTF8(utfDataFourBitUnvaild5));
158 }
159
160 /*
161 * @tc.name: ConvertUtf16ToUtf8
162 * @tc.desc: Converts a UTF16 encoding sequence encoding a character into a UTF8 encoding sequence,
163 * and returns the sequence and the byte length of the sequence. The parameter "modify"
164 * indicates whether to perform special conversion for 0.
165 * @tc.type: FUNC
166 */
HWTEST_F_L0(UtfHelperTest,ConvertUtf16ToUtf8_001)167 HWTEST_F_L0(UtfHelperTest, ConvertUtf16ToUtf8_001)
168 {
169 // codePoint lie in [0,0x7F]--->UTF-8(length:1)
170 {
171 uint16_t utf16Data0 = 0x00;
172 uint16_t utf16Data1= 0x00;
173 Utf8Char utf8Char = ConvertUtf16ToUtf8(utf16Data0, utf16Data1, false);
174 Utf8Char utf8CharTemp = {0, {0x00U}};
175 EXPECT_EQ(utf8Char.n, utf8CharTemp.n);
176 EXPECT_EQ(utf8Char.ch, utf8CharTemp.ch);
177 }
178
179 // special case for \u0000 ==> Co80- 1100'0000 1000'0000
180 {
181 uint16_t utf16Data0 = 0x00;
182 uint16_t utf16Data1= 0x00;
183 Utf8Char utf8Char = ConvertUtf16ToUtf8(utf16Data0, utf16Data1, true);
184 Utf8Char utf8CharTemp = {2, {UTF8_2B_FIRST, UTF8_2B_SECOND}};
185 EXPECT_EQ(utf8Char.n, utf8CharTemp.n);
186 EXPECT_EQ(utf8Char.ch, utf8CharTemp.ch);
187 utf16Data0 = 0x7F;
188 utf8Char = ConvertUtf16ToUtf8(utf16Data0, utf16Data1, false);
189 utf8CharTemp = {1, {0x7F}};
190 EXPECT_EQ(utf8Char.n, utf8CharTemp.n);
191 EXPECT_EQ(utf8Char.ch, utf8CharTemp.ch);
192
193 // codePoint lie in [0x80,0x7FF]--> UTF-8(length:2)
194 utf16Data0 = 0x80;
195 utf8Char = ConvertUtf16ToUtf8(utf16Data0, utf16Data1, false);
196 utf8CharTemp = {2, {UTF8_2B_FIRST + 0x02U, UTF8_2B_SECOND}};
197 EXPECT_EQ(utf8Char.n, utf8CharTemp.n);
198 EXPECT_EQ(utf8Char.ch, utf8CharTemp.ch);
199 utf16Data0 = 0x7FF;
200 utf8Char = ConvertUtf16ToUtf8(utf16Data0, utf16Data1, false);
201 utf8CharTemp = {2, {BIT_MASK_3 - 0x01, BIT_MASK_2 - 0x01}};
202 EXPECT_EQ(utf8Char.n, utf8CharTemp.n);
203 EXPECT_EQ(utf8Char.ch, utf8CharTemp.ch);
204 }
205
206 // codePoint lie in [0xD800,0xDFFF]--> UTF-8(length:3)
207 {
208 uint16_t utf16Data0 = 0xD800;
209 uint16_t utf16Data1= 0x00;
210 Utf8Char utf8Char = ConvertUtf16ToUtf8(utf16Data0, utf16Data1, false);
211 Utf8Char utf8CharTemp = {3, {UTF8_3B_FIRST | static_cast<uint8_t>(0xD800 >> 12),
212 UTF8_3B_SECOND | (static_cast<uint8_t>(0xD800 >> 6) & utf::MASK_6BIT),
213 UTF8_3B_THIRD | (static_cast<uint8_t>(0xD800) & utf::MASK_6BIT)}};
214 EXPECT_EQ(utf8Char.n, utf8CharTemp.n);
215 EXPECT_EQ(utf8Char.ch, utf8CharTemp.ch);
216 utf16Data0 = 0xDFFF;
217 utf8Char = ConvertUtf16ToUtf8(utf16Data0, utf16Data1, false);
218 utf8CharTemp = {3, {UTF8_3B_FIRST | static_cast<uint8_t>(0xDFFF >> 12),
219 UTF8_3B_SECOND | (static_cast<uint8_t>(0xDFFF >> 6) & utf::MASK_6BIT),
220 UTF8_3B_THIRD | (static_cast<uint8_t>(0xDFFF) & utf::MASK_6BIT)}};
221 EXPECT_EQ(utf8Char.n, utf8CharTemp.n);
222 EXPECT_EQ(utf8Char.ch, utf8CharTemp.ch);
223 }
224 }
225
HWTEST_F_L0(UtfHelperTest,ConvertUtf16ToUtf8_002)226 HWTEST_F_L0(UtfHelperTest, ConvertUtf16ToUtf8_002)
227 {
228 // codePoint lie in [0x800,0xD7FF]&&[0xE000,0xFFFF]-->UTF-8(length:3)
229 uint16_t utf16Data0 = 0x800;
230 uint16_t utf16Data1= 0x00;
231 Utf8Char utf8Char = ConvertUtf16ToUtf8(utf16Data0, utf16Data1, false);
232 Utf8Char utf8CharTemp = {3, {UTF8_3B_FIRST | static_cast<uint8_t>(0x800 >> 12),
233 UTF8_3B_SECOND | (static_cast<uint8_t>(0x800 >> 6) & utf::MASK_6BIT),
234 UTF8_3B_THIRD | (static_cast<uint8_t>(0x800) & utf::MASK_6BIT)}};
235 EXPECT_EQ(utf8Char.n, utf8CharTemp.n);
236 EXPECT_EQ(utf8Char.ch, utf8CharTemp.ch);
237 utf16Data0 = 0xD7FF;
238 utf8Char = ConvertUtf16ToUtf8(utf16Data0, utf16Data1, false);
239 utf8CharTemp = {3, {UTF8_3B_FIRST | static_cast<uint8_t>(0xD7FF>>12),
240 UTF8_3B_SECOND | (static_cast<uint8_t>(0xD7FF >> 6) & utf::MASK_6BIT),
241 UTF8_3B_THIRD | (static_cast<uint8_t>(0xD7FF) & utf::MASK_6BIT)}};
242 EXPECT_EQ(utf8Char.n, utf8CharTemp.n);
243 EXPECT_EQ(utf8Char.ch, utf8CharTemp.ch);
244 utf16Data0= 0xE000;
245 utf8Char = ConvertUtf16ToUtf8(utf16Data0, utf16Data1, false);
246 utf8CharTemp = {3, {UTF8_3B_FIRST | static_cast<uint8_t>(0xE000 >> 12),
247 UTF8_3B_SECOND | (static_cast<uint8_t>(0xE000 >> 6)& utf::MASK_6BIT),
248 UTF8_3B_THIRD | (static_cast<uint8_t>(0xE000) & utf::MASK_6BIT)}};
249 EXPECT_EQ(utf8Char.n, utf8CharTemp.n);
250 EXPECT_EQ(utf8Char.ch, utf8CharTemp.ch);
251 utf16Data0 = 0xFFFF;
252 utf8Char = ConvertUtf16ToUtf8(utf16Data0, utf16Data1, false);
253 utf8CharTemp = {3, {UTF8_3B_FIRST | static_cast<uint8_t>(0xFFFF >> 12),
254 UTF8_3B_SECOND | (static_cast<uint8_t>(0xFFFF >> 6)& utf::MASK_6BIT),
255 UTF8_3B_THIRD | (static_cast<uint8_t>(0xFFFF) & utf::MASK_6BIT)}};
256 EXPECT_EQ(utf8Char.n, utf8CharTemp.n);
257 EXPECT_EQ(utf8Char.ch, utf8CharTemp.ch);
258 }
259
HWTEST_F_L0(UtfHelperTest,ConvertUtf16ToUtf8_003)260 HWTEST_F_L0(UtfHelperTest, ConvertUtf16ToUtf8_003)
261 {
262 // codePoint lie in [0x10000,0x10FFFF] --> UTF-8(length:4)
263 {
264 uint16_t utf16Data0 = 0xD800;
265 uint16_t utf16Data1= 0xDC00;
266 Utf8Char utf8Char = ConvertUtf16ToUtf8(utf16Data0, utf16Data1, false);
267 uint32_t codePoint = CombineTwoU16(utf16Data0, utf16Data1);
268 Utf8Char utf8CharTemp = {4, {static_cast<uint8_t>((codePoint >> 18) | UTF8_4B_FIRST),
269 static_cast<uint8_t>(((codePoint >> 12) & utf::MASK_6BIT) | utf::MASK1),
270 static_cast<uint8_t>(((codePoint >> 6) & utf::MASK_6BIT) | utf::MASK1),
271 static_cast<uint8_t>((codePoint & utf::MASK_6BIT) | utf::MASK1)}};
272 EXPECT_EQ(utf8Char.n, utf8CharTemp.n);
273 EXPECT_EQ(utf8Char.ch, utf8CharTemp.ch);
274 }
275
276 // 0xD950 0xDF21 --> 0x64321 --> 0xf1 0xa4 0x8c 0xa1
277 {
278 uint16_t utf16Data0 = 0xD950;
279 uint16_t utf16Data1 = 0xDF21;
280 Utf8Char utf8Char = ConvertUtf16ToUtf8(utf16Data0, utf16Data1, false);
281 uint32_t codePoint = CombineTwoU16(utf16Data0, utf16Data1);
282 Utf8Char utf8CharTemp = {4, {static_cast<uint8_t>((codePoint >> 18) | UTF8_4B_FIRST),
283 static_cast<uint8_t>(((codePoint >> 12)& utf::MASK_6BIT)| utf::MASK1),
284 static_cast<uint8_t>(((codePoint >> 6)& utf::MASK_6BIT) | utf::MASK1),
285 static_cast<uint8_t>((codePoint & utf::MASK_6BIT) | utf::MASK1)}};
286 EXPECT_EQ(utf8Char.n, utf8CharTemp.n);
287 EXPECT_EQ(utf8Char.ch, utf8CharTemp.ch);
288 utf8CharTemp = {4, {0xf1, 0xa4, 0x8c, 0xa1}};
289 EXPECT_EQ(utf8Char.n, utf8CharTemp.n);
290 EXPECT_EQ(utf8Char.ch, utf8CharTemp.ch);
291 }
292 }
293
294 /*
295 * @tc.name: Utf16ToUtf8Size
296 * @tc.desc: Enter a string of UTF16 coded sequences and return the length of the sequence converted into UTF8 coded
297 * sequences. "length" indicates the length of the input UTF16 sequence, and "modify" indicates whether
298 * to perform special conversion for.
299 * @tc.type: FUNC
300 */
HWTEST_F_L0(UtfHelperTest,Utf16ToUtf8Size_001)301 HWTEST_F_L0(UtfHelperTest, Utf16ToUtf8Size_001)
302 {
303 // when utf16 data length is only 1 and code in 0xd800-0xdfff, means that is a single code point, it needs to be
304 // represented by three UTF8 code.
305 uint32_t length = 0;
306 uint16_t utf16Value1[1] = {0xD800};
307 const uint16_t *utf16ValuePtr1 = utf16Value1;
308 length = Utf16ToUtf8Size(utf16ValuePtr1, 1, false);
309 EXPECT_EQ(length - 1, UtfLength::THREE);
310 length = 1;
311 uint16_t utf16Value2[1] = {0xDFFF};
312 const uint16_t *utf16ValuePtr2 = utf16Value2;
313 length = Utf16ToUtf8Size(utf16ValuePtr2, 1, false);
314 EXPECT_EQ(length - 1, UtfLength::THREE);
315
316 // special case for U+0000 => c0 80
317 uint16_t utf16Value3[1] = {0x00};
318 const uint16_t *utf16ValuePtr3 = utf16Value3;
319 length = Utf16ToUtf8Size(utf16ValuePtr3, 1, false);
320 EXPECT_EQ(length - 1, 0U);
321 length = Utf16ToUtf8Size(utf16ValuePtr3, 1, true);
322 EXPECT_EQ(length - 1, 2U);
323
324 // code point lie in [0x00, 0x7F], it needs to be represented by one UTF8 code.
325 uint16_t utf16Value4[1] = {0x00};
326 uint16_t utf16Value5[1] = {0x7F};
327 const uint16_t *utf16ValuePtr4 = utf16Value4;
328 const uint16_t *utf16ValuePtr5 = utf16Value5;
329 length = Utf16ToUtf8Size(utf16ValuePtr4, 1, false);
330 EXPECT_EQ(length - 1, 0U);
331 length = Utf16ToUtf8Size(utf16ValuePtr5, 1, false);
332 EXPECT_EQ(length - 1, 1U);
333
334 // code point lie in [0x80, 0x7FF], it needs to be represented by two UTF8 code,
335 uint16_t utf16Value6[1] = {0x80};
336 uint16_t utf16Value7[1] = {0x7FF};
337 const uint16_t *utf16ValuePtr6 = utf16Value6;
338 const uint16_t *utf16ValuePtr7 = utf16Value7;
339 length = Utf16ToUtf8Size(utf16ValuePtr6, 1, false);
340 EXPECT_EQ(length - 1, 2U);
341 length = Utf16ToUtf8Size(utf16ValuePtr7, 1, false);
342 EXPECT_EQ(length - 1, 2U);
343 // code point lie in [0x800, 0xD7FF] or [0xDCoo, 0xFFFF], it needs to be represented by three UTF8 code.
344 uint16_t utf16Value8[1] = {0x800};
345 uint16_t utf16Value9[1] = {0xD7FF};
346 uint16_t utf16Value10[1] = {0xDC00};
347 uint16_t utf16Value11[1] = {0xFFFF};
348 const uint16_t *utf16ValuePtr8 = utf16Value8;
349 const uint16_t *utf16ValuePtr9 = utf16Value9;
350 const uint16_t *utf16ValuePtr10 = utf16Value10;
351 const uint16_t *utf16ValuePtr11 = utf16Value11;
352 length = Utf16ToUtf8Size(utf16ValuePtr8, 1, false);
353 EXPECT_EQ(length - 1, 3U);
354 length = Utf16ToUtf8Size(utf16ValuePtr9, 1, false);
355 EXPECT_EQ(length - 1, 3U);
356 length = Utf16ToUtf8Size(utf16ValuePtr10, 1, false);
357 EXPECT_EQ(length-1, 3U);
358 length = Utf16ToUtf8Size(utf16ValuePtr11, 1, false);
359 EXPECT_EQ(length - 1, 3U);
360 }
361
HWTEST_F_L0(UtfHelperTest,Utf16ToUtf8Size_002)362 HWTEST_F_L0(UtfHelperTest, Utf16ToUtf8Size_002)
363 {
364 // The trail value is valid, located in [0xDc00, 0xDFFF].It needs to be represented by four UTF8 code.
365 uint16_t utf16Value12[2] = {0xD800, 0xDc00};
366 uint16_t utf16Value13[2] = {0xD800, 0xDFFF};
367 uint16_t utf16Value14[2] = {0xDBFF, 0xDC00};
368 uint16_t utf16Value15[2] = {0xDBFF, 0xDFFF};
369 const uint16_t *utf16ValuePtr12 = utf16Value12;
370 const uint16_t *utf16ValuePtr13 = utf16Value13;
371 const uint16_t *utf16ValuePtr14 = utf16Value14;
372 const uint16_t *utf16ValuePtr15 = utf16Value15;
373 uint32_t length = Utf16ToUtf8Size(utf16ValuePtr12, 2, false);
374 EXPECT_EQ(length - 1, 4U);
375 length = Utf16ToUtf8Size(utf16ValuePtr13, 2, false);
376 EXPECT_EQ(length- 1, 4U);
377 length = Utf16ToUtf8Size(utf16ValuePtr14, 2, false);
378 EXPECT_EQ(length - 1, 4U);
379 length = Utf16ToUtf8Size(utf16ValuePtr15, 2, false);
380 EXPECT_EQ(length - 1, 4U);
381
382 // The trail value of Bad sequence is invalid, not located in [0xDC00, 0xDFFF].
383 // Need to return 6 bytes length
384 uint16_t utf16Value16[2] = {0xD800, 0xDBFF};
385 uint16_t utf16Value17[2] = {0xDC00, 0xDFFF};
386 const uint16_t *utf16ValuePtr16 = utf16Value16;
387 const uint16_t *utf16ValuePtr17 = utf16Value17;
388 length = Utf16ToUtf8Size(utf16ValuePtr16, 2, false);
389 EXPECT_EQ(length- 1, 6U);
390 length = Utf16ToUtf8Size(utf16ValuePtr17, 2, false);
391 EXPECT_EQ(length-1, 6U);
392
393 // 0(or 2)+ 1+ 2 + 3 + 4 = 10(or 12)
394 uint16_t utf16Value18[6] = {0x00, 0x7F, 0x80, 0x800, 0xD800, 0xDC00};
395 const uint16_t *utf16ValuePtr18 = utf16Value18;
396 length = Utf16ToUtf8Size(utf16ValuePtr18, 6, false);
397 EXPECT_EQ(length - 1, 10U);
398 length = Utf16ToUtf8Size(utf16ValuePtr18, 6, true);
399 EXPECT_EQ(length - 1, 12U);
400 }
401
402 /*
403 * @tc.name: ConvertUtf8ToUtf16Pair
404 * @tc.desc: Converts a UTF8 encoding sequence encoding a character into a UTF16 encoding sequence, and returns the
405 * sequence and the byte length of the UTF16 encoding sequence. The parameter "combine" identifies whether
406 * to return a pr0xy pair of Unicode values in the secondary plane, or the Unicode value itself.
407 * @tc.type: FUNC
408 */
HWTEST_F_L0(UtfHelperTest,ConvertUtf8ToUtf16Pair)409 HWTEST_F_L0(UtfHelperTest, ConvertUtf8ToUtf16Pair)
410 {
411 // code point lie in [0x00, 0x7F], the length of utf8 code element byte is 1
412 uint8_t utf8Value1[1] = {0x00};
413 uint8_t utf8Value2[1] = {UTF8_1B_MAX};
414 const uint8_t *utf8ValuePtr1 = utf8Value1;
415 const uint8_t *utf8ValuePtr2 = utf8Value2;
416 std::pair<uint32_t, size_t> utf16Res = ConvertUtf8ToUtf16Pair(utf8ValuePtr1);
417 std::pair<uint32_t, size_t> utf16Value = {utf8Value1[0], 1};
418 EXPECT_EQ(utf16Res, utf16Value);
419 utf16Res = ConvertUtf8ToUtf16Pair(utf8ValuePtr2);
420 utf16Value = {utf8Value2[0], 1};
421 EXPECT_EQ(utf16Res, utf16Value);
422 // code point lie in [0x80, 0x7FF], the length of utf8 code element byte is 2
423 uint8_t utf8Value3[2] = {0xc2, 0x80}; // 0x80
424 uint8_t utf8Value4[2] = {0xDF, 0x7F}; // 0x7FF
425 const uint8_t *utf8ValuePtr3 = utf8Value3;
426 const uint8_t *utf8ValuePtr4 = utf8Value4;
427 utf16Res = ConvertUtf8ToUtf16Pair(utf8ValuePtr3);
428 utf16Value = {0x80, 2};
429 EXPECT_EQ(utf16Res, utf16Value);
430 utf16Res = ConvertUtf8ToUtf16Pair(utf8ValuePtr4);
431 utf16Value = {0x7FF, 2};
432 EXPECT_EQ(utf16Res, utf16Value);
433
434 // code point lie in [0x800, 0xD7FF] or [0xDC00,0xFFFF], the length of utf8 code element byte is 3.
435 // when code point lie in [0xD800, 0xDBFF], due to the use of UCS-2, it corresponds to 3 utf8 symbols.
436 uint8_t utf8Value5[3] = {0xE0, 0xA0, 0x80}; // 0x800
437 uint8_t utf8Value6[3] = {0xEF, 0xBF, 0xBF}; // 0xD7FF
438 const uint8_t *utf8ValuePtr5 = utf8Value5;
439 const uint8_t *utf8ValuePtr6 = utf8Value6;
440 utf16Res = ConvertUtf8ToUtf16Pair(utf8ValuePtr5);
441 utf16Value = {0x800, 3};
442 EXPECT_EQ(utf16Res, utf16Value);
443 utf16Res = ConvertUtf8ToUtf16Pair(utf8ValuePtr6);
444 utf16Value = {0xFFFF, 3};
445 EXPECT_EQ(utf16Res, utf16Value);
446 // code point lie in [0x10000, 0x10FFFF], the length of utf8 code element byte is 4.
447 uint8_t utf8Value9[4] = {0xF0, 0x90, 0x80, 0x80}; // 0x10000
448 uint8_t utf8Value10[4] = {0xF4, 0x8F, 0xBF, 0xBF}; // 0x10FFFF
449 const uint8_t *utf8ValuePtr9 = utf8Value9;
450 const uint8_t *utf8ValuePtr10 = utf8Value10;
451 utf16Res = ConvertUtf8ToUtf16Pair(utf8ValuePtr9);
452 utf16Value = {0xD800 << 16 | 0xDC00U, 4};
453 EXPECT_EQ(utf16Res, utf16Value);
454 utf16Res = ConvertUtf8ToUtf16Pair(utf8ValuePtr10);
455 utf16Value = {0xDBFF << 16 | 0xDFFF, 4};
456 EXPECT_EQ(utf16Res, utf16Value);
457 utf16Res = ConvertUtf8ToUtf16Pair(utf8ValuePtr9, true);
458 utf16Value = {0x10000, 4};
459 EXPECT_EQ(utf16Res, utf16Value);
460 utf16Res = ConvertUtf8ToUtf16Pair(utf8ValuePtr10, true);
461 utf16Value = {0x10FFFF, 4};
462 EXPECT_EQ(utf16Res, utf16Value);
463 }
464
465 /*
466 * @tc.name: Utf8ToUtf16Size
467 * @tc.desc: Enter a string of UTF8 coded sequences and return the length of the sequence converted into UTF16 coded
468 * sequences.
469 * @tc.type: FUNC
470 */
HWTEST_F_L0(UtfHelperTest,Utf8ToUtf16Size)471 HWTEST_F_L0(UtfHelperTest, Utf8ToUtf16Size)
472 {
473 // when code point lie in (0x00, 0xFFFF], the required utf16 code element length is 1.
474 uint8_t utf8ValueOneByteMin[1] = {0x00};
475 uint8_t utf8ValueOneByteMax[4] = {0xEF, 0xBF, 0xBF, 0x00}; // 0xFFFF
476 const uint8_t *utf8ValueOneByteMinPtr = utf8ValueOneByteMin;
477 const uint8_t *utf8ValueOneByteMaxPtr = utf8ValueOneByteMax;
478 size_t length = Utf8ToUtf16Size(utf8ValueOneByteMinPtr, sizeof(utf8ValueOneByteMin));
479 EXPECT_EQ(length, 1U);
480 length = Utf8ToUtf16Size(utf8ValueOneByteMaxPtr, sizeof(utf8ValueOneByteMax));
481 EXPECT_EQ(length, 2U);
482 // when code point lie in [0x10000, 0x10FFFF], the required utf16 code element length is 2.
483 const uint8_t utf8ValueTwoBytesMin[5] = {0xF0, 0x90, 0x80, 0x80, 0x00}; // 0x10000
484 const uint8_t utf8ValueTwoBytesMax[5] = {0xF4, 0x8F, 0xBF, 0xBF, 0x00}; // 0x10FFFF
485 const uint8_t *utf8ValueTwoBytesMinPtr = utf8ValueTwoBytesMin;
486 const uint8_t *utf8ValueTwoBytesMaxPtr = utf8ValueTwoBytesMax;
487 length = Utf8ToUtf16Size(utf8ValueTwoBytesMinPtr, sizeof(utf8ValueTwoBytesMin));
488 EXPECT_EQ(length, 3U);
489 length = Utf8ToUtf16Size(utf8ValueTwoBytesMaxPtr, sizeof(utf8ValueTwoBytesMax));
490 EXPECT_EQ(length, 3U);
491 uint8_t utf8Value[12] = {
492 0xEF, 0xBF, 0xBF, 0xF0,
493 0x90, 0x80, 0x80, 0xF4,
494 0x8F, 0xBF, 0xBF, 0x00};
495 const uint8_t *utf8ValuePtr = utf8Value;
496 length = Utf8ToUtf16Size(utf8ValuePtr, sizeof(utf8Value));
497 EXPECT_EQ(length, 6U);
498 }
499
500 /*
501 * @tc.name: ConvertRegionUtf16ToUtf8
502 * @tc.desc: Input aUTF16-encoded sequence (thelength is "utf16Len"), convert part of the sequence into a UTF8-encoded
503 * sequence, and save it to "utf8Out"(the maximum length is "utf8Len"). The start parameter indicates the
504 * start position of the conversion. Whether to perform special processing for O in the "modify" parameter.
505 * @tc.type: FUNC
506 */
HWTEST_F_L0(UtfHelperTest,ConvertRegionUtf16ToUtf8)507 HWTEST_F_L0(UtfHelperTest, ConvertRegionUtf16ToUtf8)
508 {
509 size_t utf16Len = 8;
510 size_t utf8Len = 100;
511 size_t start = 0;
512 bool modify = false;
513 uint16_t utf16Value[8] = {
514 0x00, // 0 or 2 (special case for \u0000 ==> C080 - 1100'0000 1000'0000)
515 0x7F, // 1(0x00, 0x7F]
516 0x7FF, // 2 [0x80, 0x7FF]
517 0x800, // 3 [0x800, 0xD7FF]
518 0xD800, // 3 [0xD800, 0xDFFF]
519 0xFFFF, // 3 [0xE000, 0xFFFF]
520 0xD800, 0xDFFF}; // 4 [0x10000, 0x10FFFF]
521 const uint16_t *utf16ValuePtr = utf16Value;
522 uint8_t *utf8Out = (uint8_t*)malloc(utf8Len);
523 size_t utf8Pos = ConvertRegionUtf16ToUtf8(utf16ValuePtr, utf8Out, utf16Len, utf8Len, start, modify);
524 // 0 + 1 + 2 +(3 *3)+ 4= 16
525 EXPECT_EQ(utf8Pos, 16U);
526 // 2 + 1 + 2 +(3 * 3)+ 4 = 18
527 modify = true;
528 utf8Pos = ConvertRegionUtf16ToUtf8(utf16ValuePtr, utf8Out, utf16Len, utf8Len, start, modify);
529 EXPECT_EQ(utf8Pos, 18U);
530 free(utf8Out);
531 }
532
533 /*
534 * @tc.name: ConvertRegionUtf8ToUtf16
535 * @tc.desc: Input a UTF8-encoded sequence, convert part of the sequence into a UTF8-encoded sequence, and save it to
536 * "utf16Out"(the maximum length is "utf16Len"), The start parameter indicates the start position of the
537 * conversion.
538 * @tc.type: FUNC
539 */
HWTEST_F_L0(UtfHelperTest,ConvertRegionUtf8ToUtf16)540 HWTEST_F_L0(UtfHelperTest, ConvertRegionUtf8ToUtf16)
541 {
542 size_t utf16Len = 100;
543 size_t start = 0;
544 uint8_t utf8Value[10] = {
545 0x7F, // 1-length UTF16 encoding
546 0xDF, 0xBF, // 1-length UTF16 encoding
547 0xEF, 0xBF, 0xBF, // 1-length UTF16 encoding
548 0xF4, 0x8F, 0xBF, 0xBF}; // 2-length UTF16 encoding
549 const uint8_t *utf8ValuePtr = utf8Value;
550 uint16_t *utf16Out = (uint16_t*)malloc(utf16Len);
551 size_t outPos = ConvertRegionUtf8ToUtf16(utf8ValuePtr, utf16Out, sizeof(utf8Value), utf16Len, start);
552 // 1 + 1 + 1 + 2 = 5s
553 EXPECT_EQ(outPos, 5U);
554 // 1 + 2 = 3
555 start = 3;
556 outPos = ConvertRegionUtf8ToUtf16(utf8ValuePtr, utf16Out, sizeof(utf8Value), utf16Len, start);
557 EXPECT_EQ(outPos, 3U);
558
559 // When "start" is in the middle of a symbol sequence
560 start = 2;
561 outPos = ConvertRegionUtf8ToUtf16(utf8ValuePtr, utf16Out, sizeof(utf8Value), utf16Len, start);
562 EXPECT_EQ(outPos, 0U);
563 start = 4;
564 outPos = ConvertRegionUtf8ToUtf16(utf8ValuePtr, utf16Out, sizeof(utf8Value), utf16Len, start);
565 EXPECT_EQ(outPos, 0U);
566 start = 7;
567 outPos = ConvertRegionUtf8ToUtf16(utf8ValuePtr, utf16Out, sizeof(utf8Value), utf16Len, start);
568 EXPECT_EQ(outPos, 0U);
569 free(utf16Out);
570 }
571 } // namespace panda:test
572