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