1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2012 Index Data
3 * See the file LICENSE for details.
7 * \brief ISO 5426 decoding
10 * http://www.loc.gov/marc/specifications/specchariso8.html
12 * ISO 5426 reference (in German)
13 * Zeichenkonkordanz MAB2-Zeichensatz - ISO/IEC 10646 / Unicode
14 * http://www.d-nb.de/standardisierung/pdf/mab_unic.pdf
25 #include <yaz/xmalloc.h>
34 unsigned long comb_x[8];
35 size_t comb_no_read[8];
38 yaz_conv_func_t yaz_iso5426_42_conv;
39 yaz_conv_func_t yaz_iso5426_45_conv;
40 yaz_conv_func_t yaz_iso5426_67_conv;
41 yaz_conv_func_t yaz_iso5426_62_conv;
42 yaz_conv_func_t yaz_iso5426_70_conv;
43 yaz_conv_func_t yaz_iso5426_32_conv;
44 yaz_conv_func_t yaz_iso5426_4E_conv;
45 yaz_conv_func_t yaz_iso5426_51_conv;
46 yaz_conv_func_t yaz_iso5426_33_conv;
47 yaz_conv_func_t yaz_iso5426_34_conv;
48 yaz_conv_func_t yaz_iso5426_53_conv;
49 yaz_conv_func_t yaz_iso5426_31_conv;
52 static unsigned long yaz_read_iso5426_comb(yaz_iconv_t cd,
53 struct decoder_data *data,
55 size_t inbytesleft, size_t *no_read,
58 static unsigned long read_iso5426(yaz_iconv_t cd, yaz_iconv_decoder_t d,
60 size_t inbytesleft, size_t *no_read)
62 struct decoder_data *data = (struct decoder_data *) d->data;
64 if (data->comb_offset < data->comb_size)
66 *no_read = data->comb_no_read[data->comb_offset];
67 x = data->comb_x[data->comb_offset];
69 /* special case for double-diacritic combining characters,
70 INVERTED BREVE and DOUBLE TILDE.
71 We'll increment the no_read counter by 1, since we want to skip over
72 the processing of the closing ligature character
74 /* this code is no longer necessary.. our handlers code in
75 yaz_iso5426_?_conv (generated by charconv.tcl) now returns
76 0 and no_read=1 when a sequence does not match the input.
77 The SECOND HALFs in codetables.xml produces a non-existant
78 entry in the conversion trie.. Hence when met, the input byte is
79 skipped as it should (in yaz_iconv)
82 if (x == 0x0361 || x == 0x0360)
89 data->comb_offset = 0;
90 for (data->comb_size = 0; data->comb_size < 8; data->comb_size++)
94 if (inbytesleft == 0 && data->comb_size)
96 yaz_iconv_set_errno(cd, YAZ_ICONV_EINVAL);
101 x = yaz_read_iso5426_comb(cd, data, inp, inbytesleft, no_read, &comb);
104 data->comb_x[data->comb_size] = x;
105 data->comb_no_read[data->comb_size] = *no_read;
107 inbytesleft = inbytesleft - *no_read;
114 static unsigned long read_iso5426s(yaz_iconv_t cd, yaz_iconv_decoder_t d,
116 size_t inbytesleft, size_t *no_read)
118 struct decoder_data *data = (struct decoder_data *) d->data;
119 unsigned long x = read_iso5426(cd, d, inp, inbytesleft, no_read);
120 if (x && data->comb_size == 1)
122 if (yaz_iso_8859_1_lookup_x12(x, data->comb_x[0], &x))
124 *no_read += data->comb_no_read[0];
132 static unsigned long yaz_read_iso5426_comb(yaz_iconv_t cd,
133 struct decoder_data *data,
135 size_t inbytesleft, size_t *no_read,
139 while (inbytesleft > 0 && *inp == 27)
141 int *modep = &data->g0_mode;
142 size_t inbytesleft0 = inbytesleft;
146 if (inbytesleft == 0)
148 if (*inp == '$') /* set with multiple bytes */
153 if (inbytesleft == 0)
155 if (*inp == '(' || *inp == ',') /* G0 */
160 else if (*inp == ')' || *inp == '-') /* G1 */
164 modep = &data->g1_mode;
166 if (inbytesleft == 0)
168 if (*inp == '!') /* ANSEL is a special case */
173 if (inbytesleft == 0)
175 *modep = *inp++; /* Final character */
178 (*no_read) += inbytesleft0 - inbytesleft;
180 if (inbytesleft == 0)
182 else if (*inp == ' ')
190 size_t no_read_sub = 0;
191 int mode = *inp < 128 ? data->g0_mode : data->g1_mode;
196 case 'B': /* Basic ASCII */
197 case 's': /* ASCII */
198 x = yaz_iso5426_42_conv(inp, inbytesleft, &no_read_sub, comb, 127, 0);
200 case 'E': /* ANSEL */
201 x = yaz_iso5426_45_conv(inp, inbytesleft, &no_read_sub, comb, 127, 128);
205 case 'g': /* Greek */
206 x = yaz_iso5426_67_conv(inp, inbytesleft, &no_read_sub, comb, 127, 0);
208 case 'b': /* Subscripts */
209 x = yaz_iso5426_62_conv(inp, inbytesleft, &no_read_sub, comb, 127, 0);
211 case 'p': /* Superscripts */
212 x = yaz_iso5426_70_conv(inp, inbytesleft, &no_read_sub, comb, 127, 0);
214 case '2': /* Basic Hebrew */
215 x = yaz_iso5426_32_conv(inp, inbytesleft, &no_read_sub, comb, 127, 0);
217 case 'N': /* Basic Cyrillic */
218 x = yaz_iso5426_4E_conv(inp, inbytesleft, &no_read_sub, comb, 127, 0);
220 case 'Q': /* Extended Cyrillic */
221 x = yaz_iso5426_51_conv(inp, inbytesleft, &no_read_sub, comb, 127, 0);
223 case '3': /* Basic Arabic */
224 x = yaz_iso5426_33_conv(inp, inbytesleft, &no_read_sub, comb, 127, 0);
226 case '4': /* Extended Arabic */
227 x = yaz_iso5426_34_conv(inp, inbytesleft, &no_read_sub, comb, 127, 0);
229 case 'S': /* Greek */
230 x = yaz_iso5426_53_conv(inp, inbytesleft, &no_read_sub, comb, 127, 0);
232 case '1': /* Chinese, Japanese, Korean (EACC) */
233 x = yaz_iso5426_31_conv(inp, inbytesleft, &no_read_sub, comb, 127, 0);
238 yaz_iconv_set_errno(cd, YAZ_ICONV_EILSEQ);
241 *no_read += no_read_sub;
246 yaz_iconv_set_errno(cd, YAZ_ICONV_EINVAL);
251 static size_t init_iso5426(yaz_iconv_t cd, yaz_iconv_decoder_t d,
253 size_t inbytesleft, size_t *no_read)
255 struct decoder_data *data = (struct decoder_data *) d->data;
258 data->comb_offset = data->comb_size = 0;
262 void destroy_iso5426(yaz_iconv_decoder_t d)
264 struct decoder_data *data = (struct decoder_data *) d->data;
268 yaz_iconv_decoder_t yaz_iso5426_decoder(const char *fromcode,
269 yaz_iconv_decoder_t d)
271 if (!yaz_matchstr(fromcode, "ISO5426"))
272 d->read_handle = read_iso5426;
276 struct decoder_data *data = (struct decoder_data *)
277 xmalloc(sizeof(*data));
279 d->init_handle = init_iso5426;
280 d->destroy_handle = destroy_iso5426;
289 * c-file-style: "Stroustrup"
290 * indent-tabs-mode: nil
292 * vim: shiftwidth=4 tabstop=8 expandtab