Updated information about YAZ.
[yaz-moved-to-github.git] / odr / odr_cons.c
1 /*
2  * Copyright (c) 1995-1999, Index Data
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: odr_cons.c,v $
7  * Revision 1.20  1999-11-30 13:47:11  adam
8  * Improved installation. Moved header files to include/yaz.
9  *
10  * Revision 1.19  1999/04/20 09:56:48  adam
11  * Added 'name' paramter to encoder/decoder routines (typedef Odr_fun).
12  * Modified all encoders/decoders to reflect this change.
13  *
14  * Revision 1.18  1997/05/14 06:53:58  adam
15  * C++ support.
16  *
17  * Revision 1.17  1996/10/23 12:31:24  adam
18  * Added 'static' modifier to dummy variable in odr_constructed_begin.
19  *
20  * Revision 1.16  1996/07/26  13:38:20  quinn
21  * Various smaller things. Gathered header-files.
22  *
23  * Revision 1.15  1995/09/29  17:12:23  quinn
24  * Smallish
25  *
26  * Revision 1.14  1995/09/27  15:02:58  quinn
27  * Modified function heads & prototypes.
28  *
29  * Revision 1.13  1995/08/15  11:16:39  quinn
30  * Fixed pretty-printers.
31  *
32  * Revision 1.12  1995/06/19  12:38:47  quinn
33  * Added BER dumper.
34  *
35  * Revision 1.11  1995/05/16  08:50:53  quinn
36  * License, documentation, and memory fixes
37  *
38  * Revision 1.10  1995/04/18  08:15:21  quinn
39  * Added dynamic memory allocation on encoding (whew). Code is now somewhat
40  * neater. We'll make the same change for decoding one day.
41  *
42  * Revision 1.9  1995/03/28  09:15:49  quinn
43  * Fixed bug in the printing mode
44  *
45  * Revision 1.8  1995/03/15  11:18:04  quinn
46  * Fixed serious bug in odr_cons
47  *
48  * Revision 1.7  1995/03/10  11:44:41  quinn
49  * Fixed serious stack-bug in odr_cons_begin
50  *
51  * Revision 1.6  1995/03/08  12:12:23  quinn
52  * Added better error checking.
53  *
54  * Revision 1.5  1995/02/10  18:57:25  quinn
55  * More in the way of error-checking.
56  *
57  * Revision 1.4  1995/02/10  15:55:29  quinn
58  * Bug fixes, mostly.
59  *
60  * Revision 1.3  1995/02/09  15:51:48  quinn
61  * Works better now.
62  *
63  * Revision 1.2  1995/02/07  17:52:59  quinn
64  * A damn mess, but now things work, I think.
65  *
66  * Revision 1.1  1995/02/02  16:21:53  quinn
67  * First kick.
68  *
69  */
70
71 #include <assert.h>
72 #include <yaz/odr.h>
73
74 void odr_setlenlen(ODR o, int len)
75 {
76     o->lenlen = len;
77 }
78
79 int odr_constructed_begin(ODR o, void *p, int zclass, int tag,
80                           const char *name)
81 {
82     int res;
83     int cons = 1;
84     int lenlen = o->lenlen;
85
86     if (o->error)
87         return 0;
88     o->lenlen = 1; /* reset lenlen */
89     if (o->t_class < 0)
90     {
91         o->t_class = zclass;
92         o->t_tag = tag;
93     }
94     if ((res = ber_tag(o, p, o->t_class, o->t_tag, &cons, 1)) < 0)
95         return 0;
96     if (!res || !cons)
97         return 0;
98
99     if (o->stackp == ODR_MAX_STACK - 1)
100     {
101         o->error = OSTACK;
102         return 0;
103     }
104     o->stack[++(o->stackp)].lenb = o->bp;
105     o->stack[o->stackp].len_offset = odr_tell(o);
106 #ifdef ODR_DEBUG
107     fprintf(stderr, "[cons_begin(%d)]", o->stackp);
108 #endif
109     if (o->direction == ODR_ENCODE)
110     {
111         static unsigned char dummy[sizeof(int)+1];
112
113         o->stack[o->stackp].lenlen = lenlen;
114
115         if (odr_write(o, dummy, lenlen) < 0) /* dummy */
116             return 0;
117     }
118     else if (o->direction == ODR_DECODE)
119     {
120         if ((res = ber_declen(o->bp, &o->stack[o->stackp].len)) < 0)
121             return 0;
122         o->stack[o->stackp].lenlen = res;
123         o->bp += res;
124         o->left -= res;
125     }
126     else if (o->direction == ODR_PRINT)
127     {
128         odr_prname(o, name);
129         fprintf(o->print, "{\n");
130         o->indent++;
131     }
132     else
133     {
134         o->error = OOTHER;
135         return 0;
136     }
137     o->stack[o->stackp].base = o->bp;
138     o->stack[o->stackp].base_offset = odr_tell(o);
139     return 1;
140 }
141
142 int odr_constructed_more(ODR o)
143 {
144     if (o->error)
145         return 0;
146     if (o->stackp < 0)
147         return 0;
148     if (o->stack[o->stackp].len >= 0)
149         return o->bp - o->stack[o->stackp].base < o->stack[o->stackp].len;
150     else
151         return (!(*o->bp == 0 && *(o->bp + 1) == 0));
152 }
153
154 int odr_constructed_end(ODR o)
155 {
156     int res;
157     int pos;
158
159     if (o->error)
160         return 0;
161     if (o->stackp < 0)
162     {
163         o->error = OOTHER;
164         return 0;
165     }
166     switch (o->direction)
167     {
168         case ODR_DECODE:
169             if (o->stack[o->stackp].len < 0)
170             {
171                 if (*o->bp++ == 0 && *(o->bp++) == 0)
172                 {
173                     o->left -= 2;
174                     o->stackp--;
175                     return 1;
176                 }
177                 else
178                 {
179                     o->error = OOTHER;
180                     return 0;
181                 }
182             }
183             else if (o->bp - o->stack[o->stackp].base !=
184                 o->stack[o->stackp].len)
185             {
186                 o->error = OCONLEN;
187                 return 0;
188             }
189             o->stackp--;
190             return 1;
191         case ODR_ENCODE:
192             pos = odr_tell(o);
193             odr_seek(o, ODR_S_SET, o->stack[o->stackp].len_offset);
194             if ((res = ber_enclen(o, pos - o->stack[o->stackp].base_offset,
195                 o->stack[o->stackp].lenlen, 1)) < 0)
196             {
197                 o->error = OLENOV;
198                 return 0;
199             }
200             odr_seek(o, ODR_S_END, 0);
201             if (res == 0)   /* indefinite encoding */
202             {
203 #ifdef ODR_DEBUG
204                 fprintf(stderr, "[cons_end(%d): indefinite]", o->stackp);
205 #endif
206                 if (odr_putc(o, 0) < 0 || odr_putc(o, 0) < 0)
207                     return 0;
208             }
209 #ifdef ODR_DEBUG
210             else
211             {
212                 fprintf(stderr, "[cons_end(%d): definite]", o->stackp);
213             }
214 #endif
215             o->stackp--;
216             return 1;
217         case ODR_PRINT:
218             assert(o->indent > 0);
219             o->stackp--;
220             o->indent--;
221             odr_prname(o, 0);
222             fprintf(o->print, "}\n");
223             return 1;
224         default:
225             o->error = OOTHER;
226             return 0;
227     }
228 }