TCPD libs only used in libyaz's LIBADD
[yaz-moved-to-github.git] / src / odr_cons.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2010 Index Data
3  * See the file LICENSE for details.
4  */
5
6 /**
7  * \file odr_cons.c
8  * \brief Implements ODR constructed codec.
9  */
10
11 #if HAVE_CONFIG_H
12 #include <config.h>
13 #endif
14
15 #include <assert.h>
16
17 #include "odr-priv.h"
18
19 void odr_setlenlen(ODR o, int len)
20 {
21     o->op->lenlen = len;
22 }
23
24 int odr_constructed_begin(ODR o, void *xxp, int zclass, int tag,
25                           const char *name)
26 {
27     int res;
28     int cons = 1;
29     int lenlen = o->op->lenlen;
30
31     if (o->error)
32         return 0;
33     o->op->lenlen = 1; /* reset lenlen */
34     if (o->op->t_class < 0)
35     {
36         o->op->t_class = zclass;
37         o->op->t_tag = tag;
38     }
39     res = ber_tag(o, xxp, o->op->t_class, o->op->t_tag, &cons, 1, name);
40     if (res < 0)
41         return 0;
42     if (!res || !cons)
43         return 0;
44
45     /* push the odr_constack */
46     if (o->op->stack_top && o->op->stack_top->next)
47     {
48         /* reuse old entry */
49         o->op->stack_top = o->op->stack_top->next;
50     }
51     else if (o->op->stack_top && !o->op->stack_top->next)
52     {
53         /* must allocate new entry (not first) */
54         int sz = 0;
55         struct odr_constack *st;
56         /* check size first */
57         for (st = o->op->stack_top; st; st = st->prev)
58             sz++;
59
60         if (sz >= ODR_MAX_STACK)
61         {
62             odr_seterror(o, OSTACK, 30);
63             return 0;
64         }
65         o->op->stack_top->next = (struct odr_constack *)
66             odr_malloc(o, sizeof(*o->op->stack_top));
67         o->op->stack_top->next->prev = o->op->stack_top;
68         o->op->stack_top->next->next = 0;
69
70         o->op->stack_top = o->op->stack_top->next;
71     }
72     else if (!o->op->stack_top)
73     {
74         /* stack empty */
75         if (!o->op->stack_first)
76         {
77             /* first item must be allocated */
78             o->op->stack_first = (struct odr_constack *)
79                 odr_malloc(o, sizeof(*o->op->stack_top));
80             o->op->stack_first->prev = 0;
81             o->op->stack_first->next = 0;
82         }
83         o->op->stack_top = o->op->stack_first;
84         assert(o->op->stack_top->prev == 0);
85     }
86     o->op->stack_top->lenb = o->bp;
87     o->op->stack_top->len_offset = odr_tell(o);
88     o->op->stack_top->name = name ? name : "?";
89     if (o->direction == ODR_ENCODE)
90     {
91         static unsigned char dummy[sizeof(int)+1];
92
93         o->op->stack_top->lenlen = lenlen;
94
95         if (odr_write(o, dummy, lenlen) < 0)  /* dummy */
96         {
97             ODR_STACK_POP(o);
98             return 0;
99         }
100     }
101     else if (o->direction == ODR_DECODE)
102     {
103         if ((res = ber_declen(o->bp, &o->op->stack_top->len,
104                               odr_max(o))) < 0)
105         {
106             odr_seterror(o, OOTHER, 31);
107             ODR_STACK_POP(o);
108             return 0;
109         }
110         o->op->stack_top->lenlen = res;
111         o->bp += res;
112         if (o->op->stack_top->len > odr_max(o))
113         {
114             odr_seterror(o, OOTHER, 32);
115             ODR_STACK_POP(o);
116             return 0;
117         }
118     }
119     else if (o->direction == ODR_PRINT)
120     {
121         odr_prname(o, name);
122         odr_printf(o, "{\n");
123         o->op->indent++;
124     }
125     else
126     {
127         odr_seterror(o, OOTHER, 33);
128         ODR_STACK_POP(o);
129         return 0;
130     }
131     o->op->stack_top->base = o->bp;
132     o->op->stack_top->base_offset = odr_tell(o);
133     return 1;
134 }
135
136 int odr_constructed_more(ODR o)
137 {
138     if (o->error)
139         return 0;
140     if (ODR_STACK_EMPTY(o))
141         return 0;
142     if (o->op->stack_top->len >= 0)
143         return o->bp - o->op->stack_top->base < o->op->stack_top->len;
144     else
145         return (!(*o->bp == 0 && *(o->bp + 1) == 0));
146 }
147
148 int odr_constructed_end(ODR o)
149 {
150     int res;
151     int pos;
152
153     if (o->error)
154         return 0;
155     if (ODR_STACK_EMPTY(o))
156     {
157         odr_seterror(o, OOTHER, 34);
158         return 0;
159     }
160     switch (o->direction)
161     {
162     case ODR_DECODE:
163         if (o->op->stack_top->len < 0)
164         {
165             if (*o->bp++ == 0 && *(o->bp++) == 0)
166             {
167                 ODR_STACK_POP(o);
168                 return 1;
169             }
170             else
171             {
172                 odr_seterror(o, OOTHER, 35);
173                 return 0;
174             }
175         }
176         else if (o->bp - o->op->stack_top->base !=
177                  o->op->stack_top->len)
178         {
179             odr_seterror(o, OCONLEN, 36);
180             return 0;
181         }
182         ODR_STACK_POP(o);
183         return 1;
184     case ODR_ENCODE:
185         pos = odr_tell(o);
186         odr_seek(o, ODR_S_SET, o->op->stack_top->len_offset);
187         if ((res = ber_enclen(o, pos - o->op->stack_top->base_offset,
188                               o->op->stack_top->lenlen, 1)) < 0)
189         {
190             odr_seterror(o, OLENOV, 37);
191             return 0;
192         }
193         odr_seek(o, ODR_S_END, 0);
194         if (res == 0)   /* indefinite encoding */
195         {
196             if (odr_putc(o, 0) < 0 || odr_putc(o, 0) < 0)
197                 return 0;
198         }
199         ODR_STACK_POP(o);
200         return 1;
201     case ODR_PRINT:
202         ODR_STACK_POP(o);
203         o->op->indent--;
204         odr_prname(o, 0);
205         odr_printf(o, "}\n");
206         return 1;
207     default:
208         odr_seterror(o, OOTHER, 38);
209         return 0;
210     }
211 }
212 /*
213  * Local variables:
214  * c-basic-offset: 4
215  * c-file-style: "Stroustrup"
216  * indent-tabs-mode: nil
217  * End:
218  * vim: shiftwidth=4 tabstop=8 expandtab
219  */
220