SRW, CQL, 2003
[yaz-moved-to-github.git] / util / siconvtst.c
1 /*
2  * Copyright (c) 1997-2003, Index Data
3  * See the file LICENSE for details.
4  *
5  * $Id: siconvtst.c,v 1.8 2003-01-06 08:20:28 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_IN 64
19 #define CHUNK_OUT 64
20
21 void convert (FILE *inf, yaz_iconv_t cd, int verbose)
22 {
23     char inbuf0[CHUNK_IN], *inbuf = inbuf0;
24     char outbuf0[CHUNK_OUT], *outbuf = outbuf0;
25     size_t inbytesleft = CHUNK_IN;
26     size_t outbytesleft = CHUNK_OUT;
27     int mustread = 1;
28
29     while (1)
30     {
31         size_t r;
32         if (mustread)
33         {
34             r = fread (inbuf, 1, inbytesleft, inf);
35             if (inbytesleft != r)
36             {
37                 if (ferror(inf))
38                 {
39                     fprintf (stderr, "yaziconv: error reading file\n");
40                     exit (6);
41                 }
42                 if (r == 0)
43                 {
44                     if (outbuf != outbuf0)
45                         fwrite (outbuf0, 1, outbuf - outbuf0, stdout);
46                     break;
47                 }
48                 inbytesleft = r;
49             }
50         }
51         if (verbose > 1)
52         {
53             fprintf (stderr, "yaz_iconv: inbytesleft=%d outbytesleft=%d\n",
54                      inbytesleft, outbytesleft);
55
56         }
57         r = yaz_iconv (cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
58         if (r == (size_t)(-1))
59         {
60             int e = yaz_iconv_error(cd);
61             if (e == YAZ_ICONV_EILSEQ)
62             {
63                 fprintf (stderr, "invalid sequence\n");
64                 return ;
65             }
66             else if (e == YAZ_ICONV_EINVAL) /* incomplete input */
67             { 
68                 size_t i;
69                 for (i = 0; i<inbytesleft; i++)
70                     inbuf0[i] = inbuf[i];
71
72                 r = fread(inbuf0 + i, 1, CHUNK_IN - i, inf);
73                 if (r != CHUNK_IN - i)
74                 {
75                     if (ferror(inf))
76                     {
77                         fprintf (stderr, "yaziconv: error reading file\n");
78                         exit(6);
79                     }
80                 }
81                 if (r == 0)
82                 {
83                     fprintf (stderr, "invalid sequence\n");
84                     return ;
85                 }
86                 inbytesleft += r;
87                 inbuf = inbuf0;
88                 mustread = 0;
89             }
90             else if (e == YAZ_ICONV_E2BIG) /* no more output space */
91             {
92                 fwrite (outbuf0, 1, outbuf - outbuf0, stdout);
93                 outbuf = outbuf0;
94                 outbytesleft = CHUNK_OUT;
95                 mustread = 0;
96             }
97             else
98             {
99                 fprintf (stderr, "yaziconv: unknown error\n");
100                 exit (7);
101             }
102         }
103         else
104         {
105             inbuf = inbuf0;
106             inbytesleft = CHUNK_IN;
107
108             fwrite (outbuf0, 1, outbuf - outbuf0, stdout);
109             outbuf = outbuf0;
110             outbytesleft = CHUNK_OUT;
111
112             mustread = 1;
113         }
114     }
115 }
116
117 int main (int argc, char **argv)
118 {
119     int ret;
120     int verbose = 0;
121     char *from = 0;
122     char *to = 0;
123     char *arg;
124     yaz_iconv_t cd;
125     FILE *inf = stdin;
126
127     while ((ret = options ("vf:t:", argv, argc, &arg)) != -2)
128     {
129         switch (ret)
130         {
131         case 0:
132             inf = fopen (arg, "rb");
133             if (!inf)
134             {
135                 fprintf (stderr, "yaziconv: cannot open %s", arg);
136                 exit (2);
137             }
138             break;
139         case 'f':
140             from = arg;
141             break;
142         case 't':
143             to = arg;
144             break;
145         case 'v':
146             verbose++;
147             break;
148         default:
149             fprintf (stderr, "yaziconv: Usage\n"
150                      "siconv -f encoding -t encoding [-v] [file]\n");
151             exit(1);
152         }
153     }
154     if (!to)
155     {
156         fprintf (stderr, "yaziconv: -t encoding missing\n");
157         exit (3);
158     }
159     if (!from)
160     {
161         fprintf (stderr, "yaziconv: -f encoding missing\n");
162         exit (4);
163     }
164     cd = yaz_iconv_open (to, from);
165     if (!cd)
166     {
167         fprintf (stderr, "yaziconv: unsupported encoding\n");
168         exit (5);
169     }
170     else
171     {
172         if (verbose)
173         {
174             fprintf (stderr, "yaziconv: using %s\n",
175                      yaz_iconv_isbuiltin(cd) ? "YAZ" : "iconv");
176         }
177     }
178     convert (inf, cd, verbose);
179     yaz_iconv_close (cd);
180     return 0;
181 }