• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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