odr_set_charset: allow to==from==0 to disable charset conversion
[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.42 2003-05-19 14:37:38 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     "HTTP Bad 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\n", message, odr_errlist[o->error]);
50 }
51
52 int odr_geterror(ODR o)
53 {
54     return o->error;
55 }
56
57 int odr_geterrorx(ODR o, int *x)
58 {
59     if (x)
60         *x = o->op->error_id;
61     return o->error;
62 }
63
64 void odr_seterror(ODR o, int error, int id)
65 {
66     o->error = error;
67     o->op->error_id = id;
68 }
69
70 void odr_setprint(ODR o, FILE *file)
71 {
72     o->print = file;
73 }
74
75 int odr_set_charset(ODR o, const char *to, const char *from)
76 {
77     if (o->op->iconv_handle)
78         yaz_iconv_close (o->op->iconv_handle);
79     o->op->iconv_handle = 0;
80     if (to && from)
81     {
82         o->op->iconv_handle = yaz_iconv_open (to, from);
83         if (o->op->iconv_handle == 0)
84             return -1;
85     }
86     return 0;
87 }
88
89 #include <yaz/log.h>
90
91 ODR odr_createmem(int direction)
92 {
93     ODR r;
94
95     if (!(r = (ODR)xmalloc(sizeof(*r))))
96         return 0;
97     r->direction = direction;
98     r->print = stderr;
99     r->buf = 0;
100     r->size = r->pos = r->top = 0;
101     r->can_grow = 1;
102     r->mem = nmem_create();
103     r->enable_bias = 1;
104     r->op = (struct Odr_private *) xmalloc (sizeof(*r->op));
105     r->op->odr_ber_tag.lclass = -1;
106     r->op->iconv_handle = 0;
107     odr_reset(r);
108     yaz_log (LOG_DEBUG, "odr_createmem dir=%d o=%p", direction, r);
109     return r;
110 }
111
112 void odr_reset(ODR o)
113 {
114     odr_seterror(o, ONONE, 0);
115     o->bp = o->buf;
116     odr_seek(o, ODR_S_SET, 0);
117     o->top = 0;
118     o->t_class = -1;
119     o->t_tag = -1;
120     o->indent = 0;
121     o->op->stackp = -1;
122     nmem_reset(o->mem);
123     o->choice_bias = -1;
124     o->lenlen = 1;
125     if (o->op->iconv_handle != 0)
126         yaz_iconv(o->op->iconv_handle, 0, 0, 0, 0);
127     yaz_log (LOG_DEBUG, "odr_reset o=%p", o);
128 }
129     
130 void odr_destroy(ODR o)
131 {
132     nmem_destroy(o->mem);
133     if (o->buf && o->can_grow)
134        xfree(o->buf);
135     if (o->print && o->print != stderr)
136         fclose(o->print);
137     if (o->op->iconv_handle != 0)
138         yaz_iconv_close (o->op->iconv_handle);
139     xfree(o->op);
140     xfree(o);
141     yaz_log (LOG_DEBUG, "odr_destroy o=%p", o);
142 }
143
144 void odr_setbuf(ODR o, char *buf, int len, int can_grow)
145 {
146     o->bp = (unsigned char *) buf;
147
148     o->buf = (unsigned char *) buf;
149     o->can_grow = can_grow;
150     o->top = o->pos = 0;
151     o->size = len;
152 }
153
154 char *odr_getbuf(ODR o, int *len, int *size)
155 {
156     *len = o->top;
157     if (size)
158         *size = o->size;
159     return (char*) o->buf;
160 }
161