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