1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 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)
138 for (i = 0; i < len; i++)
140 unsigned c = ((const unsigned char *) buf)[i];
141 if (i == 20000 && len > 31000)
143 fputs(" ..... ", (FILE*) handle);
146 if (strchr("\r\n\f\t", c) || (c >= ' ' && c <= 126))
147 putc(c, (FILE*) handle);
151 sprintf(x, "\\X%02X", c);
152 fputs(x, (FILE*) handle);
157 void odr_FILE_close(void *handle)
159 FILE *f = (FILE *) handle;
160 if (f && f != stderr && f != stdout)
164 void odr_setprint(ODR o, FILE *file)
166 odr_set_stream(o, file, odr_FILE_write, odr_FILE_close);
169 void odr_setprint_noclose(ODR o, FILE *file)
171 odr_set_stream(o, file, odr_FILE_write, 0);
174 void odr_set_stream(ODR o, void *handle,
175 void (*stream_write)(ODR o,
176 void *handle, int type,
177 const char *buf, int len),
178 void (*stream_close)(void *handle))
180 o->op->print = (FILE*) handle;
181 o->op->stream_write = stream_write;
182 o->op->stream_close = stream_close;
185 int odr_set_charset(ODR o, const char *to, const char *from)
187 if (o->op->iconv_handle)
188 yaz_iconv_close (o->op->iconv_handle);
189 o->op->iconv_handle = 0;
192 o->op->iconv_handle = yaz_iconv_open(to, from);
193 if (o->op->iconv_handle == 0)
200 ODR odr_createmem(int direction)
203 if (!log_level_initialized)
205 log_level = yaz_log_module_level("odr");
206 log_level_initialized = 1;
209 if (!(o = (ODR) xmalloc(sizeof(*o))))
211 o->op = (struct Odr_private *) xmalloc(sizeof(*o->op));
212 o->direction = direction;
214 o->op->size = o->op->pos = o->op->top = 0;
216 o->mem = nmem_create();
217 o->op->enable_bias = 1;
218 o->op->odr_ber_tag.lclass = -1;
219 o->op->iconv_handle = 0;
220 odr_setprint_noclose(o, stderr);
222 yaz_log(log_level, "odr_createmem dir=%d o=%p", direction, o);
226 void odr_reset(ODR o)
228 if (!log_level_initialized)
230 log_level = yaz_log_module_level("odr");
231 log_level_initialized = 1;
234 odr_seterror(o, ONONE, 0);
235 o->op->bp = o->op->buf;
236 odr_seek(o, ODR_S_SET, 0);
241 o->op->stack_first = 0;
242 o->op->stack_top = 0;
243 o->op->tmp_names_sz = 0;
244 o->op->tmp_names_buf = 0;
246 o->op->choice_bias = -1;
248 if (o->op->iconv_handle != 0)
249 yaz_iconv(o->op->iconv_handle, 0, 0, 0, 0);
250 yaz_log(log_level, "odr_reset o=%p", o);
253 void odr_destroy(ODR o)
255 nmem_destroy(o->mem);
256 if (o->op->buf && o->op->can_grow)
258 if (o->op->stream_close)
259 o->op->stream_close(o->op->print);
260 if (o->op->iconv_handle != 0)
261 yaz_iconv_close(o->op->iconv_handle);
264 yaz_log(log_level, "odr_destroy o=%p", o);
267 void odr_setbuf(ODR o, char *buf, int len, int can_grow)
269 odr_seterror(o, ONONE, 0);
272 o->op->can_grow = can_grow;
273 o->op->top = o->op->pos = 0;
277 char *odr_getbuf(ODR o, int *len, int *size)
285 int odr_offset(ODR o)
287 return o->op->bp - o->op->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 * c-file-style: "Stroustrup"
304 * indent-tabs-mode: nil
306 * vim: shiftwidth=4 tabstop=8 expandtab