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