Fixed buffer handling (incomplete input) in yaziconv test
[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.5 2002-12-10 10:23:21 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)
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         r = yaz_iconv (cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
52         if (r == (size_t)(-1))
53         {
54             int e = yaz_iconv_error(cd);
55             if (e == YAZ_ICONV_EILSEQ)
56             {
57                 fprintf (stderr, "invalid sequence\n");
58                 return ;
59             }
60             else if (e == YAZ_ICONV_EINVAL) /* incomplete input */
61             { 
62                 size_t i;
63                 for (i = 0; i<inbytesleft; i++)
64                     inbuf0[i] = inbuf[i];
65
66                 r = fread(inbuf0 + i, 1, CHUNK_IN - i, inf);
67                 if (r != CHUNK_IN - i)
68                 {
69                     if (ferror(inf))
70                     {
71                         fprintf (stderr, "yaziconv: error reading file\n");
72                         exit(6);
73                     }
74                 }
75                 if (r == 0)
76                 {
77                     fprintf (stderr, "invalid sequence\n");
78                     return ;
79                 }
80                 inbytesleft += r;
81                 inbuf = inbuf0;
82                 mustread = 0;
83             }
84             else if (e == YAZ_ICONV_E2BIG) /* no more output space */
85             {
86                 fwrite (outbuf0, 1, outbuf - outbuf0, stdout);
87                 outbuf = outbuf0;
88                 outbytesleft = CHUNK_OUT;
89                 mustread = 0;
90             }
91             else
92             {
93                 fprintf (stderr, "yaziconv: unknown error\n");
94                 exit (7);
95             }
96         }
97         else
98         {
99             inbuf = inbuf0;
100             inbytesleft = CHUNK_IN;
101
102             fwrite (outbuf0, 1, outbuf - outbuf0, stdout);
103             outbuf = outbuf0;
104             outbytesleft = CHUNK_OUT;
105
106             mustread = 1;
107         }
108     }
109 }
110
111 int main (int argc, char **argv)
112 {
113     int ret;
114     char *from = 0;
115     char *to = 0;
116     char *arg;
117     yaz_iconv_t cd;
118     FILE *inf = stdin;
119
120     while ((ret = options ("f:t:", argv, argc, &arg)) != -2)
121     {
122         switch (ret)
123         {
124         case 0:
125             inf = fopen (arg, "rb");
126             if (!inf)
127             {
128                 fprintf (stderr, "yaziconv: cannot open %s", arg);
129                 exit (2);
130             }
131             break;
132         case 'f':
133             from = arg;
134             break;
135         case 't':
136             to = arg;
137             break;
138         default:
139             fprintf (stderr, "yaziconv: Usage\n"
140                      "siconv -f encoding -t encoding [file]\n");
141             exit(1);
142         }
143     }
144     if (!to)
145     {
146         fprintf (stderr, "yaziconv: -t encoding missing\n");
147         exit (3);
148     }
149     if (!from)
150     {
151         fprintf (stderr, "yaziconv: -f encoding missing\n");
152         exit (4);
153     }
154     cd = yaz_iconv_open (to, from);
155     if (!cd)
156     {
157         fprintf (stderr, "yaziconv: unsupported encoding\n");
158         exit (5);
159     }
160
161     convert (inf, cd);
162     yaz_iconv_close (cd);
163     return 0;
164 }