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