Improve error reporting for ICU chains YAZ-707
[yaz-moved-to-github.git] / src / odr_oct.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2013 Index Data
3  * See the file LICENSE for details.
4  */
5 /**
6  * \file odr_oct.c
7  * \brief Implements ODR OCTET codec
8  */
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12
13 #include "odr-priv.h"
14
15 /*
16  * Top level octet string en/decoder.
17  * Returns 1 on success, 0 on error.
18  */
19 int odr_octetstring(ODR o, Odr_oct **p, int opt, const char *name)
20 {
21     int res, cons = 0;
22
23     if (o->error)
24         return 0;
25     if (o->op->t_class < 0)
26     {
27         o->op->t_class = ODR_UNIVERSAL;
28         o->op->t_tag = ODR_OCTETSTRING;
29     }
30     res = ber_tag(o, p, o->op->t_class, o->op->t_tag, &cons, opt, name);
31     if (res < 0)
32         return 0;
33     if (!res)
34         return odr_missing(o, opt, name);
35     if (o->direction == ODR_PRINT)
36     {
37         odr_prname(o, name);
38         odr_printf(o, "OCTETSTRING(len=%d) ", (*p)->len);
39
40         o->op->stream_write(o, o->op->print, ODR_OCTETSTRING,
41                             (char*) (*p)->buf, (*p)->len);
42         odr_printf(o, "\n");
43         return 1;
44     }
45     if (o->direction == ODR_DECODE)
46     {
47         *p = (Odr_oct *)odr_malloc(o, sizeof(Odr_oct));
48         (*p)->len = 0;
49         (*p)->buf = 0;
50     }
51     if (ber_octetstring(o, *p, cons))
52         return 1;
53     odr_seterror(o, OOTHER, 43);
54     return 0;
55 }
56
57 /*
58  * Friendlier interface to octetstring.
59  */
60 int odr_cstring(ODR o, char **p, int opt, const char *name)
61 {
62     int cons = 0, res;
63     Odr_oct *t;
64
65     if (o->error)
66         return 0;
67     if (o->op->t_class < 0)
68     {
69         o->op->t_class = ODR_UNIVERSAL;
70         o->op->t_tag = ODR_OCTETSTRING;
71     }
72     res = ber_tag(o, p, o->op->t_class, o->op->t_tag, &cons, opt, name);
73     if (res < 0)
74         return 0;
75     if (!res)
76         return odr_missing(o, opt, name);
77     if (o->direction == ODR_PRINT)
78     {
79         odr_prname(o, name);
80         odr_printf(o, "'%s'\n", *p);
81         return 1;
82     }
83     t = (Odr_oct *)odr_malloc(o, sizeof(Odr_oct)); /* wrapper for octstring */
84     if (o->direction == ODR_ENCODE)
85     {
86         t->buf = *p;
87         t->len = strlen(*p);
88     }
89     else
90     {
91         t->len = 0;
92         t->buf = 0;
93     }
94     if (!ber_octetstring(o, t, cons))
95         return 0;
96     if (o->direction == ODR_DECODE)
97     {
98         *p = (char *) t->buf;
99         *(*p + t->len) = '\0';  /* ber_octs reserves space for this */
100     }
101     return 1;
102 }
103
104 /*
105  * iconv interface to octetstring.
106  */
107 int odr_iconv_string(ODR o, char **p, int opt, const char *name)
108 {
109     int cons = 0, res;
110     Odr_oct *t;
111
112     if (o->error)
113         return 0;
114     if (o->op->t_class < 0)
115     {
116         o->op->t_class = ODR_UNIVERSAL;
117         o->op->t_tag = ODR_OCTETSTRING;
118     }
119     res = ber_tag(o, p, o->op->t_class, o->op->t_tag, &cons, opt, name);
120     if (res < 0)
121         return 0;
122     if (!res)
123         return odr_missing(o, opt, name);
124     if (o->direction == ODR_PRINT)
125     {
126         odr_prname(o, name);
127         odr_printf(o, "'%s'\n", *p);
128         return 1;
129     }
130     t = (Odr_oct *)odr_malloc(o, sizeof(Odr_oct)); /* wrapper for octstring */
131     if (o->direction == ODR_ENCODE)
132     {
133         t->buf = 0;
134
135         if (o->op->iconv_handle != 0)
136         {
137             size_t inleft = strlen(*p);
138             char *inbuf = *p;
139             size_t outleft = 4 * inleft + 2;
140             char *outbuf = (char *) odr_malloc (o, outleft);
141             size_t ret;
142
143             t->buf = outbuf;
144
145             ret = yaz_iconv(o->op->iconv_handle, &inbuf, &inleft,
146                             &outbuf, &outleft);
147             if (ret == (size_t)(-1))
148             {
149                 odr_seterror(o, ODATA, 44);
150                 return 0;
151             }
152             ret = yaz_iconv(o->op->iconv_handle, 0, 0,
153                             &outbuf, &outleft);
154
155             if (ret == (size_t)(-1))
156             {
157                 odr_seterror(o, ODATA, 44);
158                 return 0;
159             }
160             t->len = outbuf - (char*) t->buf;
161         }
162         if (!t->buf)
163         {
164             t->buf = *p;
165             t->len = strlen(*p);
166         }
167     }
168     else
169     {
170         t->len = 0;
171         t->buf = 0;
172     }
173     if (!ber_octetstring(o, t, cons))
174         return 0;
175     if (o->direction == ODR_DECODE)
176     {
177         *p = 0;
178
179         if (o->op->iconv_handle != 0)
180         {
181             size_t inleft = t->len;
182             char *inbuf = (char *) t->buf;
183             size_t outleft = 4 * inleft + 2;
184             char *outbuf = (char *) odr_malloc (o, outleft);
185             size_t ret;
186
187             *p = outbuf;
188
189             ret = yaz_iconv (o->op->iconv_handle, &inbuf, &inleft,
190                              &outbuf, &outleft);
191             if (ret == (size_t)(-1))
192             {
193                 odr_seterror(o, ODATA, 45);
194                 return 0;
195             }
196             ret = yaz_iconv(o->op->iconv_handle, 0, 0,
197                             &outbuf, &outleft);
198             if (ret == (size_t)(-1))
199             {
200                 odr_seterror(o, ODATA, 45);
201                 return 0;
202             }
203             inleft = outbuf - (char*) *p;
204
205             (*p)[inleft] = '\0';    /* null terminate it */
206         }
207         if (!*p)
208         {
209             *p = (char *) t->buf;
210             *(*p + t->len) = '\0';  /* ber_octs reserves space for this */
211         }
212     }
213     return 1;
214 }
215 /*
216  * Local variables:
217  * c-basic-offset: 4
218  * c-file-style: "Stroustrup"
219  * indent-tabs-mode: nil
220  * End:
221  * vim: shiftwidth=4 tabstop=8 expandtab
222  */
223