1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2008 Index Data
3 * See the file LICENSE for details.
8 * \brief Implements fundamental ODR functionality
20 #include <yaz/xmalloc.h>
22 #include <yaz/snprintf.h>
25 static int log_level=0;
26 static int log_level_initialized=0;
28 Odr_null *ODR_NULLVAL = (Odr_null *) "NULL"; /* the presence of a null value */
30 Odr_null *odr_nullval (void)
38 "Memory allocation failed",
41 "Required data element missing",
47 "Length of constructed type different from sum of members",
48 "Overflow writing definite length of constructed type",
52 char *odr_errmsg(int n)
54 return odr_errlist[n];
57 void odr_perror(ODR o, const char *message)
59 const char *e = odr_getelement(o);
60 const char **element_path = odr_get_element_path(o);
63 err = odr_geterrorx(o, &x);
64 fprintf(stderr, "%s: %s (code %d:%d)", message, odr_errlist[err], err, x);
66 fprintf(stderr, " element %s", e);
68 fprintf(stderr, "\n");
71 fprintf(stderr, "Element path:");
73 fprintf(stderr, " %s", *element_path++);
74 fprintf(stderr, "\n");
78 int odr_geterror(ODR o)
83 int odr_geterrorx(ODR o, int *x)
90 const char *odr_getelement(ODR o)
92 return o->op->element;
95 const char **odr_get_element_path(ODR o)
98 struct odr_constack *st;
100 for (st = o->op->stack_top; st; st = st->prev)
102 if (o->op->tmp_names_sz < cur_sz + 1)
104 o->op->tmp_names_sz = 2 * cur_sz + 5;
105 o->op->tmp_names_buf = (const char **)
106 odr_malloc(o, o->op->tmp_names_sz * sizeof(char*));
108 o->op->tmp_names_buf[cur_sz] = 0;
109 for (st = o->op->stack_top; st; st = st->prev)
112 o->op->tmp_names_buf[cur_sz] = st->name;
115 return o->op->tmp_names_buf;
118 void odr_seterror(ODR o, int error, int id)
121 o->op->error_id = id;
122 o->op->element[0] = '\0';
125 void odr_setelement(ODR o, const char *element)
129 strncpy(o->op->element, element, sizeof(o->op->element)-1);
130 o->op->element[sizeof(o->op->element)-1] = '\0';
134 void odr_FILE_write(ODR o, void *handle, int type,
135 const char *buf, int len)
139 if (type == ODR_OCTETSTRING)
141 const char **stack_names = odr_get_element_path(o);
142 for (i = 0; stack_names[i]; i++)
143 fprintf((FILE*) handle, "[%s]", stack_names[i]);
144 fputs("\n", (FILE*) handle);
147 for (i = 0; i<len; i++)
149 unsigned c = ((const unsigned char *) buf)[i];
150 if (i == 2000 && len > 3100)
152 fputs(" ..... ", (FILE*) handle);
155 if (strchr("\r\n\f\t", c) || (c >= ' ' && c <= 126))
156 putc(c, (FILE*) handle);
160 sprintf(x, "\\X%02X", c);
161 fputs(x, (FILE*) handle);
166 void odr_FILE_close(void *handle)
168 FILE *f = (FILE *) handle;
169 if (f && f != stderr && f != stdout)
173 void odr_setprint(ODR o, FILE *file)
175 odr_set_stream(o, file, odr_FILE_write, odr_FILE_close);
178 void odr_set_stream(ODR o, void *handle,
179 void (*stream_write)(ODR o,
180 void *handle, int type,
181 const char *buf, int len),
182 void (*stream_close)(void *handle))
184 o->op->print = (FILE*) handle;
185 o->op->stream_write = stream_write;
186 o->op->stream_close = stream_close;
189 int odr_set_charset(ODR o, const char *to, const char *from)
191 if (o->op->iconv_handle)
192 yaz_iconv_close (o->op->iconv_handle);
193 o->op->iconv_handle = 0;
196 o->op->iconv_handle = yaz_iconv_open (to, from);
197 if (o->op->iconv_handle == 0)
204 ODR odr_createmem(int direction)
207 if (!log_level_initialized)
209 log_level=yaz_log_module_level("odr");
210 log_level_initialized=1;
213 if (!(o = (ODR)xmalloc(sizeof(*o))))
215 o->op = (struct Odr_private *) xmalloc (sizeof(*o->op));
216 o->direction = direction;
218 o->size = o->pos = o->top = 0;
220 o->mem = nmem_create();
221 o->op->enable_bias = 1;
222 o->op->odr_ber_tag.lclass = -1;
223 o->op->iconv_handle = 0;
224 odr_setprint(o, stderr);
226 yaz_log (log_level, "odr_createmem dir=%d o=%p", direction, o);
230 void odr_reset(ODR o)
232 if (!log_level_initialized)
234 log_level=yaz_log_module_level("odr");
235 log_level_initialized=1;
238 odr_seterror(o, ONONE, 0);
240 odr_seek(o, ODR_S_SET, 0);
245 o->op->stack_first = 0;
246 o->op->stack_top = 0;
247 o->op->tmp_names_sz = 0;
248 o->op->tmp_names_buf = 0;
250 o->op->choice_bias = -1;
252 if (o->op->iconv_handle != 0)
253 yaz_iconv(o->op->iconv_handle, 0, 0, 0, 0);
254 yaz_log (log_level, "odr_reset o=%p", o);
257 void odr_destroy(ODR o)
259 nmem_destroy(o->mem);
260 if (o->buf && o->op->can_grow)
262 if (o->op->stream_close)
263 o->op->stream_close(o->op->print);
264 if (o->op->iconv_handle != 0)
265 yaz_iconv_close (o->op->iconv_handle);
268 yaz_log (log_level, "odr_destroy o=%p", o);
271 void odr_setbuf(ODR o, char *buf, int len, int can_grow)
273 odr_seterror(o, ONONE, 0);
274 o->bp = (unsigned char *) buf;
276 o->buf = (unsigned char *) buf;
277 o->op->can_grow = can_grow;
282 char *odr_getbuf(ODR o, int *len, int *size)
287 return (char*) o->buf;
290 void odr_printf(ODR o, const char *fmt, ...)
296 yaz_vsnprintf(buf, sizeof(buf), fmt, ap);
297 o->op->stream_write(o, o->op->print, ODR_VISIBLESTRING, buf, strlen(buf));
303 * indent-tabs-mode: nil
305 * vim: shiftwidth=4 tabstop=8 expandtab