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