Allow HTTP protocol on unix local socket
[yaz-moved-to-github.git] / src / iconv_decode_danmarc.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2012 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 = 'a';
61             data->x_back = 'a';
62             *no_read = 1;
63             break;
64         case 0xc5: /* LATIN CAPITAL LETTER A WITH RING ABOVE */
65             x = 'A';
66             data->x_back = 'a';
67             *no_read = 1;
68             break;
69         default:
70             if (inbytesleft < 5)
71             {
72                 yaz_iconv_set_errno(cd, YAZ_ICONV_EINVAL);
73                 *no_read = 0;
74                 return 0;
75             }
76             else
77             {
78                 unsigned long v;
79                 sscanf((const char *) inp+1, "%4lx", &v);
80                 *no_read = 5;
81                 x = v;
82             }
83         }
84     }
85     else
86         *no_read = 1;
87     return x;
88 }
89
90
91 static size_t init_danmarc(yaz_iconv_t cd, yaz_iconv_decoder_t d,
92                            unsigned char *inp,
93                            size_t inbytesleft, size_t *no_read)
94 {
95     struct decoder_data *data = (struct decoder_data *) d->data;
96     data->x_back = 0;
97     return 0;
98 }
99
100 void destroy_danmarc(yaz_iconv_decoder_t d)
101 {
102     struct decoder_data *data = (struct decoder_data *) d->data;
103     xfree(data);
104 }
105
106 yaz_iconv_decoder_t yaz_danmarc_decoder(const char *fromcode,
107                                         yaz_iconv_decoder_t d)
108
109 {
110     if (!yaz_matchstr(fromcode, "danmarc"))
111     {
112         struct decoder_data *data = (struct decoder_data *)
113             xmalloc(sizeof(*data));
114         d->data = data;
115         data->x_back = 0;
116         d->read_handle = read_danmarc;
117         d->init_handle = init_danmarc;
118         d->destroy_handle = destroy_danmarc;
119         return d;
120     }
121     return 0;
122 }
123
124
125 /*
126  * Local variables:
127  * c-basic-offset: 4
128  * c-file-style: "Stroustrup"
129  * indent-tabs-mode: nil
130  * End:
131  * vim: shiftwidth=4 tabstop=8 expandtab
132  */
133