Move declaration to start of block
[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.4 2004-08-13 08:58:59 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     o->bp = (unsigned char *) buf;
225
226     o->buf = (unsigned char *) buf;
227     o->can_grow = can_grow;
228     o->top = o->pos = 0;
229     o->size = len;
230 }
231
232 char *odr_getbuf(ODR o, int *len, int *size)
233 {
234     *len = o->top;
235     if (size)
236         *size = o->size;
237     return (char*) o->buf;
238 }
239
240 void odr_printf(ODR o, const char *fmt, ...)
241 {
242     va_list ap;
243     char buf[4096];
244
245     va_start(ap, fmt);
246 #ifdef WIN32
247     _vsnprintf(buf, sizeof(buf)-1, fmt, ap);
248 #else
249 #if HAVE_VSNPRINTF
250     vsnprintf(buf, sizeof(buf), fmt, ap);
251 #else
252     vsprintf(buf, fmt, ap);
253 #endif
254 #endif
255     o->op->stream_write(o, o->print, ODR_VISIBLESTRING, buf, strlen(buf));
256     va_end(ap);
257 }