Bump year
[yaz-moved-to-github.git] / src / odr_cons.c
1 /*
2  * Copyright (C) 1995-2005, Index Data ApS
3  * See the file LICENSE for details.
4  *
5  * $Id: odr_cons.c,v 1.5 2005-01-15 19:47:14 adam Exp $
6  *
7  */
8
9 /**
10  * \file odr_cons.c
11  * \brief Implements ODR constructed codec.
12  */
13
14 #if HAVE_CONFIG_H
15 #include <config.h>
16 #endif
17
18 #include "odr-priv.h"
19
20 void odr_setlenlen(ODR o, int len)
21 {
22     o->lenlen = len;
23 }
24
25 int odr_constructed_begin(ODR o, void *p, int zclass, int tag,
26                           const char *name)
27 {
28     int res;
29     int cons = 1;
30     int lenlen = o->lenlen;
31
32     if (o->error)
33         return 0;
34     o->lenlen = 1; /* reset lenlen */
35     if (o->t_class < 0)
36     {
37         o->t_class = zclass;
38         o->t_tag = tag;
39     }
40     if ((res = ber_tag(o, p, o->t_class, o->t_tag, &cons, 1, name)) < 0)
41         return 0;
42     if (!res || !cons)
43         return 0;
44
45     if (o->op->stackp == ODR_MAX_STACK - 1)
46     {
47         odr_seterror(o, OSTACK, 30);
48         return 0;
49     }
50     o->op->stack[++(o->op->stackp)].lenb = o->bp;
51     o->op->stack[o->op->stackp].len_offset = odr_tell(o);
52     o->op->stack_names[o->op->stackp] = name ? name : "?";
53     o->op->stack_names[o->op->stackp + 1] = 0;
54 #ifdef ODR_DEBUG
55     fprintf(stderr, "[cons_begin(%d)]", o->op->stackp);
56 #endif
57     if (o->direction == ODR_ENCODE)
58     {
59         static unsigned char dummy[sizeof(int)+1];
60
61         o->op->stack[o->op->stackp].lenlen = lenlen;
62
63         if (odr_write(o, dummy, lenlen) < 0)  /* dummy */
64         {
65             o->op->stack_names[o->op->stackp] = 0;
66             --(o->op->stackp);
67             return 0;
68         }
69     }
70     else if (o->direction == ODR_DECODE)
71     {
72         if ((res = ber_declen(o->bp, &o->op->stack[o->op->stackp].len,
73                               odr_max(o))) < 0)
74         {
75             odr_seterror(o, OOTHER, 31);
76             o->op->stack_names[o->op->stackp] = 0;
77             --(o->op->stackp);
78             return 0;
79         }
80         o->op->stack[o->op->stackp].lenlen = res;
81         o->bp += res;
82         if (o->op->stack[o->op->stackp].len > odr_max(o))
83         {
84             odr_seterror(o, OOTHER, 32);
85             o->op->stack_names[o->op->stackp] = 0;
86             --(o->op->stackp);
87             return 0;
88         }
89     }
90     else if (o->direction == ODR_PRINT)
91     {
92         odr_prname(o, name);
93         odr_printf(o, "{\n");
94         o->indent++;
95     }
96     else
97     {
98         odr_seterror(o, OOTHER, 33);
99         o->op->stack_names[o->op->stackp] = 0;
100         --(o->op->stackp);
101         return 0;
102     }
103     o->op->stack[o->op->stackp].base = o->bp;
104     o->op->stack[o->op->stackp].base_offset = odr_tell(o);
105     return 1;
106 }
107
108 int odr_constructed_more(ODR o)
109 {
110     if (o->error)
111         return 0;
112     if (o->op->stackp < 0)
113         return 0;
114     if (o->op->stack[o->op->stackp].len >= 0)
115         return o->bp - o->op->stack[o->op->stackp].base < o->op->stack[o->op->stackp].len;
116     else
117         return (!(*o->bp == 0 && *(o->bp + 1) == 0));
118 }
119
120 int odr_constructed_end(ODR o)
121 {
122     int res;
123     int pos;
124
125     if (o->error)
126         return 0;
127     if (o->op->stackp < 0)
128     {
129         odr_seterror(o, OOTHER, 34);
130         return 0;
131     }
132     o->op->stack_names[o->op->stackp] = 0;
133     switch (o->direction)
134     {
135     case ODR_DECODE:
136         if (o->op->stack[o->op->stackp].len < 0)
137         {
138             if (*o->bp++ == 0 && *(o->bp++) == 0)
139             {
140                     o->op->stackp--;
141                     return 1;
142             }
143             else
144             {
145                 odr_seterror(o, OOTHER, 35);
146                 return 0;
147             }
148         }
149         else if (o->bp - o->op->stack[o->op->stackp].base !=
150                  o->op->stack[o->op->stackp].len)
151         {
152             odr_seterror(o, OCONLEN, 36);
153             return 0;
154         }
155         o->op->stackp--;
156         return 1;
157     case ODR_ENCODE:
158         pos = odr_tell(o);
159         odr_seek(o, ODR_S_SET, o->op->stack[o->op->stackp].len_offset);
160         if ((res = ber_enclen(o, pos - o->op->stack[o->op->stackp].base_offset,
161                               o->op->stack[o->op->stackp].lenlen, 1)) < 0)
162         {
163             odr_seterror(o, OLENOV, 37);
164             return 0;
165         }
166         odr_seek(o, ODR_S_END, 0);
167         if (res == 0)   /* indefinite encoding */
168         {
169 #ifdef ODR_DEBUG
170             fprintf(stderr, "[cons_end(%d): indefinite]", o->op->stackp);
171 #endif
172             if (odr_putc(o, 0) < 0 || odr_putc(o, 0) < 0)
173                 return 0;
174         }
175 #ifdef ODR_DEBUG
176         else
177         {
178             fprintf(stderr, "[cons_end(%d): definite]", o->op->stackp);
179         }
180 #endif
181         o->op->stackp--;
182         return 1;
183     case ODR_PRINT:
184         o->op->stackp--;
185         o->indent--;
186         odr_prname(o, 0);
187         odr_printf(o, "}\n");
188         return 1;
189     default:
190         odr_seterror(o, OOTHER, 38);
191         return 0;
192     }
193 }