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