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