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