2 * Copyright (C) 1995-2005, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: siconv.c,v 1.15 2005-11-06 01:28:09 adam Exp $
9 * \brief Implements simple ICONV
11 * This implements an interface similar to that of iconv and
12 * is used by YAZ to interface with iconv (if present).
13 * For systems where iconv is not present, this layer
14 * provides a few important conversion: UTF-8, MARC-8, Latin-1.
32 #include <yaz/yaz-util.h>
34 unsigned long yaz_marc8_1_conv (unsigned char *inp, size_t inbytesleft,
35 size_t *no_read, int *combining);
36 unsigned long yaz_marc8_2_conv (unsigned char *inp, size_t inbytesleft,
37 size_t *no_read, int *combining);
38 unsigned long yaz_marc8_3_conv (unsigned char *inp, size_t inbytesleft,
39 size_t *no_read, int *combining);
40 unsigned long yaz_marc8_4_conv (unsigned char *inp, size_t inbytesleft,
41 size_t *no_read, int *combining);
42 unsigned long yaz_marc8_5_conv (unsigned char *inp, size_t inbytesleft,
43 size_t *no_read, int *combining);
44 unsigned long yaz_marc8_6_conv (unsigned char *inp, size_t inbytesleft,
45 size_t *no_read, int *combining);
46 unsigned long yaz_marc8_7_conv (unsigned char *inp, size_t inbytesleft,
47 size_t *no_read, int *combining);
48 unsigned long yaz_marc8_8_conv (unsigned char *inp, size_t inbytesleft,
49 size_t *no_read, int *combining);
50 unsigned long yaz_marc8_9_conv (unsigned char *inp, size_t inbytesleft,
51 size_t *no_read, int *combining);
53 struct yaz_iconv_struct {
56 size_t (*init_handle)(yaz_iconv_t cd, unsigned char *inbuf,
57 size_t inbytesleft, size_t *no_read);
58 unsigned long (*read_handle)(yaz_iconv_t cd, unsigned char *inbuf,
59 size_t inbytesleft, size_t *no_read);
60 size_t (*write_handle)(yaz_iconv_t cd, unsigned long x,
61 char **outbuf, size_t *outbytesleft,
67 unsigned long comb_x[8];
68 size_t comb_no_read[8];
70 unsigned long unget_x;
74 unsigned long compose_char;
77 static unsigned long yaz_read_ISO8859_1 (yaz_iconv_t cd, unsigned char *inp,
78 size_t inbytesleft, size_t *no_read)
80 unsigned long x = inp[0];
85 static size_t yaz_init_UTF8 (yaz_iconv_t cd, unsigned char *inp,
86 size_t inbytesleft, size_t *no_read)
95 cd->my_errno = YAZ_ICONV_EINVAL;
98 if (inp[1] != 0xbb || inp[2] != 0xbf)
100 cd->my_errno = YAZ_ICONV_EILSEQ;
107 static unsigned long yaz_read_UTF8 (yaz_iconv_t cd, unsigned char *inp,
108 size_t inbytesleft, size_t *no_read)
117 else if (inp[0] <= 0xbf || inp[0] >= 0xfe)
120 cd->my_errno = YAZ_ICONV_EILSEQ;
122 else if (inp[0] <= 0xdf && inbytesleft >= 2)
124 x = ((inp[0] & 0x1f) << 6) | (inp[1] & 0x3f);
130 cd->my_errno = YAZ_ICONV_EILSEQ;
133 else if (inp[0] <= 0xef && inbytesleft >= 3)
135 x = ((inp[0] & 0x0f) << 12) | ((inp[1] & 0x3f) << 6) |
142 cd->my_errno = YAZ_ICONV_EILSEQ;
145 else if (inp[0] <= 0xf7 && inbytesleft >= 4)
147 x = ((inp[0] & 0x07) << 18) | ((inp[1] & 0x3f) << 12) |
148 ((inp[2] & 0x3f) << 6) | (inp[3] & 0x3f);
154 cd->my_errno = YAZ_ICONV_EILSEQ;
157 else if (inp[0] <= 0xfb && inbytesleft >= 5)
159 x = ((inp[0] & 0x03) << 24) | ((inp[1] & 0x3f) << 18) |
160 ((inp[2] & 0x3f) << 12) | ((inp[3] & 0x3f) << 6) |
167 cd->my_errno = YAZ_ICONV_EILSEQ;
170 else if (inp[0] <= 0xfd && inbytesleft >= 6)
172 x = ((inp[0] & 0x01) << 30) | ((inp[1] & 0x3f) << 24) |
173 ((inp[2] & 0x3f) << 18) | ((inp[3] & 0x3f) << 12) |
174 ((inp[4] & 0x3f) << 6) | (inp[5] & 0x3f);
180 cd->my_errno = YAZ_ICONV_EILSEQ;
186 cd->my_errno = YAZ_ICONV_EINVAL;
191 static unsigned long yaz_read_UCS4 (yaz_iconv_t cd, unsigned char *inp,
192 size_t inbytesleft, size_t *no_read)
198 cd->my_errno = YAZ_ICONV_EINVAL; /* incomplete input */
203 x = (inp[0]<<24) | (inp[1]<<16) | (inp[2]<<8) | inp[3];
209 static unsigned long yaz_read_UCS4LE (yaz_iconv_t cd, unsigned char *inp,
210 size_t inbytesleft, size_t *no_read)
216 cd->my_errno = YAZ_ICONV_EINVAL; /* incomplete input */
221 x = (inp[3]<<24) | (inp[2]<<16) | (inp[1]<<8) | inp[0];
228 static unsigned long yaz_read_wchar_t (yaz_iconv_t cd, unsigned char *inp,
229 size_t inbytesleft, size_t *no_read)
233 if (inbytesleft < sizeof(wchar_t))
235 cd->my_errno = YAZ_ICONV_EINVAL; /* incomplete input */
241 memcpy (&wch, inp, sizeof(wch));
243 *no_read = sizeof(wch);
250 static unsigned long yaz_read_marc8_comb (yaz_iconv_t cd, unsigned char *inp,
251 size_t inbytesleft, size_t *no_read,
254 static unsigned long yaz_read_marc8 (yaz_iconv_t cd, unsigned char *inp,
255 size_t inbytesleft, size_t *no_read)
258 if (cd->comb_offset < cd->comb_size)
260 *no_read = cd->comb_no_read[cd->comb_offset];
261 x = cd->comb_x[cd->comb_offset];
263 /* special case for double-diacritic combining characters,
264 INVERTED BREVE and DOUBLE TILDE.
265 We'll increment the no_read counter by 1, since we want to skip over
266 the processing of the closing ligature character
269 if (x == 0x0361 || x == 0x0360)
277 for (cd->comb_size = 0; cd->comb_size < 8; cd->comb_size++)
280 x = yaz_read_marc8_comb(cd, inp, inbytesleft, no_read, &comb);
283 cd->comb_x[cd->comb_size] = x;
284 cd->comb_no_read[cd->comb_size] = *no_read;
286 inbytesleft = inbytesleft - *no_read;
291 static unsigned long yaz_read_marc8_comb (yaz_iconv_t cd, unsigned char *inp,
292 size_t inbytesleft, size_t *no_read,
296 while(inbytesleft >= 1 && inp[0] == 27)
298 size_t inbytesleft0 = inbytesleft;
301 while(inbytesleft > 0 && strchr("(,$!", *inp))
306 if (inbytesleft <= 0)
309 cd->my_errno = YAZ_ICONV_EINVAL;
312 cd->marc8_esc_mode = *inp++;
314 (*no_read) += inbytesleft0 - inbytesleft;
316 if (inbytesleft <= 0)
321 size_t no_read_sub = 0;
324 switch(cd->marc8_esc_mode)
326 case 'B': /* Basic ASCII */
327 case 'E': /* ANSEL */
328 case 's': /* ASCII */
329 x = yaz_marc8_1_conv(inp, inbytesleft, &no_read_sub, comb);
331 case 'g': /* Greek */
332 x = yaz_marc8_2_conv(inp, inbytesleft, &no_read_sub, comb);
334 case 'b': /* Subscripts */
335 x = yaz_marc8_3_conv(inp, inbytesleft, &no_read_sub, comb);
337 case 'p': /* Superscripts */
338 x = yaz_marc8_4_conv(inp, inbytesleft, &no_read_sub, comb);
340 case '2': /* Basic Hebrew */
341 x = yaz_marc8_5_conv(inp, inbytesleft, &no_read_sub, comb);
343 case 'N': /* Basic Cyrillic */
344 case 'Q': /* Extended Cyrillic */
345 x = yaz_marc8_6_conv(inp, inbytesleft, &no_read_sub, comb);
347 case '3': /* Basic Arabic */
348 case '4': /* Extended Arabic */
349 x = yaz_marc8_7_conv(inp, inbytesleft, &no_read_sub, comb);
351 case 'S': /* Greek */
352 x = yaz_marc8_8_conv(inp, inbytesleft, &no_read_sub, comb);
354 case '1': /* Chinese, Japanese, Korean (EACC) */
355 x = yaz_marc8_9_conv(inp, inbytesleft, &no_read_sub, comb);
359 cd->my_errno = YAZ_ICONV_EILSEQ;
362 *no_read += no_read_sub;
367 static size_t yaz_write_UTF8 (yaz_iconv_t cd, unsigned long x,
368 char **outbuf, size_t *outbytesleft,
371 unsigned char *outp = (unsigned char *) *outbuf;
372 if (x <= 0x7f && *outbytesleft >= 1)
374 *outp++ = (unsigned char) x;
377 else if (x <= 0x7ff && *outbytesleft >= 2)
379 *outp++ = (unsigned char) ((x >> 6) | 0xc0);
380 *outp++ = (unsigned char) ((x & 0x3f) | 0x80);
381 (*outbytesleft) -= 2;
383 else if (x <= 0xffff && *outbytesleft >= 3)
385 *outp++ = (unsigned char) ((x >> 12) | 0xe0);
386 *outp++ = (unsigned char) (((x >> 6) & 0x3f) | 0x80);
387 *outp++ = (unsigned char) ((x & 0x3f) | 0x80);
388 (*outbytesleft) -= 3;
390 else if (x <= 0x1fffff && *outbytesleft >= 4)
392 *outp++ = (unsigned char) ((x >> 18) | 0xf0);
393 *outp++ = (unsigned char) (((x >> 12) & 0x3f) | 0x80);
394 *outp++ = (unsigned char) (((x >> 6) & 0x3f) | 0x80);
395 *outp++ = (unsigned char) ((x & 0x3f) | 0x80);
396 (*outbytesleft) -= 4;
398 else if (x <= 0x3ffffff && *outbytesleft >= 5)
400 *outp++ = (unsigned char) ((x >> 24) | 0xf8);
401 *outp++ = (unsigned char) (((x >> 18) & 0x3f) | 0x80);
402 *outp++ = (unsigned char) (((x >> 12) & 0x3f) | 0x80);
403 *outp++ = (unsigned char) (((x >> 6) & 0x3f) | 0x80);
404 *outp++ = (unsigned char) ((x & 0x3f) | 0x80);
405 (*outbytesleft) -= 5;
407 else if (*outbytesleft >= 6)
409 *outp++ = (unsigned char) ((x >> 30) | 0xfc);
410 *outp++ = (unsigned char) (((x >> 24) & 0x3f) | 0x80);
411 *outp++ = (unsigned char) (((x >> 18) & 0x3f) | 0x80);
412 *outp++ = (unsigned char) (((x >> 12) & 0x3f) | 0x80);
413 *outp++ = (unsigned char) (((x >> 6) & 0x3f) | 0x80);
414 *outp++ = (unsigned char) ((x & 0x3f) | 0x80);
415 (*outbytesleft) -= 6;
419 cd->my_errno = YAZ_ICONV_E2BIG; /* not room for output */
422 *outbuf = (char *) outp;
427 static size_t yaz_write_ISO8859_1 (yaz_iconv_t cd, unsigned long x,
428 char **outbuf, size_t *outbytesleft,
431 /* list of two char unicode sequence that, when combined, are
432 equivalent to single unicode chars that can be represented in
434 Regular iconv on Linux at least does not seem to convert these,
435 but since MARC-8 to UTF-8 generates these composed sequence
436 we get a better chance of a successful MARC-8 -> ISO-8859-1
439 unsigned long x1, x2;
442 { 'A', 0x0300, 0xc0}, /* LATIN CAPITAL LETTER A WITH GRAVE */
443 { 'A', 0x0301, 0xc1}, /* LATIN CAPITAL LETTER A WITH ACUTE */
444 { 'A', 0x0302, 0xc2}, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
445 { 'A', 0x0303, 0xc3}, /* LATIN CAPITAL LETTER A WITH TILDE */
446 { 'A', 0x0308, 0xc4}, /* LATIN CAPITAL LETTER A WITH DIAERESIS */
447 { 'A', 0x030a, 0xc5}, /* LATIN CAPITAL LETTER A WITH RING ABOVE */
448 /* no need for 0xc6 LATIN CAPITAL LETTER AE */
449 { 'C', 0x0327, 0xc7}, /* LATIN CAPITAL LETTER C WITH CEDILLA */
450 { 'E', 0x0300, 0xc8}, /* LATIN CAPITAL LETTER E WITH GRAVE */
451 { 'E', 0x0301, 0xc9}, /* LATIN CAPITAL LETTER E WITH ACUTE */
452 { 'E', 0x0302, 0xca}, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
453 { 'E', 0x0308, 0xcb}, /* LATIN CAPITAL LETTER E WITH DIAERESIS */
454 { 'I', 0x0300, 0xcc}, /* LATIN CAPITAL LETTER I WITH GRAVE */
455 { 'I', 0x0301, 0xcd}, /* LATIN CAPITAL LETTER I WITH ACUTE */
456 { 'I', 0x0302, 0xce}, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
457 { 'I', 0x0308, 0xcf}, /* LATIN CAPITAL LETTER I WITH DIAERESIS */
458 { 'N', 0x0303, 0xd1}, /* LATIN CAPITAL LETTER N WITH TILDE */
459 { 'O', 0x0300, 0xd2}, /* LATIN CAPITAL LETTER O WITH GRAVE */
460 { 'O', 0x0301, 0xd3}, /* LATIN CAPITAL LETTER O WITH ACUTE */
461 { 'O', 0x0302, 0xd4}, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
462 { 'O', 0x0303, 0xd5}, /* LATIN CAPITAL LETTER O WITH TILDE */
463 { 'O', 0x0308, 0xd6}, /* LATIN CAPITAL LETTER O WITH DIAERESIS */
464 /* omitted: 0xd7 MULTIPLICATION SIGN */
465 /* omitted: 0xd8 LATIN CAPITAL LETTER O WITH STROKE */
466 { 'U', 0x0300, 0xd9}, /* LATIN CAPITAL LETTER U WITH GRAVE */
467 { 'U', 0x0301, 0xda}, /* LATIN CAPITAL LETTER U WITH ACUTE */
468 { 'U', 0x0302, 0xdb}, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
469 { 'U', 0x0308, 0xdc}, /* LATIN CAPITAL LETTER U WITH DIAERESIS */
470 { 'Y', 0x0301, 0xdd}, /* LATIN CAPITAL LETTER Y WITH ACUTE */
471 /* omitted: 0xde LATIN CAPITAL LETTER THORN */
472 /* omitted: 0xdf LATIN SMALL LETTER SHARP S */
473 { 'a', 0x0300, 0xe0}, /* LATIN SMALL LETTER A WITH GRAVE */
474 { 'a', 0x0301, 0xe1}, /* LATIN SMALL LETTER A WITH ACUTE */
475 { 'a', 0x0302, 0xe2}, /* LATIN SMALL LETTER A WITH CIRCUMFLEX */
476 { 'a', 0x0303, 0xe3}, /* LATIN SMALL LETTER A WITH TILDE */
477 { 'a', 0x0308, 0xe4}, /* LATIN SMALL LETTER A WITH DIAERESIS */
478 { 'a', 0x030a, 0xe5}, /* LATIN SMALL LETTER A WITH RING ABOVE */
479 /* omitted: 0xe6 LATIN SMALL LETTER AE */
480 { 'c', 0x0327, 0xe7}, /* LATIN SMALL LETTER C WITH CEDILLA */
481 { 'e', 0x0300, 0xe8}, /* LATIN SMALL LETTER E WITH GRAVE */
482 { 'e', 0x0301, 0xe9}, /* LATIN SMALL LETTER E WITH ACUTE */
483 { 'e', 0x0302, 0xea}, /* LATIN SMALL LETTER E WITH CIRCUMFLEX */
484 { 'e', 0x0308, 0xeb}, /* LATIN SMALL LETTER E WITH DIAERESIS */
485 { 'i', 0x0300, 0xec}, /* LATIN SMALL LETTER I WITH GRAVE */
486 { 'i', 0x0301, 0xed}, /* LATIN SMALL LETTER I WITH ACUTE */
487 { 'i', 0x0302, 0xee}, /* LATIN SMALL LETTER I WITH CIRCUMFLEX */
488 { 'i', 0x0308, 0xef}, /* LATIN SMALL LETTER I WITH DIAERESIS */
489 /* omitted: 0xf0 LATIN SMALL LETTER ETH */
490 { 'n', 0x0303, 0xf1}, /* LATIN SMALL LETTER N WITH TILDE */
491 { 'o', 0x0300, 0xf2}, /* LATIN SMALL LETTER O WITH GRAVE */
492 { 'o', 0x0301, 0xf3}, /* LATIN SMALL LETTER O WITH ACUTE */
493 { 'o', 0x0302, 0xf4}, /* LATIN SMALL LETTER O WITH CIRCUMFLEX */
494 { 'o', 0x0303, 0xf5}, /* LATIN SMALL LETTER O WITH TILDE */
495 { 'o', 0x0308, 0xf6}, /* LATIN SMALL LETTER O WITH DIAERESIS */
496 /* omitted: 0xf7 DIVISION SIGN */
497 /* omitted: 0xf8 LATIN SMALL LETTER O WITH STROKE */
498 { 'u', 0x0300, 0xf9}, /* LATIN SMALL LETTER U WITH GRAVE */
499 { 'u', 0x0301, 0xfa}, /* LATIN SMALL LETTER U WITH ACUTE */
500 { 'u', 0x0302, 0xfb}, /* LATIN SMALL LETTER U WITH CIRCUMFLEX */
501 { 'u', 0x0308, 0xfc}, /* LATIN SMALL LETTER U WITH DIAERESIS */
502 { 'y', 0x0301, 0xfd}, /* LATIN SMALL LETTER Y WITH ACUTE */
503 /* omitted: 0xfe LATIN SMALL LETTER THORN */
504 { 'y', 0x0308, 0xff}, /* LATIN SMALL LETTER Y WITH DIAERESIS */
508 unsigned char *outp = (unsigned char *) *outbuf;
510 if (!last && x > 32 && x < 127 && cd->compose_char == 0)
512 cd->compose_char = x;
515 else if (cd->compose_char)
518 for (i = 0; comb[i].x1; i++)
519 if (cd->compose_char == comb[i].x1 && x == comb[i].x2)
526 if (*outbytesleft >= 1)
528 *outp++ = (unsigned char) cd->compose_char;
530 *outbuf = (char *) outp;
531 if (!last && x > 32 && x < 127)
533 cd->compose_char = x;
539 cd->my_errno = YAZ_ICONV_E2BIG;
543 /* compose_char and old x combined to one new char: x */
544 cd->compose_char = 0;
546 if (x > 255 || x < 1)
548 cd->my_errno = YAZ_ICONV_EILSEQ;
551 else if (*outbytesleft >= 1)
553 *outp++ = (unsigned char) x;
558 cd->my_errno = YAZ_ICONV_E2BIG;
561 *outbuf = (char *) outp;
566 static size_t yaz_write_UCS4 (yaz_iconv_t cd, unsigned long x,
567 char **outbuf, size_t *outbytesleft,
570 unsigned char *outp = (unsigned char *) *outbuf;
571 if (*outbytesleft >= 4)
573 *outp++ = (unsigned char) (x>>24);
574 *outp++ = (unsigned char) (x>>16);
575 *outp++ = (unsigned char) (x>>8);
576 *outp++ = (unsigned char) x;
577 (*outbytesleft) -= 4;
581 cd->my_errno = YAZ_ICONV_E2BIG;
584 *outbuf = (char *) outp;
588 static size_t yaz_write_UCS4LE (yaz_iconv_t cd, unsigned long x,
589 char **outbuf, size_t *outbytesleft,
592 unsigned char *outp = (unsigned char *) *outbuf;
593 if (*outbytesleft >= 4)
595 *outp++ = (unsigned char) x;
596 *outp++ = (unsigned char) (x>>8);
597 *outp++ = (unsigned char) (x>>16);
598 *outp++ = (unsigned char) (x>>24);
599 (*outbytesleft) -= 4;
603 cd->my_errno = YAZ_ICONV_E2BIG;
606 *outbuf = (char *) outp;
611 static size_t yaz_write_wchar_t (yaz_iconv_t cd, unsigned long x,
612 char **outbuf, size_t *outbytesleft,
615 unsigned char *outp = (unsigned char *) *outbuf;
617 if (*outbytesleft >= sizeof(wchar_t))
620 memcpy(outp, &wch, sizeof(wch));
622 (*outbytesleft) -= sizeof(wch);
626 cd->my_errno = YAZ_ICONV_E2BIG;
629 *outbuf = (char *) outp;
634 int yaz_iconv_isbuiltin(yaz_iconv_t cd)
636 return cd->read_handle && cd->write_handle;
639 yaz_iconv_t yaz_iconv_open (const char *tocode, const char *fromcode)
641 yaz_iconv_t cd = (yaz_iconv_t) xmalloc (sizeof(*cd));
643 cd->write_handle = 0;
646 cd->my_errno = YAZ_ICONV_UNKNOWN;
647 cd->marc8_esc_mode = 'B';
648 cd->comb_offset = cd->comb_size = 0;
649 cd->compose_char = 0;
651 /* a useful hack: if fromcode has leading @,
652 the library not use YAZ's own conversions .. */
653 if (fromcode[0] == '@')
657 if (!yaz_matchstr(fromcode, "UTF8"))
659 cd->read_handle = yaz_read_UTF8;
660 cd->init_handle = yaz_init_UTF8;
662 else if (!yaz_matchstr(fromcode, "ISO88591"))
663 cd->read_handle = yaz_read_ISO8859_1;
664 else if (!yaz_matchstr(fromcode, "UCS4"))
665 cd->read_handle = yaz_read_UCS4;
666 else if (!yaz_matchstr(fromcode, "UCS4LE"))
667 cd->read_handle = yaz_read_UCS4LE;
668 else if (!yaz_matchstr(fromcode, "MARC8"))
669 cd->read_handle = yaz_read_marc8;
671 else if (!yaz_matchstr(fromcode, "WCHAR_T"))
672 cd->read_handle = yaz_read_wchar_t;
675 if (!yaz_matchstr(tocode, "UTF8"))
676 cd->write_handle = yaz_write_UTF8;
677 else if (!yaz_matchstr(tocode, "ISO88591"))
678 cd->write_handle = yaz_write_ISO8859_1;
679 else if (!yaz_matchstr (tocode, "UCS4"))
680 cd->write_handle = yaz_write_UCS4;
681 else if (!yaz_matchstr(tocode, "UCS4LE"))
682 cd->write_handle = yaz_write_UCS4LE;
684 else if (!yaz_matchstr(tocode, "WCHAR_T"))
685 cd->write_handle = yaz_write_wchar_t;
690 if (!cd->read_handle || !cd->write_handle)
692 cd->iconv_cd = iconv_open (tocode, fromcode);
693 if (cd->iconv_cd == (iconv_t) (-1))
700 if (!cd->read_handle || !cd->write_handle)
710 size_t yaz_iconv(yaz_iconv_t cd, char **inbuf, size_t *inbytesleft,
711 char **outbuf, size_t *outbytesleft)
719 iconv(cd->iconv_cd, inbuf, inbytesleft, outbuf, outbytesleft);
720 if (r == (size_t)(-1))
725 cd->my_errno = YAZ_ICONV_E2BIG;
728 cd->my_errno = YAZ_ICONV_EINVAL;
731 cd->my_errno = YAZ_ICONV_EILSEQ;
734 cd->my_errno = YAZ_ICONV_UNKNOWN;
740 if (inbuf == 0 || *inbuf == 0)
743 cd->my_errno = YAZ_ICONV_UNKNOWN;
753 size_t r = (cd->init_handle)(cd, (unsigned char *) *inbuf,
754 *inbytesleft, &no_read);
757 if (cd->my_errno == YAZ_ICONV_EINVAL)
762 *inbytesleft -= no_read;
774 if (*inbytesleft == 0)
781 x = (cd->read_handle)(cd, (unsigned char *) *inbuf, *inbytesleft,
792 no_read = cd->no_read_x;
796 r = (cd->write_handle)(cd, x, outbuf, outbytesleft,
797 (*inbytesleft - no_read) == 0 ? 1 : 0);
800 /* unable to write it. save it because read_handle cannot
803 cd->no_read_x = no_read;
808 *inbytesleft -= no_read;
814 int yaz_iconv_error (yaz_iconv_t cd)
819 int yaz_iconv_close (yaz_iconv_t cd)
823 iconv_close (cd->iconv_cd);
833 * indent-tabs-mode: nil
835 * vim: shiftwidth=4 tabstop=8 expandtab