Fixed bug #830: pkg-config support. YAZ installs yaz.pc for Debian
[yaz-moved-to-github.git] / src / odr_oct.c
1 /*
2  * Copyright (C) 1995-2007, Index Data ApS
3  * See the file LICENSE for details.
4  *
5  * $Id: odr_oct.c,v 1.10 2007-01-03 08:42:15 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 "odr-priv.h"
16
17 /*
18  * Top level octet string en/decoder.
19  * Returns 1 on success, 0 on error.
20  */
21 int odr_octetstring(ODR o, Odr_oct **p, int opt, const char *name)
22 {
23     int res, cons = 0;
24
25     if (o->error)
26         return 0;
27     if (o->t_class < 0)
28     {
29         o->t_class = ODR_UNIVERSAL;
30         o->t_tag = ODR_OCTETSTRING;
31     }
32     if ((res = ber_tag(o, p, o->t_class, o->t_tag, &cons, opt, name)) < 0)
33         return 0;
34     if (!res)
35         return odr_missing(o, opt, name);
36     if (o->direction == ODR_PRINT)
37     {
38         odr_prname(o, name);
39         odr_printf(o, "OCTETSTRING(len=%d) ", (*p)->len);
40
41         o->op->stream_write(o, o->print, ODR_OCTETSTRING,
42                             (char*) (*p)->buf, (*p)->len);
43         odr_printf(o, "\n");
44         return 1;
45     }
46     if (o->direction == ODR_DECODE)
47     {
48         *p = (Odr_oct *)odr_malloc(o, sizeof(Odr_oct));
49         (*p)->size= 0;
50         (*p)->len = 0;
51         (*p)->buf = 0;
52     }
53     if (ber_octetstring(o, *p, cons))
54         return 1;
55     odr_seterror(o, OOTHER, 43);
56     return 0;
57 }
58
59 /*
60  * Friendlier interface to octetstring.
61  */
62 int odr_cstring(ODR o, char **p, int opt, const char *name)
63 {
64     int cons = 0, res;
65     Odr_oct *t;
66
67     if (o->error)
68         return 0;
69     if (o->t_class < 0)
70     {
71         o->t_class = ODR_UNIVERSAL;
72         o->t_tag = ODR_OCTETSTRING;
73     }
74     if ((res = ber_tag(o, p, o->t_class, o->t_tag, &cons, opt, name)) < 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->t_class < 0)
117     {
118         o->t_class = ODR_UNIVERSAL;
119         o->t_tag = ODR_OCTETSTRING;
120     }
121     if ((res = ber_tag(o, p, o->t_class, o->t_tag, &cons, opt, name)) < 0)
122         return 0;
123     if (!res)
124         return odr_missing(o, opt, name);
125     if (o->direction == ODR_PRINT)
126     {
127         odr_prname(o, name);
128         odr_printf(o, "'%s'\n", *p);
129         return 1;
130     }
131     t = (Odr_oct *)odr_malloc(o, sizeof(Odr_oct)); /* wrapper for octstring */
132     if (o->direction == ODR_ENCODE)
133     {
134         t->buf = 0;
135
136         if (o->op->iconv_handle != 0)
137         {
138             size_t inleft = strlen(*p);
139             char *inbuf = *p;
140             size_t outleft = 4 * inleft + 2;
141             char *outbuf = (char *) odr_malloc (o, outleft);
142             size_t ret;
143             
144             t->buf = (unsigned char *) outbuf;
145             
146             ret = yaz_iconv (o->op->iconv_handle, &inbuf, &inleft,
147                              &outbuf, &outleft);
148             if (ret == (size_t)(-1))
149             {
150                 odr_seterror(o, ODATA, 44);
151                 return 0;
152             }
153             t->size = t->len = outbuf - (char*) t->buf;
154         }
155         if (!t->buf)
156         {
157             t->buf = (unsigned char *) *p;
158             t->size = t->len = strlen(*p);
159         }
160     }
161     else
162     {
163         t->size= 0;
164         t->len = 0;
165         t->buf = 0;
166     }
167     if (!ber_octetstring(o, t, cons))
168         return 0;
169     if (o->direction == ODR_DECODE)
170     {
171         *p = 0;
172
173         if (o->op->iconv_handle != 0)
174         {
175             size_t inleft = t->len;
176             char *inbuf = (char *) t->buf;
177             size_t outleft = 4 * inleft + 2;
178             char *outbuf = (char *) odr_malloc (o, outleft);
179             size_t ret;
180
181             *p = outbuf;
182             
183             ret = yaz_iconv (o->op->iconv_handle, &inbuf, &inleft,
184                              &outbuf, &outleft);
185             if (ret == (size_t)(-1))
186             {
187                 odr_seterror(o, ODATA, 45);
188                 return 0;
189             }
190             inleft = outbuf - (char*) *p;
191             
192             (*p)[inleft] = '\0';    /* null terminate it */
193         }
194         if (!*p)
195         {
196             *p = (char *) t->buf;
197             *(*p + t->len) = '\0';  /* ber_octs reserves space for this */
198         }
199     }
200     return 1;
201 }
202 /*
203  * Local variables:
204  * c-basic-offset: 4
205  * indent-tabs-mode: nil
206  * End:
207  * vim: shiftwidth=4 tabstop=8 expandtab
208  */
209