Version 5.1.1
[yaz-moved-to-github.git] / src / iconv_decode_danmarc.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 Danmarc2 character set decoding
8  *
9  */
10
11 #if HAVE_CONFIG_H
12 #include <config.h>
13 #endif
14
15 #include <assert.h>
16 #include <errno.h>
17 #include <string.h>
18 #include <stdio.h>
19 #include <yaz/log.h>
20 #include <yaz/xmalloc.h>
21 #include "iconv-p.h"
22
23 struct decoder_data {
24     unsigned long x_back;
25 };
26
27 static unsigned long read_danmarc(yaz_iconv_t cd,
28                                   yaz_iconv_decoder_t d,
29                                   unsigned char *inp,
30                                   size_t inbytesleft, size_t *no_read)
31 {
32     struct decoder_data *data = (struct decoder_data *) d->data;
33     unsigned long x = inp[0];
34
35     if (data->x_back)
36     {
37         *no_read = 1;
38         x = data->x_back;
39         data->x_back = 0;
40         return x;
41     }
42
43     if (x == '@')
44     {
45         if (inbytesleft < 2)
46         {
47             yaz_iconv_set_errno(cd, YAZ_ICONV_EINVAL);
48             *no_read = 0;
49             return 0;
50         }
51         switch(inp[1])
52         {
53         case '@':
54         case '*':
55         case 0xa4: /* CURRENCY SIGN */
56             x = inp[1];
57             *no_read = 2;
58             break;
59         case 0xe5: /* LATIN SMALL LETTER A WITH RING ABOVE */
60             x = 0xa733;
61             *no_read = 2;
62             break;
63         case 0xc5: /* LATIN CAPITAL LETTER A WITH RING ABOVE */
64             x = 0xa732;
65             *no_read = 2;
66             break;
67         default:
68             if (inbytesleft < 5)
69             {
70                 yaz_iconv_set_errno(cd, YAZ_ICONV_EINVAL);
71                 *no_read = 0;
72                 return 0;
73             }
74             else
75             {
76                 unsigned long v;
77                 sscanf((const char *) inp+1, "%4lx", &v);
78                 *no_read = 5;
79                 x = v;
80             }
81         }
82     }
83     else
84         *no_read = 1;
85     return x;
86 }
87
88
89 static size_t init_danmarc(yaz_iconv_t cd, yaz_iconv_decoder_t d,
90                            unsigned char *inp,
91                            size_t inbytesleft, size_t *no_read)
92 {
93     struct decoder_data *data = (struct decoder_data *) d->data;
94     data->x_back = 0;
95     return 0;
96 }
97
98 void destroy_danmarc(yaz_iconv_decoder_t d)
99 {
100     struct decoder_data *data = (struct decoder_data *) d->data;
101     xfree(data);
102 }
103
104 yaz_iconv_decoder_t yaz_danmarc_decoder(const char *fromcode,
105                                         yaz_iconv_decoder_t d)
106
107 {
108     if (!yaz_matchstr(fromcode, "danmarc"))
109     {
110         struct decoder_data *data = (struct decoder_data *)
111             xmalloc(sizeof(*data));
112         d->data = data;
113         data->x_back = 0;
114         d->read_handle = read_danmarc;
115         d->init_handle = init_danmarc;
116         d->destroy_handle = destroy_danmarc;
117         return d;
118     }
119     return 0;
120 }
121
122
123 /*
124  * Local variables:
125  * c-basic-offset: 4
126  * c-file-style: "Stroustrup"
127  * indent-tabs-mode: nil
128  * End:
129  * vim: shiftwidth=4 tabstop=8 expandtab
130  */
131