/*
- * Copyright (c) 1997-2003, Index Data
+ * Copyright (c) 1997-2004, Index Data
* See the file LICENSE for details.
*
- * $Id: siconv.c,v 1.1 2003-10-27 12:21:35 adam Exp $
+ * $Id: siconv.c,v 1.5 2004-03-16 13:12:43 adam Exp $
*/
/* mini iconv and wrapper for system iconv library (if present) */
#include <yaz/yaz-util.h>
unsigned long yaz_marc8_conv (unsigned char *inp, size_t inbytesleft,
- size_t *no_read);
+ size_t *no_read);
+unsigned long yaz_marc8_2_conv (unsigned char *inp, size_t inbytesleft,
+ size_t *no_read);
+unsigned long yaz_marc8_3_conv (unsigned char *inp, size_t inbytesleft,
+ size_t *no_read);
+unsigned long yaz_marc8_4_conv (unsigned char *inp, size_t inbytesleft,
+ size_t *no_read);
+unsigned long yaz_marc8_5_conv (unsigned char *inp, size_t inbytesleft,
+ size_t *no_read);
+unsigned long yaz_marc8_6_conv (unsigned char *inp, size_t inbytesleft,
+ size_t *no_read);
+unsigned long yaz_marc8_7_conv (unsigned char *inp, size_t inbytesleft,
+ size_t *no_read);
+unsigned long yaz_marc8_8_conv (unsigned char *inp, size_t inbytesleft,
+ size_t *no_read);
+unsigned long yaz_marc8_9_conv (unsigned char *inp, size_t inbytesleft,
+ size_t *no_read);
struct yaz_iconv_struct {
int my_errno;
size_t inbytesleft, size_t *no_read);
size_t (*write_handle)(yaz_iconv_t cd, unsigned long x,
char **outbuf, size_t *outbytesleft);
+ int marc8_esc_mode;
#if HAVE_ICONV_H
iconv_t iconv_cd;
#endif
static unsigned long yaz_read_marc8 (yaz_iconv_t cd, unsigned char *inp,
size_t inbytesleft, size_t *no_read)
{
- return yaz_marc8_conv(inp, inbytesleft, no_read);
+ *no_read = 0;
+ while(inbytesleft >= 1 && inp[0] == 27)
+ {
+ size_t inbytesleft0 = inbytesleft;
+ inp++;
+ inbytesleft--;
+ while(inbytesleft > 0 && strchr("(,$!", *inp))
+ {
+ inbytesleft--;
+ inp++;
+ }
+ if (inbytesleft <= 0)
+ {
+ *no_read = 0;
+ cd->my_errno = YAZ_ICONV_EINVAL;
+ return 0;
+ }
+ cd->marc8_esc_mode = *inp++;
+ inbytesleft--;
+ (*no_read) += inbytesleft0 - inbytesleft;
+ }
+ if (inbytesleft <= 0)
+ return 0;
+ else
+ {
+ unsigned long x;
+ size_t no_read_sub = 0;
+
+ switch(cd->marc8_esc_mode)
+ {
+ case 'B': /* Basic ASCII */
+ case 'E': /* ANSEL */
+ case 's': /* ASCII */
+ x = yaz_marc8_conv(inp, inbytesleft, &no_read_sub);
+ break;
+ case 'g': /* Greek */
+ x = yaz_marc8_2_conv(inp, inbytesleft, &no_read_sub);
+ break;
+ case 'b': /* Subscripts */
+ x = yaz_marc8_3_conv(inp, inbytesleft, &no_read_sub);
+ break;
+ case 'p': /* Superscripts */
+ x = yaz_marc8_4_conv(inp, inbytesleft, &no_read_sub);
+ break;
+ case '2': /* Basic Hebrew */
+ x = yaz_marc8_5_conv(inp, inbytesleft, &no_read_sub);
+ break;
+ case 'N': /* Basic Cyrillic */
+ case 'Q': /* Extended Cyrillic */
+ x = yaz_marc8_6_conv(inp, inbytesleft, &no_read_sub);
+ break;
+ case '3': /* Basic Arabic */
+ case '4': /* Extended Arabic */
+ x = yaz_marc8_7_conv(inp, inbytesleft, &no_read_sub);
+ break;
+ case 'S': /* Greek */
+ x = yaz_marc8_8_conv(inp, inbytesleft, &no_read_sub);
+ break;
+ case '1': /* Chinese, Japanese, Korean (EACC) */
+ x = yaz_marc8_9_conv(inp, inbytesleft, &no_read_sub);
+ break;
+ default:
+ *no_read = 0;
+ cd->my_errno = YAZ_ICONV_EILSEQ;
+ return 0;
+ }
+ *no_read += no_read_sub;
+ return x;
+ }
}
static size_t yaz_write_UTF8 (yaz_iconv_t cd, unsigned long x,
unsigned char *outp = (unsigned char *) *outbuf;
if (*outbytesleft >= 4)
{
- *outp++ = (unsigned char) (x<<24);
- *outp++ = (unsigned char) (x<<16);
- *outp++ = (unsigned char) (x<<8);
+ *outp++ = (unsigned char) (x>>24);
+ *outp++ = (unsigned char) (x>>16);
+ *outp++ = (unsigned char) (x>>8);
*outp++ = (unsigned char) x;
(*outbytesleft) -= 4;
}
if (*outbytesleft >= 4)
{
*outp++ = (unsigned char) x;
- *outp++ = (unsigned char) (x<<8);
- *outp++ = (unsigned char) (x<<16);
- *outp++ = (unsigned char) (x<<24);
+ *outp++ = (unsigned char) (x>>8);
+ *outp++ = (unsigned char) (x>>16);
+ *outp++ = (unsigned char) (x>>24);
(*outbytesleft) -= 4;
}
else
cd->read_handle = 0;
cd->init_handle = 0;
cd->my_errno = YAZ_ICONV_UNKNOWN;
+ cd->marc8_esc_mode = 'B';
/* a useful hack: if fromcode has leading @,
the library not use YAZ's own conversions .. */
r = (size_t)(-1);
break;
}
- r = (cd->write_handle)(cd, x, outbuf, outbytesleft);
- if (r)
- break;
+ if (x)
+ {
+ r = (cd->write_handle)(cd, x, outbuf, outbytesleft);
+ if (r)
+ break;
+ }
*inbytesleft -= no_read;
(*inbuf) += no_read;
}