]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - tools/test/iconv/gnu/gnu.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / tools / test / iconv / gnu / gnu.c
1 /*-
2  * Copyright (C) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/endian.h>
31 #include <sys/types.h>
32
33 #include <err.h>
34 #include <errno.h>
35 #include <iconv.h>
36 #include <stdbool.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 static bool uc_hook = false;
42 static bool wc_hook = false;
43 static bool mb_uc_fb = false;
44
45 void     unicode_hook(unsigned int mbr, void *data);
46 void     wchar_hook(wchar_t wc, void *data);
47
48 void    mb_to_uc_fb(const char *, size_t,
49             void (*write_replacement) (const unsigned int *, size_t, void *),
50             void *, void *);
51
52 static int
53 ctl_get_translit1(void)
54 {
55         iconv_t cd;
56         int arg, ret;
57
58         cd = iconv_open("ASCII//TRANSLIT", "UTF-8");
59         if (cd == (iconv_t)-1)
60                 return (-1);
61         if (iconvctl(cd, ICONV_GET_TRANSLITERATE, &arg) == 0)
62                 ret = (arg == 1) ? 0 : -1;
63         else
64                 ret = -1;
65         if (iconv_close(cd) == -1)
66                 return (-1);
67         return (ret);
68 }
69
70 static int
71 ctl_get_translit2(void)
72 {
73         iconv_t cd;
74         int arg, ret;
75
76         cd = iconv_open("ASCII", "UTF-8");
77         if (cd == (iconv_t)-1)
78                 return (-1);
79         if (iconvctl(cd, ICONV_GET_TRANSLITERATE, &arg) == 0)
80                 ret = (arg == 0) ? 0 : -1;
81         else
82                 ret = -1;
83         if (iconv_close(cd) == -1)
84                 return (-1);
85         return (ret);
86 }
87
88 static int
89 ctl_set_translit1(void)
90 {
91         iconv_t cd;
92         int arg = 1, ret;
93
94         cd = iconv_open("ASCII", "UTF-8");
95         if (cd == (iconv_t)-1)
96                 return (-1);
97         ret = iconvctl(cd, ICONV_SET_TRANSLITERATE, &arg) == 0 ? 0 : -1;
98         if (iconv_close(cd) == -1)
99                 return (-1);
100         return (ret);
101 }
102
103 static int
104 ctl_set_translit2(void)
105 {
106         iconv_t cd;
107         int arg = 0, ret;
108
109         cd = iconv_open("ASCII//TRANSLIT", "UTF-8");
110         if (cd == (iconv_t)-1)
111                 return (-1);
112         ret = iconvctl(cd, ICONV_SET_TRANSLITERATE, &arg) == 0 ? 0 : -1;
113         if (iconv_close(cd) == -1)
114                 return (-1);
115         return (ret);
116 }
117
118 static int
119 ctl_get_discard_ilseq1(void)
120 {
121         iconv_t cd;
122         int arg, ret;
123
124         cd = iconv_open("ASCII", "UTF-8");
125         if (cd == (iconv_t)-1)
126                 return (-1);
127         if (iconvctl(cd, ICONV_GET_DISCARD_ILSEQ, &arg) == 0)
128                 ret = arg == 0 ? 0 : -1;
129         else
130                 ret = -1;
131         if (iconv_close(cd) == -1)
132                 return (-1);
133         return (ret);
134 }
135
136 static int
137 ctl_get_discard_ilseq2(void)
138 {
139         iconv_t cd;
140         int arg, ret;
141
142         cd = iconv_open("ASCII//IGNORE", "UTF-8");
143         if (cd == (iconv_t)-1)
144                 return (-1);
145         if (iconvctl(cd, ICONV_GET_DISCARD_ILSEQ, &arg) == 0)
146                 ret = arg == 1 ? 0 : -1;
147         else
148                 ret = -1;
149         if (iconv_close(cd) == -1)
150                 return (-1);
151         return (ret);
152 }
153
154 static int
155 ctl_set_discard_ilseq1(void)
156 {
157         iconv_t cd;
158         int arg = 1, ret;
159
160         cd = iconv_open("ASCII", "UTF-8");
161         if (cd == (iconv_t)-1)
162                 return (-1);
163         ret = iconvctl(cd, ICONV_SET_DISCARD_ILSEQ, &arg) == 0 ? 0 : -1;
164         if (iconv_close(cd) == -1)
165                 return (-1);
166         return (ret);
167 }
168
169 static int
170 ctl_set_discard_ilseq2(void)
171 {
172         iconv_t cd;
173         int arg = 0, ret;
174
175         cd = iconv_open("ASCII//IGNORE", "UTF-8");
176         if (cd == (iconv_t)-1)
177         return (-1); 
178         ret = iconvctl(cd, ICONV_SET_DISCARD_ILSEQ, &arg) == 0 ? 0 : -1;
179         if (iconv_close(cd) == -1)
180                 return (-1);
181         return (ret);
182 }
183
184 static int
185 ctl_trivialp1(void)
186 {
187         iconv_t cd;
188         int arg, ret;
189
190         cd = iconv_open("latin2", "latin2");
191         if (cd == (iconv_t)-1)
192                 return (-1);
193         if (iconvctl(cd, ICONV_TRIVIALP, &arg) == 0) {
194                 ret = (arg == 1) ? 0 : -1;
195         } else
196                 ret = -1;
197         if (iconv_close(cd) == -1)
198                 return (-1);
199         return (ret);
200 }
201
202 static int
203 ctl_trivialp2(void)
204 {
205         iconv_t cd;
206         int arg, ret;
207
208         cd = iconv_open("ASCII", "KOI8-R");
209         if (cd == (iconv_t)-1)
210                 return (-1);
211         if (iconvctl(cd, ICONV_TRIVIALP, &arg) == 0) {
212                 ret = (arg == 0) ? 0 : -1;
213         } else
214                 ret = -1;
215         if (iconv_close(cd) == -1)
216                 return (-1);
217         return (ret);
218 }
219
220 void
221 unicode_hook(unsigned int mbr, void *data)
222 {
223
224 #ifdef VERBOSE
225         printf("Unicode hook: %u\n", mbr);
226 #endif
227         uc_hook = true;
228 }
229
230 void
231 wchar_hook(wchar_t wc, void *data)
232 {
233
234 #ifdef VERBOSE
235         printf("Wchar hook: %ull\n", wc);
236 #endif
237         wc_hook = true;
238 }
239
240 static int
241 ctl_uc_hook(void)
242 {
243         struct iconv_hooks hooks;
244         iconv_t cd;
245         size_t inbytesleft = 15, outbytesleft = 40;
246         const char **inptr;
247         const char *s = "Hello World!";
248         char **outptr;
249         char *outbuf;
250
251         inptr = &s;
252         hooks.uc_hook = unicode_hook;
253         hooks.wc_hook = NULL;
254
255         outbuf = malloc(40);
256         outptr = &outbuf;
257
258         cd = iconv_open("UTF-8", "ASCII");
259         if (cd == (iconv_t)-1)
260                 return (-1);
261         if (iconvctl(cd, ICONV_SET_HOOKS, (void *)&hooks) != 0)
262                 return (-1);
263         if (iconv(cd, inptr, &inbytesleft, outptr, &outbytesleft) == (size_t)-1)
264                 return (-1);
265         if (iconv_close(cd) == -1)
266                 return (-1);
267         return (uc_hook ? 0 : 1);
268 }
269
270 static int
271 ctl_wc_hook(void)
272 {
273         struct iconv_hooks hooks;
274         iconv_t cd;
275         size_t inbytesleft, outbytesleft = 40;
276         const char **inptr;
277         const char *s = "Hello World!";
278         char **outptr;
279         char *outbuf;
280
281         inptr = &s;
282         hooks.wc_hook = wchar_hook;
283         hooks.uc_hook = NULL;
284
285         outbuf = malloc(40);
286         outptr = &outbuf;
287         inbytesleft = sizeof(s);
288
289         cd = iconv_open("SHIFT_JIS", "ASCII");
290         if (cd == (iconv_t)-1)
291                 return (-1);
292         if (iconvctl(cd, ICONV_SET_HOOKS, (void *)&hooks) != 0)
293                 return (-1);
294         if (iconv(cd, inptr, &inbytesleft, outptr, &outbytesleft) == (size_t)-1)
295                 return (-1);
296         if (iconv_close(cd) == -1)
297                 return (-1);
298         return (wc_hook ? 0 : 1);
299 }
300
301
302
303 static int
304 gnu_canonicalize1(void)
305 {
306
307         return (strcmp(iconv_canonicalize("latin2"), "ISO-8859-2"));
308 }
309
310 static int
311 gnu_canonicalize2(void)
312 {
313
314         return (!strcmp(iconv_canonicalize("ASCII"), iconv_canonicalize("latin2")));
315 }
316
317
318 static int
319 iconvlist_cb(unsigned int count, const char * const *names, void *data)
320 {
321
322         return (*(int *)data = ((names == NULL) && (count > 0)) ? -1 : 0);
323 }
324
325 static int
326 gnu_iconvlist(void)
327 {
328         int i;
329
330         iconvlist(iconvlist_cb, (void *)&i);
331         return (i);
332 }
333
334 void
335 mb_to_uc_fb(const char* inbuf, size_t inbufsize,
336     void (*write_replacement)(const unsigned int *buf, size_t buflen,
337        void* callback_arg), void* callback_arg, void* data)
338 {
339         unsigned int c = 0x3F;
340
341         mb_uc_fb = true;
342         write_replacement((const unsigned int *)&c, 1, NULL);
343 }
344
345 static int __unused
346 ctl_mb_to_uc_fb(void)
347 {
348         struct iconv_fallbacks fb;
349         iconv_t cd;
350         size_t inbytesleft, outbytesleft;
351         uint16_t inbuf[1] = { 0xF187 };
352         uint8_t outbuf[4] = { 0x00, 0x00, 0x00, 0x00 };
353         const char *inptr;
354         char *outptr;
355         int ret;
356
357         if ((cd = iconv_open("UTF-32", "UTF-8")) == (iconv_t)-1)
358                 return (1);
359
360         fb.uc_to_mb_fallback = NULL;
361         fb.mb_to_wc_fallback = NULL;
362         fb.wc_to_mb_fallback = NULL;
363         fb.mb_to_uc_fallback = mb_to_uc_fb;
364         fb.data = NULL;
365
366         if (iconvctl(cd, ICONV_SET_FALLBACKS, (void *)&fb) != 0)
367                 return (1);
368
369         inptr = (const char *)inbuf;
370         outptr = (char *)outbuf;
371         inbytesleft = 2;
372         outbytesleft = 4;
373
374         errno = 0;
375         ret = iconv(cd, &inptr, &inbytesleft, &outptr, &outbytesleft);
376
377 #ifdef VERBOSE
378         printf("mb_uc fallback: %c\n", outbuf[0]);
379 #endif
380
381         if (mb_uc_fb && (outbuf[0] == 0x3F))
382                 return (0);
383         else
384                 return (1);
385 }
386
387 static int
388 gnu_openinto(void)
389 {
390         iconv_allocation_t *myspace;
391         size_t inbytesleft, outbytesleft;
392         const char *inptr;
393         char *inbuf = "works!", *outptr;
394         char outbuf[6];
395
396         if ((myspace = (iconv_allocation_t *)malloc(sizeof(iconv_allocation_t))) == NULL)
397                 return (1);
398         if (iconv_open_into("ASCII", "ASCII", myspace) == -1)
399                 return (1);
400
401         inptr = (const char *)inbuf;
402         outptr = (char *)outbuf;
403         inbytesleft = 6;
404         outbytesleft = 6;
405
406         iconv((iconv_t)myspace, &inptr, &inbytesleft, &outptr, &outbytesleft);
407
408         return ((memcmp(inbuf, outbuf, 6) == 0) ? 0 : 1);
409 }
410
411 static void
412 test(int (tester) (void), const char * label)
413 {
414         int ret;
415
416         if ((ret = tester()))
417                 printf("%s failed (%d)\n", label, ret);
418         else
419                 printf("%s succeeded\n", label);
420 }
421
422 int
423 main(void)
424 {
425         test(ctl_get_translit1, "ctl_get_translit1");
426         test(ctl_get_translit2, "ctl_get_translit2");
427         test(ctl_set_translit1, "ctl_set_translit1");
428         test(ctl_set_translit2, "ctl_set_translit2");
429         test(ctl_get_discard_ilseq1, "ctl_get_discard_ilseq1");
430         test(ctl_get_discard_ilseq2, "ctl_get_discard_ilseq2");
431         test(ctl_set_discard_ilseq1, "ctl_set_discard_ilseq1");
432         test(ctl_set_discard_ilseq2, "ctl_set_discard_ilseq2");
433         test(ctl_trivialp1, "ctl_trivialp1");
434         test(ctl_trivialp2, "ctl_trivialp2");
435         test(ctl_uc_hook, "ctl_uc_hook");
436         test(ctl_wc_hook, "ctl_wc_hook");
437 //      test(ctl_mb_to_uc_fb, "ctl_mb_to_uc_fb");
438         test(gnu_openinto, "gnu_openinto");
439         test(gnu_canonicalize1, "gnu_canonicalize1");
440         test(gnu_canonicalize2, "gnu_canonicalize2");
441         test(gnu_iconvlist, "gnu_iconvlist");
442 }