YAZ  5.23.1
odr_cons.c
Go to the documentation of this file.
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
5 
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->op->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 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->op->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->op->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->op->bp;
132  o->op->stack_top->base_offset = odr_tell(o);
133  return 1;
134 }
135 
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->op->bp - o->op->stack_top->base < o->op->stack_top->len;
144  else
145  return (!(*o->op->bp == 0 && *(o->op->bp + 1) == 0));
146 }
147 
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->op->bp++ == 0 && *(o->op->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->op->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);
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 
void odr_seterror(ODR o, int error, int id)
Definition: odr.c:118
int t_class
Definition: odr-priv.h:107
#define ODR_STACK_EMPTY(x)
Definition: odr-priv.h:118
struct odr_constack * stack_top
Definition: odr-priv.h:92
int ber_declen(const char *buf, int *len, int max)
Definition: ber_len.c:93
#define ODR_PRINT
Definition: odr.h:97
#define OOTHER
Definition: odr.h:156
#define ODR_ENCODE
Definition: odr.h:96
stack for BER constructed items
Definition: odr-priv.h:63
int error
Definition: odr.h:128
struct odr_constack * next
Definition: odr-priv.h:75
int odr_seek(ODR o, int whence, int offset)
Definition: odr_mem.c:117
char * name
Definition: initopt.c:18
#define OCONLEN
Definition: odr.h:160
#define odr_putc(o, c)
Definition: odr-priv.h:129
int ber_tag(ODR o, void *p, int zclass, int tag, int *constructed, int opt, const char *name)
Encode/decode BER tags.
Definition: ber_tag.c:34
int odr_constructed_begin(ODR o, void *xxp, int zclass, int tag, const char *name)
Definition: odr_cons.c:24
void * odr_malloc(ODR o, size_t size)
Definition: odr_mem.c:31
void odr_prname(ODR o, const char *name)
Definition: odr_util.c:18
#define ODR_S_SET
Definition: odr.h:117
Internal ODR definitions.
const char * lenb
Definition: odr-priv.h:69
void odr_setlenlen(ODR o, int len)
Definition: odr_cons.c:19
int direction
Definition: odr.h:126
const char * base
Definition: odr-priv.h:65
int odr_constructed_more(ODR o)
Definition: odr_cons.c:136
#define odr_max(o)
Definition: odr-priv.h:47
int indent
Definition: odr-priv.h:114
#define ODR_STACK_POP(x)
Definition: odr-priv.h:117
#define OSTACK
Definition: odr.h:159
struct Odr_private * op
Definition: odr.h:132
#define ODR_S_END
Definition: odr.h:119
int lenlen
Definition: odr-priv.h:71
int ber_enclen(ODR o, int len, int lenlen, int exact)
Definition: ber_len.c:30
const char * bp
Definition: odr-priv.h:85
struct odr_constack * prev
Definition: odr-priv.h:74
Definition: odr.h:124
#define OLENOV
Definition: odr.h:161
const char * name
Definition: odr-priv.h:72
int lenlen
Definition: odr-priv.h:112
#define ODR_MAX_STACK
Definition: odr-priv.h:78
struct odr_constack * stack_first
Definition: odr-priv.h:91
int odr_constructed_end(ODR o)
Definition: odr_cons.c:148
int base_offset
Definition: odr-priv.h:66
int odr_write(ODR o, const char *buf, int bytes)
Definition: odr_mem.c:98
int len_offset
Definition: odr-priv.h:70
#define odr_tell(o)
Definition: odr-priv.h:121
void odr_printf(ODR o, const char *fmt,...)
Definition: odr.c:290
#define ODR_DECODE
Definition: odr.h:95