Merge branch 'master' of ssh://git.indexdata.com/home/git/pub/yaz
[yaz-moved-to-github.git] / test / test_iconv.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2010 Index Data
3  * See the file LICENSE for details.
4  */
5 #if HAVE_CONFIG_H
6 #include <config.h>
7 #endif
8
9 #include <stdlib.h>
10 #include <errno.h>
11 #include <string.h>
12 #include <ctype.h>
13
14 #include <yaz/yaz-util.h>
15 #include <yaz/test.h>
16
17 #define ESC "\x1b"
18
19 static int compare_buffers(char *msg, int no,
20                            int expect_len, const char *expect_buf,
21                            int got_len, const char *got_buf)
22 {
23     if (expect_len == got_len
24         && !memcmp(expect_buf, got_buf, expect_len))
25         return 1;
26     
27     if (0) /* use 1 see how the buffers differ (for debug purposes) */
28     {
29         int i;
30         printf("tsticonv test=%s i=%d failed\n", msg, no);
31         printf("off got exp\n");
32         for (i = 0; i<got_len || i<expect_len; i++)
33         {
34             char got_char[10];
35             char expect_char[10];
36             
37             if (i < got_len)
38                 sprintf(got_char, "%02X", got_buf[i]);
39             else
40                 sprintf(got_char, "?  ");
41             
42             if (i < expect_len)
43                 sprintf(expect_char, "%02X", expect_buf[i]);
44             else
45                 sprintf(expect_char, "?  ");
46             
47             printf("%02d  %s  %s %c\n",
48                    i, got_char, expect_char, got_buf[i] == expect_buf[i] ?
49                    ' ' : '*');
50             
51         }
52     }
53     return 0;
54 }
55
56 static int tst_convert_l(yaz_iconv_t cd, size_t in_len, const char *in_buf,
57                          size_t expect_len, const char *expect_buf)
58 {
59     size_t r;
60     char *inbuf= (char*) in_buf;
61     size_t inbytesleft = in_len > 0 ? in_len : strlen(in_buf);
62     char outbuf0[64];
63     char *outbuf = outbuf0;
64
65     while (inbytesleft)
66     {
67         size_t outbytesleft = outbuf0 + sizeof(outbuf0) - outbuf;
68         if (outbytesleft > 12)
69             outbytesleft = 12;
70         r = yaz_iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
71         if (r == (size_t) (-1))
72         {
73             int e = yaz_iconv_error(cd);
74             if (e != YAZ_ICONV_E2BIG)
75                 return 0;
76         }
77         else
78         {
79             yaz_iconv(cd, 0, 0, &outbuf, &outbytesleft);
80             break;
81         }
82     }
83
84     return compare_buffers("tsticonv 22", 0,
85                            expect_len, expect_buf,
86                            outbuf - outbuf0, outbuf0);
87 }
88
89 static int tst_convert_x(yaz_iconv_t cd, const char *buf, const char *cmpbuf,
90                          int expect_error)
91 {
92     int ret = 1;
93     WRBUF b = wrbuf_alloc();
94     char outbuf[16];
95     size_t inbytesleft = strlen(buf);
96     const char *inp = buf;
97     int rounds = 0;
98     for (rounds = 0; inbytesleft && rounds < (int) sizeof(outbuf); rounds++)
99     {
100         size_t outbytesleft = sizeof(outbuf);
101         char *outp = outbuf;
102         size_t r = yaz_iconv(cd, (char**) &inp,  &inbytesleft,
103                              &outp, &outbytesleft);
104         wrbuf_write(b, outbuf, outp - outbuf);
105         if (r == (size_t) (-1))
106         {
107             int e = yaz_iconv_error(cd);
108             if (e != YAZ_ICONV_E2BIG)
109             {
110                 if (expect_error != -1)
111                     if (e != expect_error)
112                         ret = 0;
113                 break;
114             }
115         }
116         else
117         {
118             size_t outbytesleft = sizeof(outbuf);
119             char *outp = outbuf;
120             r = yaz_iconv(cd, 0, 0, &outp, &outbytesleft);
121             wrbuf_write(b, outbuf, outp - outbuf);
122             if (expect_error != -1)
123                 if (expect_error)
124                     ret = 0;
125             break;
126         }
127     }
128     if (wrbuf_len(b) == strlen(cmpbuf) 
129         && !memcmp(cmpbuf, wrbuf_buf(b), wrbuf_len(b)))
130         ;
131     else
132     {
133         WRBUF w = wrbuf_alloc();
134
135         ret = 0;
136         wrbuf_rewind(w);
137         wrbuf_puts_escaped(w, buf);
138         yaz_log(YLOG_LOG, "input %s", wrbuf_cstr(w));
139
140         wrbuf_rewind(w);
141         wrbuf_write_escaped(w, wrbuf_buf(b), wrbuf_len(b));
142         yaz_log(YLOG_LOG, "got %s", wrbuf_cstr(w));
143         
144         wrbuf_rewind(w);
145         wrbuf_puts_escaped(w, cmpbuf);
146         yaz_log(YLOG_LOG, "exp %s", wrbuf_cstr(w));
147
148         wrbuf_destroy(w);
149     }
150
151     wrbuf_destroy(b);
152     return ret;
153 }
154
155 static int tst_convert(yaz_iconv_t cd, const char *buf, const char *cmpbuf)
156 {
157     return tst_convert_x(cd, buf, cmpbuf, 0);
158 }
159
160 /* some test strings in ISO-8859-1 format */
161 static const char *iso_8859_1_a[] = {
162     "ax" ,
163     "\xd8",
164     "eneb\346r",
165     "\xe5" "\xd8",
166     "\xe5" "\xd8" "b",
167     "\xe5" "\xe5",
168     0 };
169
170 static void tst_marc8_to_ucs4b(void)
171 {
172     yaz_iconv_t cd = yaz_iconv_open("UCS4", "MARC8");
173     YAZ_CHECK(cd);
174     if (!cd)
175         return;
176     
177     YAZ_CHECK(tst_convert_l(
178                   cd,
179                   0,
180                   "\033$1" "\x21\x2B\x3B" /* FF1F */ "\033(B" "o",
181                   8, 
182                   "\x00\x00\xFF\x1F" "\x00\x00\x00o"));
183     YAZ_CHECK(tst_convert_l(
184                   cd,
185                   0,
186                   "\033$1" "\x6F\x77\x29" /* AE0E */
187                   "\x6F\x52\x7C" /* c0F4 */ "\033(B",
188                   8,
189                   "\x00\x00\xAE\x0E" "\x00\x00\xC0\xF4"));
190     YAZ_CHECK(tst_convert_l(
191                   cd,
192                   0,
193                   "\033$1"
194                   "\x21\x50\x6E"  /* UCS 7CFB */
195                   "\x21\x51\x31"  /* UCS 7D71 */
196                   "\x21\x3A\x67"  /* UCS 5B89 */
197                   "\x21\x33\x22"  /* UCS 5168 */
198                   "\x21\x33\x53"  /* UCS 5206 */
199                   "\x21\x44\x2B"  /* UCS 6790 */
200                   "\033(B",
201                   24, 
202                   "\x00\x00\x7C\xFB"
203                   "\x00\x00\x7D\x71"
204                   "\x00\x00\x5B\x89"
205                   "\x00\x00\x51\x68"
206                   "\x00\x00\x52\x06"
207                   "\x00\x00\x67\x90"));
208
209     YAZ_CHECK(tst_convert_l(
210                   cd,
211                   0,
212                   "\xB0\xB2",     /* AYN and oSLASH */
213                   8, 
214                   "\x00\x00\x02\xBB"  "\x00\x00\x00\xF8"));
215     YAZ_CHECK(tst_convert_l(
216                   cd,
217                   0,
218                   "\xF6\x61",     /* a underscore */
219                   8, 
220                   "\x00\x00\x00\x61"  "\x00\x00\x03\x32"));
221
222     YAZ_CHECK(tst_convert_l(
223                   cd,
224                   0,
225                   "\x61\xC2",     /* a, phonorecord mark */
226                   8,
227                   "\x00\x00\x00\x61"  "\x00\x00\x21\x17"));
228
229     /* bug #258 */
230     YAZ_CHECK(tst_convert_l(
231                   cd,
232                   0,
233                   "el" "\xe8" "am\xe8" "an", /* elaman where a is a" */
234                   32,
235                   "\x00\x00\x00" "e"
236                   "\x00\x00\x00" "l"
237                   "\x00\x00\x00" "a"
238                   "\x00\x00\x03\x08"
239                   "\x00\x00\x00" "m"
240                   "\x00\x00\x00" "a"
241                   "\x00\x00\x03\x08"
242                   "\x00\x00\x00" "n"));
243     /* bug #260 */
244     YAZ_CHECK(tst_convert_l(
245                   cd,
246                   0,
247                   "\xe5\xe8\x41",
248                   12, 
249                   "\x00\x00\x00\x41" "\x00\x00\x03\x04" "\x00\x00\x03\x08"));
250     /* bug #416 */
251     YAZ_CHECK(tst_convert_l(
252                   cd,
253                   0,
254                   "\xEB\x74\xEC\x73",
255                   12,
256                   "\x00\x00\x00\x74" "\x00\x00\x03\x61" "\x00\x00\x00\x73"));
257     /* bug #416 */
258     YAZ_CHECK(tst_convert_l(
259                   cd,
260                   0,
261                   "\xFA\x74\xFB\x73",
262                   12, 
263                   "\x00\x00\x00\x74" "\x00\x00\x03\x60" "\x00\x00\x00\x73"));
264
265     yaz_iconv_close(cd);
266 }
267
268 static void tst_ucs4b_to_utf8(void)
269 {
270     yaz_iconv_t cd = yaz_iconv_open("UTF8", "UCS4");
271     YAZ_CHECK(cd);
272     if (!cd)
273         return;
274     YAZ_CHECK(tst_convert_l(
275                   cd,
276                   8,
277                   "\x00\x00\xFF\x1F\x00\x00\x00o",
278                   4,
279                   "\xEF\xBC\x9F\x6F"));
280
281     YAZ_CHECK(tst_convert_l(
282                   cd,
283                   8, 
284                   "\x00\x00\xAE\x0E\x00\x00\xC0\xF4",
285                   6,
286                   "\xEA\xB8\x8E\xEC\x83\xB4"));
287     yaz_iconv_close(cd);
288 }
289
290 static void dconvert(int mandatory, const char *tmpcode)
291 {
292     int i;
293     int ret;
294     yaz_iconv_t cd;
295     for (i = 0; iso_8859_1_a[i]; i++)
296     {
297         size_t r;
298         char *inbuf = (char*) iso_8859_1_a[i];
299         size_t inbytesleft = strlen(inbuf);
300         char outbuf0[24];
301         char outbuf1[10];
302         char *outbuf = outbuf0;
303         size_t outbytesleft = sizeof(outbuf0);
304
305         cd = yaz_iconv_open(tmpcode, "ISO-8859-1");
306         YAZ_CHECK(cd || !mandatory);
307         if (!cd)
308             return;
309         r = yaz_iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
310         YAZ_CHECK(r != (size_t) (-1));
311
312         r = yaz_iconv(cd, 0, 0, &outbuf, &outbytesleft);
313         YAZ_CHECK(r != (size_t) (-1));
314         yaz_iconv_close(cd);
315         if (r == (size_t) (-1))
316             return;
317         
318         cd = yaz_iconv_open("ISO-8859-1", tmpcode);
319         YAZ_CHECK(cd || !mandatory);
320         if (!cd)
321             return;
322         inbuf = outbuf0;
323         inbytesleft = sizeof(outbuf0) - outbytesleft;
324
325         outbuf = outbuf1;
326         outbytesleft = sizeof(outbuf1);
327         r = yaz_iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
328         YAZ_CHECK(r != (size_t) (-1));
329
330         r = yaz_iconv(cd, 0, 0, &outbuf, &outbytesleft);
331         if (r == (size_t)(-1))
332         {
333             fprintf(stderr, "failed\n");
334         }
335         YAZ_CHECK(r != (size_t) (-1));
336
337         if (r != (size_t)(-1)) 
338         {
339             ret = compare_buffers("dconvert", i,
340                                   strlen(iso_8859_1_a[i]), iso_8859_1_a[i],
341                                   sizeof(outbuf1) - outbytesleft, outbuf1);
342             YAZ_CHECK(ret);
343         }
344         yaz_iconv_close(cd);
345     }
346 }
347
348 int utf8_check(unsigned c)
349 {
350     if (sizeof(c) >= 4)
351     {
352         size_t r;
353         char src[4];
354         char dst[4];
355         char utf8buf[6];
356         char *inbuf = src;
357         size_t inbytesleft = 4;
358         char *outbuf = utf8buf;
359         size_t outbytesleft = sizeof(utf8buf);
360         int i;
361         yaz_iconv_t cd = yaz_iconv_open("UTF-8", "UCS4LE");
362         if (!cd)
363             return 0;
364         for (i = 0; i<4; i++)
365             src[i] = c >> (i*8);
366         
367         r = yaz_iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
368         yaz_iconv_close(cd);
369
370         if (r == (size_t)(-1))
371             return 0;
372
373         cd = yaz_iconv_open("UCS4LE", "UTF-8");
374         if (!cd)
375             return 0;
376         inbytesleft = sizeof(utf8buf) - outbytesleft;
377         inbuf = utf8buf;
378
379         outbuf = dst;
380         outbytesleft = 4;
381
382         r = yaz_iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
383         if (r == (size_t)(-1))
384             return 0;
385
386         yaz_iconv_close(cd);
387
388         if (memcmp(src, dst, 4))
389             return 0;
390     }
391     return 1;
392 }
393         
394 static void tst_marc8_to_utf8(void)
395 {
396     yaz_iconv_t cd = yaz_iconv_open("UTF-8", "MARC8");
397
398     YAZ_CHECK(cd);
399     if (!cd)
400         return;
401
402     YAZ_CHECK(tst_convert(cd, "Cours de math", 
403                           "Cours de math"));
404     /* COMBINING ACUTE ACCENT */
405     YAZ_CHECK(tst_convert(cd, "Cours de mathâe", 
406                           "Cours de mathe\xcc\x81"));
407
408     YAZ_CHECK(tst_convert(cd, "\xea" "a", "a\xcc\x8a"));
409     YAZ_CHECK(tst_convert(cd, "a" "\xea" "\x1e", "a" "\x1e\xcc\x8a"));
410     YAZ_CHECK(tst_convert(cd, "a" "\xea" "p", "a" "p\xcc\x8a"));
411
412     YAZ_CHECK(tst_convert_x(cd, "a\xea", "a", YAZ_ICONV_EINVAL));
413     YAZ_CHECK(tst_convert(cd, "p", "\xcc\x8a")); /* note: missing p */
414     yaz_iconv(cd, 0, 0, 0, 0);     /* incomplete. so we have to reset */
415
416     /* bug #2115 */
417     YAZ_CHECK(tst_convert(cd, ESC "(N" ESC ")Qp" ESC "(B", "\xd0\x9f"));
418
419     YAZ_CHECK(tst_convert_x(cd, ESC , "", YAZ_ICONV_EINVAL));
420     YAZ_CHECK(tst_convert_x(cd, ESC "(", "", YAZ_ICONV_EINVAL));
421     YAZ_CHECK(tst_convert_x(cd, ESC "(B", "", 0));
422
423     YAZ_CHECK(tst_convert(cd, ESC "(B" "\x31", "1"));  /* ASCII in G0 */
424     YAZ_CHECK(tst_convert(cd, ESC ")B" "\xB1", "1"));  /* ASCII in G1 */
425
426     yaz_iconv_close(cd);
427 }
428
429 static void tst_marc8s_to_utf8(void)
430 {
431     yaz_iconv_t cd = yaz_iconv_open("UTF-8", "MARC8s");
432
433     YAZ_CHECK(cd);
434     if (!cd)
435         return;
436
437     YAZ_CHECK(tst_convert(cd, "Cours de math", 
438                           "Cours de math"));
439     /* E9: LATIN SMALL LETTER E WITH ACUTE */
440     YAZ_CHECK(tst_convert(cd, "Cours de mathâe", 
441                           "Cours de math\xc3\xa9"));
442
443     yaz_iconv_close(cd);
444 }
445
446
447 static void tst_marc8_to_latin1(void)
448 {
449     yaz_iconv_t cd = yaz_iconv_open("ISO-8859-1", "MARC8");
450
451     YAZ_CHECK(cd);
452     if (!cd)
453         return;
454
455     YAZ_CHECK(tst_convert(cd, "ax", "ax"));
456
457     /* latin capital letter o with stroke */
458     YAZ_CHECK(tst_convert(cd, "\xa2", "\xd8"));
459
460     /* with latin small letter ae */
461     YAZ_CHECK(tst_convert(cd, "eneb\xb5r", "eneb\346r"));
462
463     YAZ_CHECK(tst_convert(cd, "\xea" "a\xa2", "\xe5" "\xd8"));
464
465     YAZ_CHECK(tst_convert(cd, "\xea" "a\xa2" "b", "\xe5" "\xd8" "b"));
466
467     YAZ_CHECK(tst_convert(cd, "\xea" "a"  "\xea" "a", "\xe5" "\xe5"));
468
469     YAZ_CHECK(tst_convert(cd, "Cours de math", 
470                           "Cours de math"));
471     YAZ_CHECK(tst_convert(cd, "Cours de mathâe", 
472                           "Cours de mathé"));
473     YAZ_CHECK(tst_convert(cd, "12345678âe", 
474                           "12345678é"));
475     YAZ_CHECK(tst_convert(cd, "123456789âe", 
476                           "123456789é"));
477     YAZ_CHECK(tst_convert(cd, "1234567890âe", 
478                           "1234567890é"));
479     YAZ_CHECK(tst_convert(cd, "12345678901âe", 
480                           "12345678901é"));
481     YAZ_CHECK(tst_convert(cd, "Cours de mathâem", 
482                           "Cours de mathém"));
483     YAZ_CHECK(tst_convert(cd, "Cours de mathâematiques", 
484                           "Cours de mathématiques"));
485
486     yaz_iconv_close(cd);
487 }
488
489 static void tst_utf8_to_marc8(const char *marc8_type)
490 {
491     yaz_iconv_t cd = yaz_iconv_open(marc8_type, "UTF-8");
492
493     YAZ_CHECK(cd);
494     if (!cd)
495         return;
496
497     YAZ_CHECK(tst_convert(cd, "Cours ", "Cours "));
498
499     /** Pure ASCII. 11 characters (sizeof(outbuf)-1) */
500     YAZ_CHECK(tst_convert(cd, "Cours de mat", "Cours de mat"));
501
502     /** Pure ASCII. 12 characters (sizeof(outbuf)) */
503     YAZ_CHECK(tst_convert(cd, "Cours de math", "Cours de math"));
504
505     /** Pure ASCII. 13 characters (sizeof(outbuf)+1) */
506     YAZ_CHECK(tst_convert(cd, "Cours de math.", "Cours de math."));
507
508     /** UPPERCASE SCANDINAVIAN O */
509     YAZ_CHECK(tst_convert(cd, "S\xc3\x98", "S\xa2"));
510
511     /** ARING */
512     YAZ_CHECK(tst_convert(cd, "A" "\xCC\x8A", "\xEA" "A"));
513
514     /** A MACRON + UMLAUT, DIAERESIS */
515     YAZ_CHECK(tst_convert(cd, "A" "\xCC\x84" "\xCC\x88",
516                           "\xE5\xE8\x41"));
517     
518     /* Ligature spanning two characters */
519     YAZ_CHECK(tst_convert(cd,
520                           "\x74" "\xCD\xA1" "\x73",  /* UTF-8 */
521                           "\xEB\x74\xEC\x73"));      /* MARC-8 */
522
523     /* Double title spanning two characters */
524     YAZ_CHECK(tst_convert(cd,
525                           "\x74" "\xCD\xA0" "\x73",  /* UTF-8 */
526                           "\xFA\x74\xFB\x73"));      /* MARC-8 */
527
528     /** Ideographic question mark (Unicode FF1F) */
529     YAZ_CHECK(tst_convert(cd,
530                           "\xEF\xBC\x9F" "o",        /* UTF-8 */
531                           "\033$1" "\x21\x2B\x3B" "\033(B" "o" ));
532
533
534     /** Ideographic space per ANSI Z39.64 */
535     YAZ_CHECK(tst_convert(cd,
536                           "\xe3\x80\x80" "o",        /* UTF-8 */
537                           "\033$1" "\x21\x23\x21" "\033(B" "o" ));
538
539     /** Superscript 0 . bug #642 */
540     YAZ_CHECK(tst_convert(cd,
541                           "(\xe2\x81\xb0)",        /* UTF-8 */
542                           "(\033p0\x1bs)"));
543     
544     
545     /** bug #1778 */
546     YAZ_CHECK(tst_convert(cd,
547                           /* offset 0x530 in UTF-8 rec marccol4.u8.marc */
548                           "\xE3\x83\xB3" "\xE3\x82\xBF" 
549                           "\xCC\x84" "\xCC\x84" "\xE3\x83\xBC" /* UTF-8 */,
550                           "\x1B\x24\x31" "\x69\x25\x73"
551                           "\x1B\x28\x42" "\xE5\xE5" "\x1B\x24\x31" 
552                           "\x69\x25\x3F"
553                           "\x69\x21\x3C" "\x1B\x28\x42"));
554
555     
556     /** bug #2120 */
557     YAZ_CHECK(tst_convert(cd, 
558                           "\xCE\x94\xCE\xB5\xCF\x84"
559                           "\xCE\xBF\xCF\x81\xCE\xB1"
560                           "\xCE\xBA\xCE\xB7\xCF\x82\x2C",
561
562                           "\x1B\x28\x53\x45\x66\x78\x72\x75"
563                           "\x61\x6D\x6A\x77"
564                           "\x1B\x28\x42\x2C"
565                   ));
566  
567     {
568         char *inbuf0 = "\xe2\x81\xb0";
569         char *inbuf = inbuf0;
570         size_t inbytesleft = strlen(inbuf);
571         char outbuf0[64];
572         char *outbuf = outbuf0;
573         size_t outbytesleft = sizeof(outbuf0)-1;
574         size_t r;
575 #if 0
576         int i;
577 #endif
578         r = yaz_iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
579         YAZ_CHECK(r != (size_t) (-1));
580
581 #if 0
582         *outbuf = '\0';  /* so we know when to stop printing */
583         for (i = 0; outbuf0[i]; i++)
584         {
585             int ch = outbuf0[i] & 0xff;
586             yaz_log(YLOG_LOG, "ch%d %02X %c", i, ch, ch >= ' ' ? ch : '?');
587         }
588 #endif
589
590         r = yaz_iconv(cd, 0, 0, &outbuf, &outbytesleft);
591         YAZ_CHECK(r != (size_t) (-1));
592         *outbuf = '\0';  /* for strcmp test below and printing */
593 #if 0
594         for (i = 0; outbuf0[i]; i++)
595         {
596             int ch = outbuf0[i] & 0xff;
597             yaz_log(YLOG_LOG, "ch%d %02X %c", i, ch, ch >= ' ' ? ch : '?');
598         }
599 #endif
600         YAZ_CHECK(strcmp("\033p0\x1bs", outbuf0) == 0);
601     }
602     yaz_iconv(cd, 0, 0, 0, 0);
603     yaz_iconv_close(cd);
604 }
605
606 static void tst_advance_to_utf8(void)
607 {
608     yaz_iconv_t cd = yaz_iconv_open("utf-8", "advancegreek");
609
610     YAZ_CHECK(cd);
611     if (!cd)
612         return;
613
614     YAZ_CHECK(tst_convert(cd, "Cours ", "Cours "));
615     yaz_iconv_close(cd);
616 }
617
618 static void tst_utf8_to_advance(void)
619 {
620     yaz_iconv_t cd = yaz_iconv_open("advancegreek", "utf-8");
621
622     YAZ_CHECK(cd);
623     if (!cd)
624         return;
625
626     YAZ_CHECK(tst_convert(cd, "Cours ", "Cours "));
627     yaz_iconv_close(cd);
628 }
629
630 static void tst_latin1_to_marc8(void)
631 {
632     yaz_iconv_t cd = yaz_iconv_open("MARC8", "ISO-8859-1");
633
634     YAZ_CHECK(cd);
635     if (!cd)
636         return;
637
638     YAZ_CHECK(tst_convert(cd, "Cours ", "Cours "));
639
640     /** Pure ASCII. 11 characters (sizeof(outbuf)-1) */
641     YAZ_CHECK(tst_convert(cd, "Cours de mat", "Cours de mat"));
642
643     /** Pure ASCII. 12 characters (sizeof(outbuf)) */
644     YAZ_CHECK(tst_convert(cd, "Cours de math", "Cours de math"));
645
646     /** Pure ASCII. 13 characters (sizeof(outbuf)) */
647     YAZ_CHECK(tst_convert(cd, "Cours de math.", "Cours de math."));
648
649     /** D8: UPPERCASE SCANDINAVIAN O */
650     YAZ_CHECK(tst_convert(cd, "S\xd8", "S\xa2"));
651
652     /** E9: LATIN SMALL LETTER E WITH ACUTE */
653     YAZ_CHECK(tst_convert(cd, "Cours de math\xe9", "Cours de mathâe"));
654     YAZ_CHECK(tst_convert(cd, "Cours de math", "Cours de math"
655                   ));
656     YAZ_CHECK(tst_convert(cd, "Cours de mathé", "Cours de mathâe" ));
657     YAZ_CHECK(tst_convert(cd, "12345678é","12345678âe"));
658     YAZ_CHECK(tst_convert(cd, "123456789é", "123456789âe"));
659     YAZ_CHECK(tst_convert(cd, "1234567890é","1234567890âe"));
660     YAZ_CHECK(tst_convert(cd, "12345678901é", "12345678901âe"));
661     YAZ_CHECK(tst_convert(cd, "Cours de mathém", "Cours de mathâem"));
662     YAZ_CHECK(tst_convert(cd, "Cours de mathématiques",
663                           "Cours de mathâematiques"));
664     yaz_iconv_close(cd);
665 }
666
667 static void tst_utf8_codes(void)
668 {
669     YAZ_CHECK(utf8_check(3));
670     YAZ_CHECK(utf8_check(127));
671     YAZ_CHECK(utf8_check(128));
672     YAZ_CHECK(utf8_check(255));
673     YAZ_CHECK(utf8_check(256));
674     YAZ_CHECK(utf8_check(900));
675     YAZ_CHECK(utf8_check(1000));
676     YAZ_CHECK(utf8_check(10000));
677     YAZ_CHECK(utf8_check(100000));
678     YAZ_CHECK(utf8_check(1000000));
679     YAZ_CHECK(utf8_check(10000000));
680     YAZ_CHECK(utf8_check(100000000));
681 }
682
683 static void tst_danmarc_to_latin1(void)
684 {
685     yaz_iconv_t cd = yaz_iconv_open("iso-8859-1", "danmarc");
686
687     YAZ_CHECK(cd);
688     if (!cd)
689         return;
690
691     YAZ_CHECK(tst_convert(cd, "ax", "ax"));
692
693     YAZ_CHECK(tst_convert(cd, "a@@b", "a@b"));
694     YAZ_CHECK(tst_convert(cd, "a@@@@b", "a@@b"));
695     YAZ_CHECK(tst_convert(cd, "@000ab", "\nb"));
696
697     YAZ_CHECK(tst_convert(cd, "@\xe5", "aa"));
698     YAZ_CHECK(tst_convert(cd, "@\xc5.", "Aa."));
699     
700     yaz_iconv_close(cd);
701 }
702
703
704 int main (int argc, char **argv)
705 {
706     YAZ_CHECK_INIT(argc, argv);
707
708     tst_utf8_codes();
709
710     tst_marc8_to_utf8();
711
712     tst_marc8s_to_utf8();
713
714     tst_marc8_to_latin1();
715
716     tst_advance_to_utf8();
717     tst_utf8_to_advance();
718
719     tst_utf8_to_marc8("marc8");
720     tst_utf8_to_marc8("marc8lossy");
721     tst_utf8_to_marc8("marc8lossless");
722
723     tst_danmarc_to_latin1();
724
725     tst_latin1_to_marc8();
726
727     tst_marc8_to_ucs4b();
728     tst_ucs4b_to_utf8();
729
730     dconvert(1, "UTF-8");
731     dconvert(1, "ISO-8859-1");
732     dconvert(1, "UCS4");
733     dconvert(1, "UCS4LE");
734     dconvert(0, "CP865");
735
736     YAZ_CHECK_TERM;
737 }
738 /*
739  * Local variables:
740  * c-basic-offset: 4
741  * c-file-style: "Stroustrup"
742  * indent-tabs-mode: nil
743  * End:
744  * vim: shiftwidth=4 tabstop=8 expandtab
745  */
746