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