cbe4ec2d77986a3b0e971d638e77ceb2dcb70071
[yaz-moved-to-github.git] / util / siconvtst.c
1 /*
2  * Copyright (c) 1997-2002, Index Data
3  * See the file LICENSE for details.
4  *
5  * $Id: siconvtst.c,v 1.4 2002-08-28 19:33:53 adam Exp $
6  */
7
8 #if HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #include <errno.h>
13 #include <string.h>
14 #include <ctype.h>
15
16 #include <yaz/yaz-util.h>
17
18 #define CHUNK 8
19
20 void convert (FILE *inf, yaz_iconv_t cd)
21 {
22     char inbuf0[CHUNK], *inbuf = inbuf0;
23     char outbuf0[CHUNK], *outbuf = outbuf0;
24     size_t outbytesleft = CHUNK;
25     size_t inbytesleft = CHUNK;
26     int mustread = 1;
27
28     while (1)
29     {
30         size_t r;
31         if (mustread)
32         {
33             r = fread (inbuf, 1, inbytesleft, inf);
34             if (inbytesleft != r)
35             {
36                 if (ferror(inf))
37                 {
38                     fprintf (stderr, "yaziconv: error reading file\n");
39                     exit (6);
40                 }
41                 if (r == 0)
42                 {
43                     if (outbuf != outbuf0)
44                         fwrite (outbuf0, 1, outbuf - outbuf0, stdout);
45                     break;
46                 }
47                 inbytesleft = r;
48             }
49         }
50         r = yaz_iconv (cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
51         if (r == (size_t)(-1))
52         {
53             int e = yaz_iconv_error(cd);
54             if (e == YAZ_ICONV_EILSEQ)
55             {
56                 fprintf (stderr, "invalid sequence\n");
57                 return ;
58             }
59             else if (e == YAZ_ICONV_EINVAL) /* incomplete input */
60             { 
61                 size_t i;
62                 for (i = 0; i<inbytesleft; i++)
63                     inbuf0[i] = inbuf[i];
64                 inbuf = inbuf0 + i;
65                 inbytesleft = CHUNK - inbytesleft;
66                 mustread = 1;
67             }
68             else if (e == YAZ_ICONV_E2BIG) /* no more output space */
69             {
70                 fwrite (outbuf0, 1, outbuf - outbuf0, stdout);
71                 outbuf = outbuf0;
72                 outbytesleft = CHUNK;
73                 mustread = 0;
74             }
75             else
76             {
77                 fprintf (stderr, "yaziconv: unknown error\n");
78                 exit (7);
79             }
80         }
81         else
82         {
83             inbuf = inbuf0;
84             inbytesleft = CHUNK;
85
86             fwrite (outbuf0, 1, outbuf - outbuf0, stdout);
87             outbuf = outbuf0;
88             outbytesleft = CHUNK;
89
90             mustread = 1;
91         }
92     }
93 }
94
95 int main (int argc, char **argv)
96 {
97     int ret;
98     char *from = 0;
99     char *to = 0;
100     char *arg;
101     yaz_iconv_t cd;
102     FILE *inf = stdin;
103
104     while ((ret = options ("f:t:", argv, argc, &arg)) != -2)
105     {
106         switch (ret)
107         {
108         case 0:
109             inf = fopen (arg, "rb");
110             if (!inf)
111             {
112                 fprintf (stderr, "yaziconv: cannot open %s", arg);
113                 exit (2);
114             }
115             break;
116         case 'f':
117             from = arg;
118             break;
119         case 't':
120             to = arg;
121             break;
122         default:
123             fprintf (stderr, "yaziconv: Usage\n"
124                      "siconv -f encoding -t encoding [file]\n");
125             exit(1);
126         }
127     }
128     if (!to)
129     {
130         fprintf (stderr, "yaziconv: -t encoding missing\n");
131         exit (3);
132     }
133     if (!from)
134     {
135         fprintf (stderr, "yaziconv: -f encoding missing\n");
136         exit (4);
137     }
138     cd = yaz_iconv_open (to, from);
139     if (!cd)
140     {
141         fprintf (stderr, "yaziconv: unsupported encoding\n");
142         exit (5);
143     }
144
145     convert (inf, cd);
146     yaz_iconv_close (cd);
147     return 0;
148 }