2 * Copyright (C) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/endian.h>
31 #include <sys/types.h>
41 static bool uc_hook = false;
42 static bool wc_hook = false;
43 static bool mb_uc_fb = false;
45 void unicode_hook(unsigned int mbr, void *data);
46 void wchar_hook(wchar_t wc, void *data);
48 void mb_to_uc_fb(const char *, size_t,
49 void (*write_replacement) (const unsigned int *, size_t, void *),
53 ctl_get_translit1(void)
58 cd = iconv_open("ASCII//TRANSLIT", "UTF-8");
59 if (cd == (iconv_t)-1)
61 if (iconvctl(cd, ICONV_GET_TRANSLITERATE, &arg) == 0)
62 ret = (arg == 1) ? 0 : -1;
65 if (iconv_close(cd) == -1)
71 ctl_get_translit2(void)
76 cd = iconv_open("ASCII", "UTF-8");
77 if (cd == (iconv_t)-1)
79 if (iconvctl(cd, ICONV_GET_TRANSLITERATE, &arg) == 0)
80 ret = (arg == 0) ? 0 : -1;
83 if (iconv_close(cd) == -1)
89 ctl_set_translit1(void)
94 cd = iconv_open("ASCII", "UTF-8");
95 if (cd == (iconv_t)-1)
97 ret = iconvctl(cd, ICONV_SET_TRANSLITERATE, &arg) == 0 ? 0 : -1;
98 if (iconv_close(cd) == -1)
104 ctl_set_translit2(void)
109 cd = iconv_open("ASCII//TRANSLIT", "UTF-8");
110 if (cd == (iconv_t)-1)
112 ret = iconvctl(cd, ICONV_SET_TRANSLITERATE, &arg) == 0 ? 0 : -1;
113 if (iconv_close(cd) == -1)
119 ctl_get_discard_ilseq1(void)
124 cd = iconv_open("ASCII", "UTF-8");
125 if (cd == (iconv_t)-1)
127 if (iconvctl(cd, ICONV_GET_DISCARD_ILSEQ, &arg) == 0)
128 ret = arg == 0 ? 0 : -1;
131 if (iconv_close(cd) == -1)
137 ctl_get_discard_ilseq2(void)
142 cd = iconv_open("ASCII//IGNORE", "UTF-8");
143 if (cd == (iconv_t)-1)
145 if (iconvctl(cd, ICONV_GET_DISCARD_ILSEQ, &arg) == 0)
146 ret = arg == 1 ? 0 : -1;
149 if (iconv_close(cd) == -1)
155 ctl_set_discard_ilseq1(void)
160 cd = iconv_open("ASCII", "UTF-8");
161 if (cd == (iconv_t)-1)
163 ret = iconvctl(cd, ICONV_SET_DISCARD_ILSEQ, &arg) == 0 ? 0 : -1;
164 if (iconv_close(cd) == -1)
170 ctl_set_discard_ilseq2(void)
175 cd = iconv_open("ASCII//IGNORE", "UTF-8");
176 if (cd == (iconv_t)-1)
178 ret = iconvctl(cd, ICONV_SET_DISCARD_ILSEQ, &arg) == 0 ? 0 : -1;
179 if (iconv_close(cd) == -1)
190 cd = iconv_open("latin2", "latin2");
191 if (cd == (iconv_t)-1)
193 if (iconvctl(cd, ICONV_TRIVIALP, &arg) == 0) {
194 ret = (arg == 1) ? 0 : -1;
197 if (iconv_close(cd) == -1)
208 cd = iconv_open("ASCII", "KOI8-R");
209 if (cd == (iconv_t)-1)
211 if (iconvctl(cd, ICONV_TRIVIALP, &arg) == 0) {
212 ret = (arg == 0) ? 0 : -1;
215 if (iconv_close(cd) == -1)
221 unicode_hook(unsigned int mbr, void *data)
225 printf("Unicode hook: %u\n", mbr);
231 wchar_hook(wchar_t wc, void *data)
235 printf("Wchar hook: %ull\n", wc);
243 struct iconv_hooks hooks;
245 size_t inbytesleft = 15, outbytesleft = 40;
247 const char *s = "Hello World!";
252 hooks.uc_hook = unicode_hook;
253 hooks.wc_hook = NULL;
258 cd = iconv_open("UTF-8", "ASCII");
259 if (cd == (iconv_t)-1)
261 if (iconvctl(cd, ICONV_SET_HOOKS, (void *)&hooks) != 0)
263 if (iconv(cd, inptr, &inbytesleft, outptr, &outbytesleft) == (size_t)-1)
265 if (iconv_close(cd) == -1)
267 return (uc_hook ? 0 : 1);
273 struct iconv_hooks hooks;
275 size_t inbytesleft, outbytesleft = 40;
277 const char *s = "Hello World!";
282 hooks.wc_hook = wchar_hook;
283 hooks.uc_hook = NULL;
287 inbytesleft = sizeof(s);
289 cd = iconv_open("SHIFT_JIS", "ASCII");
290 if (cd == (iconv_t)-1)
292 if (iconvctl(cd, ICONV_SET_HOOKS, (void *)&hooks) != 0)
294 if (iconv(cd, inptr, &inbytesleft, outptr, &outbytesleft) == (size_t)-1)
296 if (iconv_close(cd) == -1)
298 return (wc_hook ? 0 : 1);
304 gnu_canonicalize1(void)
307 return (strcmp(iconv_canonicalize("latin2"), "ISO-8859-2"));
311 gnu_canonicalize2(void)
314 return (!strcmp(iconv_canonicalize("ASCII"), iconv_canonicalize("latin2")));
319 iconvlist_cb(unsigned int count, const char * const *names, void *data)
322 return (*(int *)data = ((names == NULL) && (count > 0)) ? -1 : 0);
330 iconvlist(iconvlist_cb, (void *)&i);
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)
339 unsigned int c = 0x3F;
342 write_replacement((const unsigned int *)&c, 1, NULL);
346 ctl_mb_to_uc_fb(void)
348 struct iconv_fallbacks fb;
350 size_t inbytesleft, outbytesleft;
351 uint16_t inbuf[1] = { 0xF187 };
352 uint8_t outbuf[4] = { 0x00, 0x00, 0x00, 0x00 };
357 if ((cd = iconv_open("UTF-32", "UTF-8")) == (iconv_t)-1)
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;
366 if (iconvctl(cd, ICONV_SET_FALLBACKS, (void *)&fb) != 0)
369 inptr = (const char *)inbuf;
370 outptr = (char *)outbuf;
375 ret = iconv(cd, &inptr, &inbytesleft, &outptr, &outbytesleft);
378 printf("mb_uc fallback: %c\n", outbuf[0]);
381 if (mb_uc_fb && (outbuf[0] == 0x3F))
390 iconv_allocation_t *myspace;
391 size_t inbytesleft, outbytesleft;
393 char *inbuf = "works!", *outptr;
396 if ((myspace = (iconv_allocation_t *)malloc(sizeof(iconv_allocation_t))) == NULL)
398 if (iconv_open_into("ASCII", "ASCII", myspace) == -1)
401 inptr = (const char *)inbuf;
402 outptr = (char *)outbuf;
406 iconv((iconv_t)myspace, &inptr, &inbytesleft, &outptr, &outbytesleft);
408 return ((memcmp(inbuf, outbuf, 6) == 0) ? 0 : 1);
412 test(int (tester) (void), const char * label)
416 if ((ret = tester()))
417 printf("%s failed (%d)\n", label, ret);
419 printf("%s succeeded\n", label);
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");