Fixed the asn1 for facets
[yaz-moved-to-github.git] / src / odr_oct.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2010 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)->size= 0;
49         (*p)->len = 0;
50         (*p)->buf = 0;
51     }
52     if (ber_octetstring(o, *p, cons))
53         return 1;
54     odr_seterror(o, OOTHER, 43);
55     return 0;
56 }
57
58 /*
59  * Friendlier interface to octetstring.
60  */
61 int odr_cstring(ODR o, char **p, int opt, const char *name)
62 {
63     int cons = 0, res;
64     Odr_oct *t;
65
66     if (o->error)
67         return 0;
68     if (o->op->t_class < 0)
69     {
70         o->op->t_class = ODR_UNIVERSAL;
71         o->op->t_tag = ODR_OCTETSTRING;
72     }
73     res = ber_tag(o, p, o->op->t_class, o->op->t_tag, &cons, opt, name);
74     if (res < 0)
75         return 0;
76     if (!res)
77         return odr_missing(o, opt, name);
78     if (o->direction == ODR_PRINT)
79     {
80         odr_prname(o, name);
81         odr_printf(o, "'%s'\n", *p);
82         return 1;
83     }
84     t = (Odr_oct *)odr_malloc(o, sizeof(Odr_oct)); /* wrapper for octstring */
85     if (o->direction == ODR_ENCODE)
86     {
87         t->buf = (unsigned char *) *p;
88         t->size = t->len = strlen(*p);
89     }
90     else
91     {
92         t->size= 0;
93         t->len = 0;
94         t->buf = 0;
95     }
96     if (!ber_octetstring(o, t, cons))
97         return 0;
98     if (o->direction == ODR_DECODE)
99     {
100         *p = (char *) t->buf;
101         *(*p + t->len) = '\0';  /* ber_octs reserves space for this */
102     }
103     return 1;
104 }
105
106 /*
107  * iconv interface to octetstring.
108  */
109 int odr_iconv_string(ODR o, char **p, int opt, const char *name)
110 {
111     int cons = 0, res;
112     Odr_oct *t;
113
114     if (o->error)
115         return 0;
116     if (o->op->t_class < 0)
117     {
118         o->op->t_class = ODR_UNIVERSAL;
119         o->op->t_tag = ODR_OCTETSTRING;
120     }
121     res = ber_tag(o, p, o->op->t_class, o->op->t_tag, &cons, opt, name);
122     if (res < 0)
123         return 0;
124     if (!res)
125         return odr_missing(o, opt, name);
126     if (o->direction == ODR_PRINT)
127     {
128         odr_prname(o, name);
129         odr_printf(o, "'%s'\n", *p);
130         return 1;
131     }
132     t = (Odr_oct *)odr_malloc(o, sizeof(Odr_oct)); /* wrapper for octstring */
133     if (o->direction == ODR_ENCODE)
134     {
135         t->buf = 0;
136
137         if (o->op->iconv_handle != 0)
138         {
139             size_t inleft = strlen(*p);
140             char *inbuf = *p;
141             size_t outleft = 4 * inleft + 2;
142             char *outbuf = (char *) odr_malloc (o, outleft);
143             size_t ret;
144             
145             t->buf = (unsigned char *) outbuf;
146             
147             ret = yaz_iconv(o->op->iconv_handle, &inbuf, &inleft,
148                             &outbuf, &outleft);
149             if (ret == (size_t)(-1))
150             {
151                 odr_seterror(o, ODATA, 44);
152                 return 0;
153             }
154             ret = yaz_iconv(o->op->iconv_handle, 0, 0,
155                             &outbuf, &outleft);
156
157             if (ret == (size_t)(-1))
158             {
159                 odr_seterror(o, ODATA, 44);
160                 return 0;
161             }
162             t->size = t->len = outbuf - (char*) t->buf;
163         }
164         if (!t->buf)
165         {
166             t->buf = (unsigned char *) *p;
167             t->size = t->len = strlen(*p);
168         }
169     }
170     else
171     {
172         t->size= 0;
173         t->len = 0;
174         t->buf = 0;
175     }
176     if (!ber_octetstring(o, t, cons))
177         return 0;
178     if (o->direction == ODR_DECODE)
179     {
180         *p = 0;
181
182         if (o->op->iconv_handle != 0)
183         {
184             size_t inleft = t->len;
185             char *inbuf = (char *) t->buf;
186             size_t outleft = 4 * inleft + 2;
187             char *outbuf = (char *) odr_malloc (o, outleft);
188             size_t ret;
189
190             *p = outbuf;
191             
192             ret = yaz_iconv (o->op->iconv_handle, &inbuf, &inleft,
193                              &outbuf, &outleft);
194             if (ret == (size_t)(-1))
195             {
196                 odr_seterror(o, ODATA, 45);
197                 return 0;
198             }
199             ret = yaz_iconv(o->op->iconv_handle, 0, 0,
200                             &outbuf, &outleft);
201             if (ret == (size_t)(-1))
202             {
203                 odr_seterror(o, ODATA, 45);
204                 return 0;
205             }
206             inleft = outbuf - (char*) *p;
207             
208             (*p)[inleft] = '\0';    /* null terminate it */
209         }
210         if (!*p)
211         {
212             *p = (char *) t->buf;
213             *(*p + t->len) = '\0';  /* ber_octs reserves space for this */
214         }
215     }
216     return 1;
217 }
218 /*
219  * Local variables:
220  * c-basic-offset: 4
221  * c-file-style: "Stroustrup"
222  * indent-tabs-mode: nil
223  * End:
224  * vim: shiftwidth=4 tabstop=8 expandtab
225  */
226