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