Source restructure. yaz-marcdump part of installation
[yaz-moved-to-github.git] / src / 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.1 2003-10-27 12:21:33 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, name)) < 0)
35         return 0;
36     if (!res || !cons)
37         return 0;
38
39     if (o->op->stackp == ODR_MAX_STACK - 1)
40     {
41         odr_seterror(o, OSTACK, 30);
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         {
57             --(o->op->stackp);
58             return 0;
59         }
60     }
61     else if (o->direction == ODR_DECODE)
62     {
63         if ((res = ber_declen(o->bp, &o->op->stack[o->op->stackp].len,
64                               odr_max(o))) < 0)
65         {
66             odr_seterror(o, OOTHER, 31);
67             --(o->op->stackp);
68             return 0;
69         }
70         o->op->stack[o->op->stackp].lenlen = res;
71         o->bp += res;
72         if (o->op->stack[o->op->stackp].len > odr_max(o))
73         {
74             odr_seterror(o, OOTHER, 32);
75             --(o->op->stackp);
76             return 0;
77         }
78     }
79     else if (o->direction == ODR_PRINT)
80     {
81         odr_prname(o, name);
82         fprintf(o->print, "{\n");
83         o->indent++;
84     }
85     else
86     {
87         odr_seterror(o, OOTHER, 33);
88         --(o->op->stackp);
89         return 0;
90     }
91     o->op->stack[o->op->stackp].base = o->bp;
92     o->op->stack[o->op->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->op->stackp < 0)
101         return 0;
102     if (o->op->stack[o->op->stackp].len >= 0)
103         return o->bp - o->op->stack[o->op->stackp].base < o->op->stack[o->op->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->op->stackp < 0)
116     {
117         odr_seterror(o, OOTHER, 34);
118         return 0;
119     }
120     switch (o->direction)
121     {
122     case ODR_DECODE:
123         if (o->op->stack[o->op->stackp].len < 0)
124         {
125             if (*o->bp++ == 0 && *(o->bp++) == 0)
126             {
127                     o->op->stackp--;
128                     return 1;
129             }
130             else
131             {
132                 odr_seterror(o, OOTHER, 35);
133                 return 0;
134             }
135         }
136         else if (o->bp - o->op->stack[o->op->stackp].base !=
137                  o->op->stack[o->op->stackp].len)
138         {
139             odr_seterror(o, OCONLEN, 36);
140             return 0;
141         }
142         o->op->stackp--;
143         return 1;
144     case ODR_ENCODE:
145         pos = odr_tell(o);
146         odr_seek(o, ODR_S_SET, o->op->stack[o->op->stackp].len_offset);
147         if ((res = ber_enclen(o, pos - o->op->stack[o->op->stackp].base_offset,
148                               o->op->stack[o->op->stackp].lenlen, 1)) < 0)
149         {
150             odr_seterror(o, OLENOV, 37);
151             return 0;
152         }
153         odr_seek(o, ODR_S_END, 0);
154         if (res == 0)   /* indefinite encoding */
155         {
156 #ifdef ODR_DEBUG
157             fprintf(stderr, "[cons_end(%d): indefinite]", o->op->stackp);
158 #endif
159             if (odr_putc(o, 0) < 0 || odr_putc(o, 0) < 0)
160                 return 0;
161         }
162 #ifdef ODR_DEBUG
163         else
164         {
165             fprintf(stderr, "[cons_end(%d): definite]", o->op->stackp);
166         }
167 #endif
168         o->op->stackp--;
169         return 1;
170     case ODR_PRINT:
171         o->op->stackp--;
172         o->indent--;
173         odr_prname(o, 0);
174         fprintf(o->print, "}\n");
175         return 1;
176     default:
177         odr_seterror(o, OOTHER, 38);
178         return 0;
179     }
180 }