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