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