Better ODR diagnostics for missing elements which includes additional
[yaz-moved-to-github.git] / odr / odr.c
1 /*
2  * Copyright (c) 1995-2003, Index Data
3  * See the file LICENSE for details.
4  *
5  * $Id: odr.c,v 1.43 2003-05-20 19:55:29 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
15 #include <yaz/xmalloc.h>
16 #include "odr-priv.h"
17
18 Odr_null *ODR_NULLVAL = (Odr_null *) "NULL";  /* the presence of a null value */
19
20 Odr_null *odr_nullval (void)
21 {
22     return ODR_NULLVAL;
23 }
24
25 char *odr_errlist[] =
26 {
27     "No (unknown) error",
28     "Memory allocation failed",
29     "System error",
30     "No space in buffer",
31     "Required data element missing",
32     "Unexpected tag",
33     "Other error",
34     "Protocol error",
35     "Malformed data",
36     "Stack overflow",
37     "Length of constructed type different from sum of members",
38     "Overflow writing definite length of constructed type",
39     "Bad HTTP Request"
40 };
41
42 char *odr_errmsg(int n)
43 {
44     return odr_errlist[n];
45 }
46
47 void odr_perror(ODR o, char *message)
48 {
49     fprintf(stderr, "%s: %s: %s\n", message, odr_errlist[o->error],
50             odr_getaddinfo(o));
51 }
52
53 int odr_geterror(ODR o)
54 {
55     return o->error;
56 }
57
58 int odr_geterrorx(ODR o, int *x)
59 {
60     if (x)
61         *x = o->op->error_id;
62     return o->error;
63 }
64
65 char *odr_getaddinfo(ODR o)
66 {
67     return o->op->addinfo;
68 }
69
70 void odr_seterror(ODR o, int error, int id)
71 {
72     o->error = error;
73     o->op->error_id = id;
74     o->op->addinfo[0] = '\0';
75 }
76
77 void odr_setaddinfo(ODR o, const char *addinfo)
78 {
79     if (addinfo)
80     {
81         strncpy(o->op->addinfo, addinfo, sizeof(o->op->addinfo)-1);
82         o->op->addinfo[sizeof(o->op->addinfo)-1] = '\0';
83     }
84 }
85
86 void odr_setprint(ODR o, FILE *file)
87 {
88     o->print = file;
89 }
90
91 int odr_set_charset(ODR o, const char *to, const char *from)
92 {
93     if (o->op->iconv_handle)
94         yaz_iconv_close (o->op->iconv_handle);
95     o->op->iconv_handle = 0;
96     if (to && from)
97     {
98         o->op->iconv_handle = yaz_iconv_open (to, from);
99         if (o->op->iconv_handle == 0)
100             return -1;
101     }
102     return 0;
103 }
104
105 #include <yaz/log.h>
106
107 ODR odr_createmem(int direction)
108 {
109     ODR r;
110
111     if (!(r = (ODR)xmalloc(sizeof(*r))))
112         return 0;
113     r->direction = direction;
114     r->print = stderr;
115     r->buf = 0;
116     r->size = r->pos = r->top = 0;
117     r->can_grow = 1;
118     r->mem = nmem_create();
119     r->enable_bias = 1;
120     r->op = (struct Odr_private *) xmalloc (sizeof(*r->op));
121     r->op->odr_ber_tag.lclass = -1;
122     r->op->iconv_handle = 0;
123     odr_reset(r);
124     yaz_log (LOG_DEBUG, "odr_createmem dir=%d o=%p", direction, r);
125     return r;
126 }
127
128 void odr_reset(ODR o)
129 {
130     odr_seterror(o, ONONE, 0);
131     o->bp = o->buf;
132     odr_seek(o, ODR_S_SET, 0);
133     o->top = 0;
134     o->t_class = -1;
135     o->t_tag = -1;
136     o->indent = 0;
137     o->op->stackp = -1;
138     nmem_reset(o->mem);
139     o->choice_bias = -1;
140     o->lenlen = 1;
141     if (o->op->iconv_handle != 0)
142         yaz_iconv(o->op->iconv_handle, 0, 0, 0, 0);
143     yaz_log (LOG_DEBUG, "odr_reset o=%p", o);
144 }
145     
146 void odr_destroy(ODR o)
147 {
148     nmem_destroy(o->mem);
149     if (o->buf && o->can_grow)
150        xfree(o->buf);
151     if (o->print && o->print != stderr)
152         fclose(o->print);
153     if (o->op->iconv_handle != 0)
154         yaz_iconv_close (o->op->iconv_handle);
155     xfree(o->op);
156     xfree(o);
157     yaz_log (LOG_DEBUG, "odr_destroy o=%p", o);
158 }
159
160 void odr_setbuf(ODR o, char *buf, int len, int can_grow)
161 {
162     o->bp = (unsigned char *) buf;
163
164     o->buf = (unsigned char *) buf;
165     o->can_grow = can_grow;
166     o->top = o->pos = 0;
167     o->size = len;
168 }
169
170 char *odr_getbuf(ODR o, int *len, int *size)
171 {
172     *len = o->top;
173     if (size)
174         *size = o->size;
175     return (char*) o->buf;
176 }
177