1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to
6 * deal in the Software without restriction, including without limitation the
7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 * sell copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 * IN THE SOFTWARE.
21 */
22 #ifndef __LITEOS__
23 #include "test.h"
24 #include <errno.h>
25 #include <iconv.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #define BUFFER_SIZE 1024
29 #define IGNORE_SIZE 9
30
31 int set_iconv_icu_enable(void);
32
33 typedef struct StatefulCombined {
34 unsigned sign;
35 const unsigned char* to;
36 const unsigned char* from;
37 iconv_t base_cd;
38 unsigned state;
39 } StatefulCombined;
40
41 typedef struct NameMap {
42 const char* source;
43 const char* target;
44 } NameMap;
45
46
47 // Global Variables
48 static NameMap g_mappings[] = {
49 {"utf8\0char\0\0", "UTF-8"},
50 {"utf7\0\0", "UTF-7"},
51 {"ucs2\0utf16\0ucs2be\0utf16be\0\0", "UTF-16BE"},
52 {"ucs2le\0utf16le\0\0", "UTF-16LE"},
53 {"ucs4\0utf32\0ucs4be\0utf32be\0\0", "UTF-32BE"},
54 {"wchart\0ucs4le\0utf32le\0\0", "UTF-32LE"},
55 {"ascii\0usascii\0""20127\0iso646\0iso646us\0\0", "US-ASCII"},
56 {"eucjp\0eucjp2007\0\0", "euc-jp-2007"},
57 {"shiftjis\0sjis\0cp932\0ibm943p15a2003\0\0", "ibm-943_P15A-2003"},
58 {"gb18030\0\0", "gb18030"},
59 {"gbk\0""54936\0windows9362000\0\0", "windows-936-2000"},
60 {"gb2312\0""52936\0ibm1383p1101999\0\0", "ibm-1383_P110-1999"},
61 {"big5\0""950\0bigfive\0cp950\0windows9502000\0\0", "windows-950-2000"},
62 {"big5hk\0big5hkscs\0""951\0ibm1375p1002008\0\0", "ibm-1375_P100-2008"},
63 {"euckr\0ibm970p110p1102006u2\0\0", "ibm-970_P110_P110-2006_U2"},
64 {"ksc5601\0ksx1001\0cp949\0windows9492000\0\0", "windows-949-2000"},
65 {"iso88591\0latin1\0\0", "ISO-8859-1"},
66 {"iso88592\0ibm912p1001995\0\0", "ibm-912_P100-1995"},
67 {"iso88593\0ibm913p1002000\0\0", "ibm-913_P100-2000"},
68 {"iso88594\0ibm914p1001995\0\0", "ibm-914_P100-1995"},
69 {"iso88595\0ibm915p1001995\0\0", "ibm-915_P100-1995"},
70 {"iso88596\0ibm1089p1001995\0\0", "ibm-1089_P100-1995"},
71 {"iso88597\0ibm9005x1102007\0\0", "ibm-9005_X110-2007"},
72 {"iso88598\0ibm5012p1001999\0\0", "ibm-5012_P100-1999"},
73 {"iso88599\0ibm920p1001995\0\0", "ibm-920_P100-1995"},
74 {"iso885910\0iso8859101998\0\0", "iso-8859_10-1998"},
75 {"iso885911\0iso8859112001\0\0", "iso-8859_11-2001"},
76 {"tis620\0windows8742000\0\0", "windows-874-2000"},
77 {"iso885913\0ibm921p1001995\0\0", "ibm-921_P100-1995"},
78 {"iso885914\0iso8859141998\0\0", "iso-8859_14-1998"},
79 {"iso885915\0latin9\0ibm923p1001998\0\0", "ibm-923_P100-1998"},
80 {"cp1250\0windows1250\0ibm5346p1001998\0\0", "ibm-5346_P100-1998"},
81 {"cp1251\0windows1251\0ibm5347p1001998\0\0", "ibm-5347_P100-1998"},
82 {"cp1252\0windows1252\0ibm5348p1001997\0\0", "ibm-5348_P100-1997"},
83 {"cp1253\0windows1253\0ibm5349p1001998\0\0", "ibm-5349_P100-1998"},
84 {"cp1254\0windows1254\0ibm5350p1001998\0\0", "ibm-5350_P100-1998"},
85 {"cp1255\0windows1255\0ibm9447p1002002\0\0", "ibm-9447_P100-2002"},
86 {"cp1256\0windows1256\0ibm9448x1002005\0\0", "ibm-9448_X100-2005"},
87 {"cp1257\0windows1257\0ibm9449p1002002\0\0", "ibm-9449_P100-2002"},
88 {"cp1258\0windows1258\0ibm5354p1001998\0\0", "ibm-5354_P100-1998"},
89 {"koi8r\0ibm878p1001996\0\0", "ibm-878_P100-1996"},
90 {"koi8u\0ibm1168p1002002\0\0", "ibm-1168_P100-2002"},
91 {"cp437\0ibm437p1001995\0\0", "ibm-437_P100-1995"},
92 {"cp850\0ibm850p1001995\0\0", "ibm-850_P100-1995"},
93 {"cp866\0ibm866p1001995\0\0", "ibm-866_P100-1995"},
94 {"ibm1047\0cp1047\0ibm1047p1001995\0\0", "ibm-1047_P100-1995"},
95 };
96 char* g_source_str;
97 char* g_target_str;
98 char g_mids[BUFFER_SIZE];
99 char g_outs[BUFFER_SIZE];
100 int32_t g_target_num = sizeof(g_mappings) / sizeof(g_mappings[0]);
101 char g_ins[] = {
102 0x00, 0x20, // ' ' (space)
103 0x00, 0x21, // '!'
104 0x00, 0x22, // '"'
105 0x00, 0x23, // '#'
106 0x00, 0x24, // '$'
107 0x00, 0x25, // '%'
108 0x00, 0x26, // '&'
109 0x00, 0x27, // '''
110 0x00, 0x28, // '('
111 0x00, 0x29, // ')'
112 0x00, 0x2A, // '*'
113 0x00, 0x2B, // '+'
114 0x00, 0x2C, // ','
115 0x00, 0x2D, // '-'
116 0x00, 0x2E, // '.'
117 0x00, 0x2F, // '/'
118 0x00, 0x30, // '0'
119 0x00, 0x31, // '1'
120 0x00, 0x32, // '2'
121 0x00, 0x33, // '3'
122 0x00, 0x34, // '4'
123 0x00, 0x35, // '5'
124 0x00, 0x36, // '6'
125 0x00, 0x37, // '7'
126 0x00, 0x38, // '8'
127 0x00, 0x39, // '9'
128 0x00, 0x3A, // ':'
129 0x00, 0x3B, // ';'
130 0x00, 0x3C, // '<'
131 0x00, 0x3D, // '='
132 0x00, 0x3E, // '>'
133 0x00, 0x3F, // '?'
134 0x00, 0x40, // '@'
135 0x00, 0x41, // 'A'
136 0x00, 0x42, // 'B'
137 0x00, 0x43, // 'C'
138 0x00, 0x44, // 'D'
139 0x00, 0x45, // 'E'
140 0x00, 0x46, // 'F'
141 0x00, 0x47, // 'G'
142 0x00, 0x48, // 'H'
143 0x00, 0x49, // 'I'
144 0x00, 0x4A, // 'J'
145 0x00, 0x4B, // 'K'
146 0x00, 0x4C, // 'L'
147 0x00, 0x4D, // 'M'
148 0x00, 0x4E, // 'N'
149 0x00, 0x4F, // 'O'
150 0x00, 0x50, // 'P'
151 0x00, 0x51, // 'Q'
152 0x00, 0x52, // 'R'
153 0x00, 0x53, // 'S'
154 0x00, 0x54, // 'T'
155 0x00, 0x55, // 'U'
156 0x00, 0x56, // 'V'
157 0x00, 0x57, // 'W'
158 0x00, 0x58, // 'X'
159 0x00, 0x59, // 'Y'
160 0x00, 0x5A, // 'Z'
161 0x00, 0x5B, // '['
162 0x00, 0x5C, // '\\'
163 0x00, 0x5D, // ']'
164 0x00, 0x5E, // '^'
165 0x00, 0x5F, // '_'
166 0x00, 0x60, // '`'
167 0x00, 0x61, // 'a'
168 0x00, 0x62, // 'b'
169 0x00, 0x63, // 'c'
170 0x00, 0x64, // 'd'
171 0x00, 0x65, // 'e'
172 0x00, 0x66, // 'f'
173 0x00, 0x67, // 'g'
174 0x00, 0x68, // 'h'
175 0x00, 0x69, // 'i'
176 0x00, 0x6A, // 'j'
177 0x00, 0x6B, // 'k'
178 0x00, 0x6C, // 'l'
179 0x00, 0x6D, // 'm'
180 0x00, 0x6E, // 'n'
181 0x00, 0x6F, // 'o'
182 0x00, 0x70, // 'p'
183 0x00, 0x71, // 'q'
184 0x00, 0x72, // 'r'
185 0x00, 0x73, // 's'
186 0x00, 0x74, // 't'
187 0x00, 0x75, // 'u'
188 0x00, 0x76, // 'v'
189 0x00, 0x77, // 'w'
190 0x00, 0x78, // 'x'
191 0x00, 0x79, // 'y'
192 0x00, 0x7A, // 'z'
193 0x00, 0x7B, // '{'
194 0x00, 0x7C, // '|'
195 0x00, 0x7D, // '}'
196 0x00, 0x7E // '~'
197 };
198 size_t g_ins_len = sizeof(g_ins);
199 char* g_ins_zh = "Big5 编码示例";
200 size_t g_ins_zh_len;
201
iconv_close_with_strerror(iconv_t cd)202 void iconv_close_with_strerror(iconv_t cd)
203 {
204 if (iconv_close(cd)) {
205 t_error("closed iconv failed, error: %s \n", strerror(errno));
206 }
207 }
208
alias_test(void)209 void alias_test(void)
210 {
211 char* s;
212 StatefulCombined *scd = 0;
213 for (s = g_source_str; *s;) {
214 scd = (void *)iconv_open(s, s);
215 if (scd == (iconv_t)-1) {
216 t_error("iconv opened failed, from: %s, to: %s, error: %s \n", s, s, strerror(errno));
217 return;
218 }
219 if (strcmp((void*)scd->to, g_target_str) != 0) {
220 t_error("verify error: [input]%s, [actual_to]%s [expect_to]%s\n", s, scd->to, g_target_str);
221 }
222 if (strcmp((void*)scd->from, g_target_str) != 0) {
223 t_error("verify error: [input]%s, [actual_from]%s [expect_from]%s\n", s, scd->from, g_target_str);
224 }
225 s += strlen(s) + 1;
226 iconv_close_with_strerror(scd);
227 }
228 }
229
iconv_test(char * from,char * to,char ** inptrptr,size_t * input_len_ptr,char ** outptrptr,size_t * output_len_ptr)230 size_t iconv_test(char* from, char* to,
231 char** inptrptr, size_t* input_len_ptr, char** outptrptr, size_t* output_len_ptr)
232 {
233 iconv_t cd = iconv_open((void*)to, (void*)from);
234 if (cd == (iconv_t)-1) {
235 t_error("iconv opened failed, from: %s, to: %s, error: %s \n", from, to, strerror(errno));
236 return (size_t)-1;
237 }
238
239 size_t res = iconv(cd, inptrptr, input_len_ptr, outptrptr, output_len_ptr);
240 if (res) {
241 iconv_close_with_strerror(cd);
242 return res;
243 }
244
245 iconv_close_with_strerror(cd);
246 return res;
247 }
248
iconv_exchange(char * from,char * to,char * ins,size_t ins_len)249 void iconv_exchange(char* from, char* to, char* ins, size_t ins_len)
250 {
251 char* ins_ptr = ins;
252 char* mids_ptr = g_mids;
253 char* outs_ptr = g_outs;
254 size_t ins_bytes = ins_len;
255 size_t mids_bytes = BUFFER_SIZE;
256 size_t outs_bytes = BUFFER_SIZE;
257
258 iconv_test(from, to, &ins_ptr, &ins_bytes, &mids_ptr, &mids_bytes);
259
260 ins_ptr = g_mids;
261 ins_bytes = BUFFER_SIZE - mids_bytes;
262 iconv_test(to, from, &ins_ptr, &ins_bytes, &outs_ptr, &outs_bytes);
263 }
264
charcmp(char * a,char * b)265 static int charcmp(char* a, char* b)
266 {
267 for (; *a && *b; a++, b++) {
268 if (*a != *b) {return 1;}
269 }
270 return *a != *b;
271 }
272
iconv_exchange_with_charcmp(char * from,char * to,char * ins,size_t ins_len)273 void iconv_exchange_with_charcmp(char* from, char* to, char* ins, size_t ins_len)
274 {
275 iconv_exchange(from, to, ins, ins_len);
276 if (charcmp(ins, g_outs) != 0) {
277 t_error("compare error [type]%s, [ins] %s, [outs] %s\n",
278 to, ins, g_outs);
279 }
280 }
281
test_to_ignore_skip(void)282 void test_to_ignore_skip(void)
283 {
284 char* expect = "Big5 示例";
285 iconv_exchange("utf8", "big5//IGNORE", g_ins_zh, g_ins_zh_len);
286 if (strcmp(expect, g_outs) != 0) {
287 t_error("iconv with ignore error: [ins] %s [outs] %s [expect] %s\n",
288 g_ins_zh, g_outs, expect);
289 }
290 }
291
test_to_translit_skip(void)292 void test_to_translit_skip(void)
293 {
294 char* expect = "Big5 ??示例";
295 iconv_exchange("utf8", "big5//TRANSLIT", g_ins_zh, g_ins_zh_len);
296 if (strcmp(expect, g_outs) != 0) {
297 t_error("iconv with translit error: [ins] %s [outs] %s [expect] %s\n",
298 g_ins_zh, g_outs, expect);
299 }
300 }
301
test_errno_ilseq(void)302 void test_errno_ilseq(void)
303 {
304 char* ins_ptr = g_ins_zh;
305 size_t ins_bytes = g_ins_zh_len;
306 char* outs_ptr = g_outs;
307 size_t outs_bytes = BUFFER_SIZE;
308 size_t res = iconv_test("utf8", "big5", &ins_ptr, &ins_bytes, &outs_ptr, &outs_bytes);
309 if (res != (size_t)-1 || errno != EILSEQ) {
310 t_error("Failed: [ins] %s [outs] %s [res] %d [errno] %s\n",
311 g_ins_zh, g_outs, res, strerror(errno));
312 }
313 }
314
test_errno_e2big(void)315 void test_errno_e2big(void)
316 {
317 char* ins_ptr = g_ins_zh;
318 size_t ins_bytes = g_ins_zh_len;
319 char* outs_ptr = g_outs;
320 size_t outs_bytes = 10;
321 size_t res = iconv_test("utf8", "utf16", &ins_ptr, &ins_bytes, &outs_ptr, &outs_bytes);
322 if (res != (size_t)-1 || errno != E2BIG) {
323 t_error("Failed: [ins] %s [outs] %s [res] %d [errno] %s\n",
324 g_ins_zh, g_outs, res, strerror(errno));
325 }
326 }
327
test_empty_type(void)328 void test_empty_type(void)
329 {
330 StatefulCombined *scd = 0;
331 scd = (void *)iconv_open("", "");
332 if (strcmp((void*)scd->to, "UTF-8") != 0 || strcmp((void*)scd->from, "UTF-8") != 0) {
333 t_error("verify error: empty type not default fill utf8");
334 }
335 iconv_close_with_strerror(scd);
336 }
337
main(void)338 int main(void)
339 {
340 int icu_res = set_iconv_icu_enable();
341 if (icu_res != 0) {
342 t_error("set_iconv_icu_enable failed, error: %d \n", icu_res);
343 return t_status;
344 }
345 icu_res = set_iconv_icu_enable();
346 if (icu_res != 0) {
347 t_error("set_iconv_icu_enable twice failed, error: %d \n", icu_res);
348 return t_status;
349 }
350 g_ins_zh_len = strlen(g_ins_zh);
351
352 for (int i = 0; i < g_target_num; i++) {
353 g_target_str = (void*)g_mappings[i].target;
354 g_source_str = (void*)g_mappings[i].source;
355
356 // test all avail alias with iconv_open
357 alias_test();
358
359 // test iconv without ignore
360 iconv_exchange_with_charcmp("utf16", g_target_str, g_ins, g_ins_len);
361
362 // test iconv with ignore (norm input->not skip)
363 char* target_str_with_ignore = malloc(strlen(g_target_str) + IGNORE_SIZE);
364 strcpy(target_str_with_ignore, g_target_str);
365 strcat(target_str_with_ignore, "//IGNORE");
366 iconv_exchange_with_charcmp("utf16", target_str_with_ignore, g_ins, g_ins_len);
367 iconv_exchange_with_charcmp("utf16//IGNORE", target_str_with_ignore, g_ins, g_ins_len);
368 free(target_str_with_ignore);
369 }
370
371 // test iconv with ignore (special input -> skip)
372 test_to_ignore_skip();
373
374 // test iconv with translit (special input -> translit)
375 test_to_translit_skip();
376
377 // test basic type (iso885916)
378 iconv_exchange_with_charcmp("utf16", "iso885916", g_ins, g_ins_len);
379
380 // test errno
381 test_errno_ilseq();
382 test_errno_e2big();
383
384 // empty type -> fill UTF-8
385 test_empty_type();
386
387 return t_status;
388 }
389 #endif