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