Added ()s to avoid warning.
[yaz-moved-to-github.git] / src / odr.c
1 /*
2  * Copyright (c) 1995-2004, Index Data
3  * See the file LICENSE for details.
4  *
5  * $Id: odr.c,v 1.6 2004-10-01 13:16:18 adam Exp $
6  *
7  */
8 #if HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <stdarg.h>
15
16 #include <yaz/xmalloc.h>
17 #include "odr-priv.h"
18
19 Odr_null *ODR_NULLVAL = (Odr_null *) "NULL";  /* the presence of a null value */
20
21 Odr_null *odr_nullval (void)
22 {
23     return ODR_NULLVAL;
24 }
25
26 char *odr_errlist[] =
27 {
28     "No (unknown) error",
29     "Memory allocation failed",
30     "System error",
31     "No space in buffer",
32     "Required data element missing",
33     "Unexpected tag",
34     "Other error",
35     "Protocol error",
36     "Malformed data",
37     "Stack overflow",
38     "Length of constructed type different from sum of members",
39     "Overflow writing definite length of constructed type",
40     "Bad HTTP Request"
41 };
42
43 char *odr_errmsg(int n)
44 {
45     return odr_errlist[n];
46 }
47
48 void odr_perror(ODR o, const char *message)
49 {
50     const char *e = odr_getelement(o);
51     int err, x;
52
53     err =  odr_geterrorx(o, &x);
54     fprintf(stderr, "%s: %s (code %d:%d)", message, odr_errlist[err], err, x);
55     if (e && *e)
56         fprintf (stderr, " element %s", e);
57     fprintf(stderr, "\n");
58 }
59
60 int odr_geterror(ODR o)
61 {
62     return o->error;
63 }
64
65 int odr_geterrorx(ODR o, int *x)
66 {
67     if (x)
68         *x = o->op->error_id;
69     return o->error;
70 }
71
72 const char *odr_getelement(ODR o)
73 {
74     return o->op->element;
75 }
76
77 const char **odr_get_element_path(ODR o)
78 {
79     return o->op->stack_names;
80 }
81
82 void odr_seterror(ODR o, int error, int id)
83 {
84     o->error = error;
85     o->op->error_id = id;
86     o->op->element[0] = '\0';
87 }
88
89 void odr_setelement(ODR o, const char *element)
90 {
91     if (element)
92     {
93         strncpy(o->op->element, element, sizeof(o->op->element)-1);
94         o->op->element[sizeof(o->op->element)-1] = '\0';
95     }
96 }
97
98 void odr_FILE_write(ODR o, void *handle, int type,
99                     const char *buf, int len)
100 {
101     int i;
102 #if 0
103     if (type  == ODR_OCTETSTRING)
104     {
105         const char **stack_names = odr_get_element_path(o);
106         for (i = 0; stack_names[i]; i++)
107             fprintf((FILE*) handle, "[%s]", stack_names[i]);
108         fputs("\n", (FILE*) handle);
109     }
110 #endif
111     for (i = 0; i<len; i++)
112     {
113         unsigned c = ((const unsigned char *) buf)[i];
114         if (i == 2000 && len > 3100)
115         {
116             fputs(" ..... ", (FILE*) handle);
117                 i = len - 1000;
118         }
119         if (strchr("\r\n\f\t", c) || (c >= ' ' && c <= 126))
120             putc(c, (FILE*) handle);
121         else
122         {
123             char x[5];
124             sprintf(x, "\\X%02X", c);
125             fputs(x, (FILE*) handle);
126         }
127     }
128 }
129
130 void odr_FILE_close(void *handle)
131 {
132     FILE *f = (FILE *) handle;
133     if (f && f != stderr && f != stdout)
134         fclose(f);
135 }
136
137 void odr_setprint(ODR o, FILE *file)
138 {
139     odr_set_stream(o, file, odr_FILE_write, odr_FILE_close);
140 }
141
142 void odr_set_stream(ODR o, void *handle,
143                     void (*stream_write)(ODR o, 
144                                          void *handle, int type,
145                                          const char *buf, int len),
146                     void (*stream_close)(void *handle))
147 {
148     o->print = handle;
149     o->op->stream_write = stream_write;
150     o->op->stream_close = stream_close;
151 }
152
153 int odr_set_charset(ODR o, const char *to, const char *from)
154 {
155     if (o->op->iconv_handle)
156         yaz_iconv_close (o->op->iconv_handle);
157     o->op->iconv_handle = 0;
158     if (to && from)
159     {
160         o->op->iconv_handle = yaz_iconv_open (to, from);
161         if (o->op->iconv_handle == 0)
162             return -1;
163     }
164     return 0;
165 }
166
167 #include <yaz/log.h>
168
169 ODR odr_createmem(int direction)
170 {
171     ODR o;
172
173     if (!(o = (ODR)xmalloc(sizeof(*o))))
174         return 0;
175     o->direction = direction;
176     o->buf = 0;
177     o->size = o->pos = o->top = 0;
178     o->can_grow = 1;
179     o->mem = nmem_create();
180     o->enable_bias = 1;
181     o->op = (struct Odr_private *) xmalloc (sizeof(*o->op));
182     o->op->odr_ber_tag.lclass = -1;
183     o->op->iconv_handle = 0;
184     odr_setprint(o, stderr);
185     odr_reset(o);
186     yaz_log (LOG_DEBUG, "odr_createmem dir=%d o=%p", direction, o);
187     return o;
188 }
189
190 void odr_reset(ODR o)
191 {
192     odr_seterror(o, ONONE, 0);
193     o->bp = o->buf;
194     odr_seek(o, ODR_S_SET, 0);
195     o->top = 0;
196     o->t_class = -1;
197     o->t_tag = -1;
198     o->indent = 0;
199     o->op->stackp = -1;
200     nmem_reset(o->mem);
201     o->choice_bias = -1;
202     o->lenlen = 1;
203     if (o->op->iconv_handle != 0)
204         yaz_iconv(o->op->iconv_handle, 0, 0, 0, 0);
205     yaz_log (LOG_DEBUG, "odr_reset o=%p", o);
206 }
207     
208 void odr_destroy(ODR o)
209 {
210     nmem_destroy(o->mem);
211     if (o->buf && o->can_grow)
212        xfree(o->buf);
213     if (o->op->stream_close)
214         o->op->stream_close(o->print);
215     if (o->op->iconv_handle != 0)
216         yaz_iconv_close (o->op->iconv_handle);
217     xfree(o->op);
218     xfree(o);
219     yaz_log (LOG_DEBUG, "odr_destroy o=%p", o);
220 }
221
222 void odr_setbuf(ODR o, char *buf, int len, int can_grow)
223 {
224     odr_seterror(o, ONONE, 0);
225     o->bp = (unsigned char *) buf;
226
227     o->buf = (unsigned char *) buf;
228     o->can_grow = can_grow;
229     o->top = o->pos = 0;
230     o->size = len;
231 }
232
233 char *odr_getbuf(ODR o, int *len, int *size)
234 {
235     *len = o->top;
236     if (size)
237         *size = o->size;
238     return (char*) o->buf;
239 }
240
241 void odr_printf(ODR o, const char *fmt, ...)
242 {
243     va_list ap;
244     char buf[4096];
245
246     va_start(ap, fmt);
247 #ifdef WIN32
248     _vsnprintf(buf, sizeof(buf)-1, fmt, ap);
249 #else
250 #if HAVE_VSNPRINTF
251     vsnprintf(buf, sizeof(buf), fmt, ap);
252 #else
253     vsprintf(buf, fmt, ap);
254 #endif
255 #endif
256     o->op->stream_write(o, o->print, ODR_VISIBLESTRING, buf, strlen(buf));
257     va_end(ap);
258 }