Fix left-right truncation fix
[yaz-moved-to-github.git] / src / iso5428.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2011 Index Data
3  * See the file LICENSE for details.
4  */
5 /**
6  * \file
7  * \brief ISO-5428:1984 encoding and decoding
8  */
9
10 #if HAVE_CONFIG_H
11 #include <config.h>
12 #endif
13
14 #include <assert.h>
15 #include <errno.h>
16 #include <string.h>
17 #include <ctype.h>
18
19 #include "iconv-p.h"
20
21 static unsigned long read_iso_5428_1984(yaz_iconv_t cd, yaz_iconv_decoder_t d,
22                                         unsigned char *inp,
23                                         size_t inbytesleft, size_t *no_read)
24 {
25     unsigned long x = 0;
26     int tonos = 0;
27     int dialitika = 0;
28
29     *no_read = 0;
30     while (inbytesleft > 0)
31     {
32         if (*inp == 0xa2)
33         {
34             tonos = 1;
35         }
36         else if (*inp == 0xa3)
37         {
38             dialitika = 1;
39         }
40         else
41             break;
42         inp++;
43         --inbytesleft;
44         (*no_read)++;
45     }    
46     if (inbytesleft == 0)
47     {
48         yaz_iconv_set_errno(cd, YAZ_ICONV_EINVAL); /* incomplete input */
49         *no_read = 0;
50         return 0;
51     }
52     switch (*inp) {
53     case 0xe1: /*  alpha small */
54             if (tonos) 
55                 x = 0x03ac;
56             else 
57                 x = 0x03b1;
58             break;
59     case 0xc1: /*  alpha capital */
60             if (tonos) 
61                 x = 0x0386;
62             else 
63                 x = 0x0391;
64             break;
65
66     case 0xe2: /*  Beta small */
67             x = 0x03b2;
68             break;
69     case 0xc2: /*  Beta capital */
70             x = 0x0392;
71             break;
72
73     case 0xe4: /*  Gamma small */
74             x = 0x03b3;
75             break;
76     case 0xc4: /*  Gamma capital */
77             x = 0x0393;
78             break;
79
80     case 0xe5: /*  Delta small */
81             x = 0x03b4;
82             break;
83     case 0xc5: /*  Delta capital */
84             x = 0x0394;
85             break;
86     case 0xe6: /*  epsilon small */
87             if (tonos) 
88                 x = 0x03ad;
89             else 
90                 x = 0x03b5;
91             break;
92     case 0xc6: /*  epsilon capital */
93             if (tonos) 
94                 x = 0x0388;
95             else 
96                 x = 0x0395;
97             break;
98     case 0xe9: /*  Zeta small */
99             x = 0x03b6;
100             break;
101     case 0xc9: /*  Zeta capital */
102             x = 0x0396;
103             break;
104     case 0xea: /*  Eta small */
105             if (tonos) 
106                 x = 0x03ae;
107             else 
108                 x = 0x03b7;
109             break;
110     case 0xca: /*  Eta capital */
111             if (tonos) 
112                 x = 0x0389;
113             else 
114                 x = 0x0397;
115             break;
116     case 0xeb: /*  Theta small */
117             x = 0x03b8;
118             break;
119     case 0xcb: /*  Theta capital */
120             x = 0x0398;
121             break;
122     case 0xec: /*  Iota small */
123             if (tonos) 
124                 if (dialitika) 
125                     x = 0x0390;
126                 else 
127                     x = 0x03af;
128             else 
129                 if (dialitika) 
130                     x = 0x03ca;
131                 else 
132                     x = 0x03b9;
133             break;
134     case 0xcc: /*  Iota capital */
135             if (tonos) 
136                 x = 0x038a;
137             else 
138                 if (dialitika) 
139                     x = 0x03aa;
140                 else 
141                     x = 0x0399;
142             break;
143     case 0xed: /*  Kappa small */
144             x = 0x03ba;
145             break;
146     case 0xcd: /*  Kappa capital */
147             x = 0x039a;
148             break;
149     case 0xee: /*  Lambda small */
150             x = 0x03bb;
151             break;
152     case 0xce: /*  Lambda capital */
153             x = 0x039b;
154             break;
155     case 0xef: /*  Mu small */
156             x = 0x03bc;
157             break;
158     case 0xcf: /*  Mu capital */
159             x = 0x039c;
160             break;
161     case 0xf0: /*  Nu small */
162             x = 0x03bd;
163             break;
164     case 0xd0: /*  Nu capital */
165             x = 0x039d;
166             break;
167     case 0xf1: /*  Xi small */
168             x = 0x03be;
169             break;
170     case 0xd1: /*  Xi capital */
171             x = 0x039e;
172             break;
173     case 0xf2: /*  Omicron small */
174             if (tonos) 
175                 x = 0x03cc;
176             else 
177                 x = 0x03bf;
178             break;
179     case 0xd2: /*  Omicron capital */
180             if (tonos) 
181                 x = 0x038c;
182             else 
183                 x = 0x039f;
184             break;
185     case 0xf3: /*  Pi small */
186             x = 0x03c0;
187             break;
188     case 0xd3: /*  Pi capital */
189             x = 0x03a0;
190             break;
191     case 0xf5: /*  Rho small */
192             x = 0x03c1;
193             break;
194     case 0xd5: /*  Rho capital */
195             x = 0x03a1;
196             break;
197     case 0xf7: /*  Sigma small (end of words) */
198             x = 0x03c2;
199             break;
200     case 0xf6: /*  Sigma small */
201             x = 0x03c3;
202             break;
203     case 0xd6: /*  Sigma capital */
204             x = 0x03a3;
205             break;
206     case 0xf8: /*  Tau small */
207             x = 0x03c4;
208             break;
209     case 0xd8: /*  Tau capital */
210             x = 0x03a4;
211             break;
212     case 0xf9: /*  Upsilon small */
213             if (tonos) 
214                 if (dialitika) 
215                     x = 0x03b0;
216                 else 
217                     x = 0x03cd;
218             else 
219                 if (dialitika) 
220                     x = 0x03cb;
221                 else 
222                     x = 0x03c5;
223             break;
224     case 0xd9: /*  Upsilon capital */
225             if (tonos) 
226                 x = 0x038e;
227             else 
228                 if (dialitika) 
229                     x = 0x03ab;
230                 else 
231                     x = 0x03a5;
232             break;
233     case 0xfa: /*  Phi small */
234             x = 0x03c6;
235             break;
236     case 0xda: /*  Phi capital */
237             x = 0x03a6;
238             break;
239     case 0xfb: /*  Chi small */
240             x = 0x03c7;
241             break;
242     case 0xdb: /*  Chi capital */
243             x = 0x03a7;
244             break;
245     case 0xfc: /*  Psi small */
246             x = 0x03c8;
247             break;
248     case 0xdc: /*  Psi capital */
249             x = 0x03a8;
250             break;
251     case 0xfd: /*  Omega small */
252             if (tonos) 
253                 x = 0x03ce;
254             else 
255                 x = 0x03c9;
256             break;
257     case 0xdd: /*  Omega capital */
258             if (tonos) 
259                 x = 0x038f;
260             else 
261                 x = 0x03a9;
262             break;
263     default:
264         x = *inp;
265         break;
266     }
267     (*no_read)++;
268     
269     return x;
270 }
271
272 static size_t write_iso_5428_1984(yaz_iconv_t cd, yaz_iconv_encoder_t en,
273                                  unsigned long x,
274                                  char **outbuf, size_t *outbytesleft)
275 {
276     size_t k = 0;
277     unsigned char *out = (unsigned char*) *outbuf;
278     if (*outbytesleft < 3)
279     {
280         yaz_iconv_set_errno(cd, YAZ_ICONV_E2BIG);  /* not room for output */
281         return (size_t)(-1);
282     }
283     switch (x)
284     {
285     case 0x03ac : out[k++]=0xa2; out[k++]=0xe1; break;
286     case 0x03b1 : out[k++]=0xe1; break;
287     case 0x0386 : out[k++]=0xa2; out[k++]=0xc1; break;
288     case 0x0391 : out[k++]=0xc1; break;
289     case 0x03b2 : out[k++]=0xe2; break;
290     case 0x0392 : out[k++]=0xc2; break;
291     case 0x03b3 : out[k++]=0xe4; break;
292     case 0x0393 : out[k++]=0xc4; break;
293     case 0x03b4 : out[k++]=0xe5; break;
294     case 0x0394 : out[k++]=0xc5; break;
295     case 0x03ad : out[k++]=0xa2; out[k++]=0xe6; break;
296     case 0x03b5 : out[k++]=0xe6; break;
297     case 0x0388 : out[k++]=0xa2; out[k++]=0xc6; break;
298     case 0x0395 : out[k++]=0xc6; break;
299     case 0x03b6 : out[k++]=0xe9; break;
300     case 0x0396 : out[k++]=0xc9; break;
301     case 0x03ae : out[k++]=0xa2; out[k++]=0xea; break;
302     case 0x03b7 : out[k++]=0xea; break;
303     case 0x0389 : out[k++]=0xa2; out[k++]=0xca; break;
304     case 0x0397 : out[k++]=0xca; break;
305     case 0x03b8 : out[k++]=0xeb; break;
306     case 0x0398 : out[k++]=0xcb; break;
307     case 0x0390 : out[k++]=0xa2; out[k++]=0xa3; out[k++]=0xec; break;
308     case 0x03af : out[k++]=0xa2; out[k++]=0xec; break;
309     case 0x03ca : out[k++]=0xa3; out[k++]=0xec; break;
310     case 0x03b9 : out[k++]=0xec; break;
311     case 0x038a : out[k++]=0xa2; out[k++]=0xcc; break;
312     case 0x03aa : out[k++]=0xa3; out[k++]=0xcc; break;
313     case 0x0399 : out[k++]=0xcc; break;
314     case 0x03ba : out[k++]=0xed; break;
315     case 0x039a : out[k++]=0xcd; break;
316     case 0x03bb : out[k++]=0xee; break;
317     case 0x039b : out[k++]=0xce; break;
318     case 0x03bc : out[k++]=0xef; break;
319     case 0x039c : out[k++]=0xcf; break;
320     case 0x03bd : out[k++]=0xf0; break;
321     case 0x039d : out[k++]=0xd0; break;
322     case 0x03be : out[k++]=0xf1; break;
323     case 0x039e : out[k++]=0xd1; break;
324     case 0x03cc : out[k++]=0xa2; out[k++]=0xf2; break;
325     case 0x03bf : out[k++]=0xf2; break;
326     case 0x038c : out[k++]=0xa2; out[k++]=0xd2; break;
327     case 0x039f : out[k++]=0xd2; break;
328     case 0x03c0 : out[k++]=0xf3; break;
329     case 0x03a0 : out[k++]=0xd3; break;
330     case 0x03c1 : out[k++]=0xf5; break;
331     case 0x03a1 : out[k++]=0xd5; break;
332     case 0x03c2 : out[k++]=0xf7; break;
333     case 0x03c3 : out[k++]=0xf6; break;
334     case 0x03a3 : out[k++]=0xd6; break;
335     case 0x03c4 : out[k++]=0xf8; break;
336     case 0x03a4 : out[k++]=0xd8; break;
337     case 0x03b0 : out[k++]=0xa2; out[k++]=0xa3; out[k++]=0xf9; break;
338     case 0x03cd : out[k++]=0xa2; out[k++]=0xf9; break;
339     case 0x03cb : out[k++]=0xa3; out[k++]=0xf9; break;
340     case 0x03c5 : out[k++]=0xf9; break;
341     case 0x038e : out[k++]=0xa2; out[k++]=0xd9; break;
342     case 0x03ab : out[k++]=0xa3; out[k++]=0xd9; break;
343     case 0x03a5 : out[k++]=0xd9; break;
344     case 0x03c6 : out[k++]=0xfa; break;
345     case 0x03a6 : out[k++]=0xda; break;
346     case 0x03c7 : out[k++]=0xfb; break;
347     case 0x03a7 : out[k++]=0xdb; break;
348     case 0x03c8 : out[k++]=0xfc; break;
349     case 0x03a8 : out[k++]=0xdc; break;
350     case 0x03ce : out[k++]=0xa2; out[k++]=0xfd; break;
351     case 0x03c9 : out[k++]=0xfd; break;
352     case 0x038f : out[k++]=0xa2; out[k++]=0xdd; break;
353     case 0x03a9 : out[k++]=0xdd; break;
354     default:
355         if (x > 255)
356         {
357             yaz_iconv_set_errno(cd, YAZ_ICONV_EILSEQ);
358             return (size_t) -1;
359         }
360         out[k++] = x;
361         break;
362     }
363     *outbytesleft -= k;
364     (*outbuf) += k;
365     return 0;
366 }
367
368 yaz_iconv_encoder_t yaz_iso_5428_encoder(const char *name,
369                                          yaz_iconv_encoder_t e)
370 {
371     if (!yaz_matchstr(name, "iso54281984")
372         || !yaz_matchstr(name, "iso5428:1984"))
373     {
374         e->write_handle = write_iso_5428_1984;
375         return e;
376     }
377     return 0;
378 }
379
380 yaz_iconv_decoder_t yaz_iso_5428_decoder(const char *name,
381                                          yaz_iconv_decoder_t d)
382 {
383     if (!yaz_matchstr(name, "iso54281984")
384         || !yaz_matchstr(name, "iso5428:1984"))
385     {
386         d->read_handle = read_iso_5428_1984;
387         return d;
388     }
389     return 0;
390 }
391
392
393
394 /*
395  * Local variables:
396  * c-basic-offset: 4
397  * c-file-style: "Stroustrup"
398  * indent-tabs-mode: nil
399  * End:
400  * vim: shiftwidth=4 tabstop=8 expandtab
401  */
402