2 * Copyright (C) 1995-2007, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: odr.c,v 1.16 2007-03-19 21:08:13 adam Exp $
11 * \brief Implements fundamental ODR functionality
23 #include <yaz/xmalloc.h>
25 #include <yaz/snprintf.h>
28 static int log_level=0;
29 static int log_level_initialized=0;
31 Odr_null *ODR_NULLVAL = (Odr_null *) "NULL"; /* the presence of a null value */
33 Odr_null *odr_nullval (void)
41 "Memory allocation failed",
44 "Required data element missing",
50 "Length of constructed type different from sum of members",
51 "Overflow writing definite length of constructed type",
55 char *odr_errmsg(int n)
57 return odr_errlist[n];
60 void odr_perror(ODR o, const char *message)
62 const char *e = odr_getelement(o);
63 const char **element_path = odr_get_element_path(o);
66 err = odr_geterrorx(o, &x);
67 fprintf(stderr, "%s: %s (code %d:%d)", message, odr_errlist[err], err, x);
69 fprintf(stderr, " element %s", e);
71 fprintf(stderr, "\n");
74 fprintf(stderr, "Element path:");
76 fprintf(stderr, " %s", *element_path++);
77 fprintf(stderr, "\n");
81 int odr_geterror(ODR o)
86 int odr_geterrorx(ODR o, int *x)
93 const char *odr_getelement(ODR o)
95 return o->op->element;
98 const char **odr_get_element_path(ODR o)
101 struct odr_constack *st;
103 for (st = o->op->stack_top; st; st = st->prev)
105 if (o->op->tmp_names_sz < cur_sz + 1)
107 o->op->tmp_names_sz = 2 * cur_sz + 5;
108 o->op->tmp_names_buf = (const char **)
109 odr_malloc(o, o->op->tmp_names_sz * sizeof(char*));
111 o->op->tmp_names_buf[cur_sz] = 0;
112 for (st = o->op->stack_top; st; st = st->prev)
115 o->op->tmp_names_buf[cur_sz] = st->name;
118 return o->op->tmp_names_buf;
121 void odr_seterror(ODR o, int error, int id)
124 o->op->error_id = id;
125 o->op->element[0] = '\0';
128 void odr_setelement(ODR o, const char *element)
132 strncpy(o->op->element, element, sizeof(o->op->element)-1);
133 o->op->element[sizeof(o->op->element)-1] = '\0';
137 void odr_FILE_write(ODR o, void *handle, int type,
138 const char *buf, int len)
142 if (type == ODR_OCTETSTRING)
144 const char **stack_names = odr_get_element_path(o);
145 for (i = 0; stack_names[i]; i++)
146 fprintf((FILE*) handle, "[%s]", stack_names[i]);
147 fputs("\n", (FILE*) handle);
150 for (i = 0; i<len; i++)
152 unsigned c = ((const unsigned char *) buf)[i];
153 if (i == 2000 && len > 3100)
155 fputs(" ..... ", (FILE*) handle);
158 if (strchr("\r\n\f\t", c) || (c >= ' ' && c <= 126))
159 putc(c, (FILE*) handle);
163 sprintf(x, "\\X%02X", c);
164 fputs(x, (FILE*) handle);
169 void odr_FILE_close(void *handle)
171 FILE *f = (FILE *) handle;
172 if (f && f != stderr && f != stdout)
176 void odr_setprint(ODR o, FILE *file)
178 odr_set_stream(o, file, odr_FILE_write, odr_FILE_close);
181 void odr_set_stream(ODR o, void *handle,
182 void (*stream_write)(ODR o,
183 void *handle, int type,
184 const char *buf, int len),
185 void (*stream_close)(void *handle))
187 o->op->print = (FILE*) handle;
188 o->op->stream_write = stream_write;
189 o->op->stream_close = stream_close;
192 int odr_set_charset(ODR o, const char *to, const char *from)
194 if (o->op->iconv_handle)
195 yaz_iconv_close (o->op->iconv_handle);
196 o->op->iconv_handle = 0;
199 o->op->iconv_handle = yaz_iconv_open (to, from);
200 if (o->op->iconv_handle == 0)
207 ODR odr_createmem(int direction)
210 if (!log_level_initialized)
212 log_level=yaz_log_module_level("odr");
213 log_level_initialized=1;
216 if (!(o = (ODR)xmalloc(sizeof(*o))))
218 o->op = (struct Odr_private *) xmalloc (sizeof(*o->op));
219 o->direction = direction;
221 o->size = o->pos = o->top = 0;
223 o->mem = nmem_create();
224 o->op->enable_bias = 1;
225 o->op->odr_ber_tag.lclass = -1;
226 o->op->iconv_handle = 0;
227 odr_setprint(o, stderr);
229 yaz_log (log_level, "odr_createmem dir=%d o=%p", direction, o);
233 void odr_reset(ODR o)
235 if (!log_level_initialized)
237 log_level=yaz_log_module_level("odr");
238 log_level_initialized=1;
241 odr_seterror(o, ONONE, 0);
243 odr_seek(o, ODR_S_SET, 0);
248 o->op->stack_first = 0;
249 o->op->stack_top = 0;
250 o->op->tmp_names_sz = 0;
251 o->op->tmp_names_buf = 0;
253 o->op->choice_bias = -1;
255 if (o->op->iconv_handle != 0)
256 yaz_iconv(o->op->iconv_handle, 0, 0, 0, 0);
257 yaz_log (log_level, "odr_reset o=%p", o);
260 void odr_destroy(ODR o)
262 nmem_destroy(o->mem);
263 if (o->buf && o->op->can_grow)
265 if (o->op->stream_close)
266 o->op->stream_close(o->op->print);
267 if (o->op->iconv_handle != 0)
268 yaz_iconv_close (o->op->iconv_handle);
271 yaz_log (log_level, "odr_destroy o=%p", o);
274 void odr_setbuf(ODR o, char *buf, int len, int can_grow)
276 odr_seterror(o, ONONE, 0);
277 o->bp = (unsigned char *) buf;
279 o->buf = (unsigned char *) buf;
280 o->op->can_grow = can_grow;
285 char *odr_getbuf(ODR o, int *len, int *size)
290 return (char*) o->buf;
293 void odr_printf(ODR o, const char *fmt, ...)
299 yaz_vsnprintf(buf, sizeof(buf), fmt, ap);
300 o->op->stream_write(o, o->op->print, ODR_VISIBLESTRING, buf, strlen(buf));
306 * indent-tabs-mode: nil
308 * vim: shiftwidth=4 tabstop=8 expandtab