Added better error checking.
[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.6  1995-03-08 12:12:23  quinn
8  * Added better error checking.
9  *
10  * Revision 1.5  1995/02/10  18:57:25  quinn
11  * More in the way of error-checking.
12  *
13  * Revision 1.4  1995/02/10  15:55:29  quinn
14  * Bug fixes, mostly.
15  *
16  * Revision 1.3  1995/02/09  15:51:48  quinn
17  * Works better now.
18  *
19  * Revision 1.2  1995/02/07  17:52:59  quinn
20  * A damn mess, but now things work, I think.
21  *
22  * Revision 1.1  1995/02/02  16:21:53  quinn
23  * First kick.
24  *
25  */
26
27 #include <odr.h>
28
29 int odr_constructed_begin(ODR o, void *p, int class, int tag)
30 {
31     int res;
32     int cons = 1;
33
34     if (o->error)
35         return 0;
36     if (o->t_class < 0)
37     {
38         o->t_class = class;
39         o->t_tag = tag;
40     }
41     if ((res = ber_tag(o, p, o->t_class, o->t_tag, &cons, 1)) < 0)
42         return 0;
43     if (!res || !cons)
44         return 0;
45
46     o->stack[++(o->stackp)].lenb = o->bp;
47     if (o->direction == ODR_ENCODE || o->direction == ODR_PRINT)
48     {
49         o->stack[o->stackp].lenlen = 1;
50         o->bp++;
51         o->left--;
52     }
53     else if (o->direction == ODR_DECODE)
54     {
55         if ((res = ber_declen(o->bp, &o->stack[o->stackp].len)) < 0)
56             return 0;
57         o->stack[o->stackp].lenlen = res;
58         o->bp += res;
59         o->left -= res;
60     }
61     else return 0;
62
63     o->stack[o->stackp].base = o->bp;
64     return 1;
65 }
66
67 int odr_constructed_more(ODR o)
68 {
69     if (o->error)
70         return 0;
71     if (o->stackp < 0)
72         return 0;
73     if (o->stack[o->stackp].len >= 0)
74         return o->bp - o->stack[o->stackp].base < o->stack[o->stackp].len;
75     else
76         return (!(*o->bp == 0 && *(o->bp + 1) == 0));
77 }
78
79 int odr_constructed_end(ODR o)
80 {
81     int res;
82
83     if (o->error)
84         return 0;
85     if (o->stackp < 0)
86     {
87         o->error = OOTHER;
88         return 0;
89     }
90     switch (o->direction)
91     {
92         case ODR_DECODE:
93             if (o->stack[o->stackp].len < 0)
94             {
95                 if (*o->bp++ == 0 && *(o->bp++) == 0)
96                 {
97                     o->left -= 2;
98                     return 1;
99                 }
100                 else
101                 {
102                     o->error = OOTHER;
103                     return 0;
104                 }
105             }
106             else if (o->bp - o->stack[o->stackp].base !=
107                 o->stack[o->stackp].len)
108             {
109                 o->error = OOTHER;
110                 return 0;
111             }
112             o->stackp--;
113             return 1;
114         case ODR_ENCODE:
115             if ((res = ber_enclen(o->stack[o->stackp].lenb,
116                 o->bp - o->stack[o->stackp].base,
117                 o->stack[o->stackp].lenlen, 1)) < 0)
118             {
119                 o->error = OSPACE;
120                 return 0;
121             }
122             if (res == 0)   /* indefinite encoding */
123             {
124                 *(o->bp++) = *(o->bp++) = 0;
125                 o->left--;
126             }
127             o->stackp--;
128             return 1;
129         case ODR_PRINT: return 1;
130         default:
131             o->error = OOTHER;
132             return 0;
133     }
134 }