b73d1fdcbc958923feb31b668b4091cd1b57b581
[yaz-moved-to-github.git] / src / odr_seq.c
1 /*
2  * Copyright (C) 1995-2007, Index Data ApS
3  * See the file LICENSE for details.
4  *
5  * $Id: odr_seq.c,v 1.6 2007-01-03 08:42:15 adam Exp $
6  */
7 /**
8  * \file odr_seq.c
9  * \brief Implements ODR SEQUENCE codec
10  */
11 #if HAVE_CONFIG_H
12 #include <config.h>
13 #endif
14
15 #include "odr-priv.h"
16
17 int odr_sequence_begin(ODR o, void *p, int size, const char *name)
18 {
19     char **pp = (char**) p;
20
21     if (o->error)
22         return 0;
23     if (o->t_class < 0)
24     {
25         o->t_class = ODR_UNIVERSAL;
26         o->t_tag = ODR_SEQUENCE;
27     }
28     if (o->direction == ODR_DECODE)
29         *pp = 0;
30     if (odr_constructed_begin(o, p, o->t_class, o->t_tag, name))
31     {
32         if (o->direction == ODR_DECODE && size)
33             *pp = (char *)odr_malloc(o, size);
34         return 1;
35     }
36     else
37         return 0;
38 }
39
40 int odr_set_begin(ODR o, void *p, int size, const char *name)
41 {
42     char **pp = (char**) p;
43
44     if (o->error)
45         return 0;
46     if (o->t_class < 0)
47     {
48         o->t_class = ODR_UNIVERSAL;
49         o->t_tag = ODR_SET;
50     }
51     if (o->direction == ODR_DECODE)
52         *pp = 0;
53     if (odr_constructed_begin(o, p, o->t_class, o->t_tag, name))
54     {
55         if (o->direction == ODR_DECODE && size)
56             *pp = (char *)odr_malloc(o, size);
57         return 1;
58     }
59     else
60         return 0;
61 }
62
63 int odr_sequence_end(ODR o)
64 {
65     return odr_constructed_end(o);    
66 }
67
68 int odr_set_end(ODR o)
69 {
70     return odr_constructed_end(o);    
71 }
72
73 static int odr_sequence_more(ODR o)
74 {
75     return odr_constructed_more(o);
76 }
77
78 static int odr_sequence_x (ODR o, Odr_fun type, void *p, int *num)
79 {
80     char ***pp = (char***) p;  /* for dereferencing */
81     char **tmp = 0;
82     int size = 0, i;
83
84     switch (o->direction)
85     {
86         case ODR_DECODE:
87             *num = 0;
88             *pp = (char **)odr_nullval();
89             while (odr_sequence_more(o))
90             {
91                 /* outgrown array? */
92                 if (*num * (int) sizeof(void*) >= size)
93                 {
94                     /* double the buffer size */
95                     tmp = (char **)odr_malloc(o, sizeof(void*) *
96                                               (size += size ? size : 128));
97                     if (*num)
98                     {
99                         memcpy(tmp, *pp, *num * sizeof(void*));
100                         /*
101                          * For now, we just throw the old *p away, since we use
102                          * nibble memory anyway (disgusting, isn't it?).
103                          */
104                     }
105                     *pp = tmp;
106                 }
107                 if (!(*type)(o, (*pp) + *num, 0, 0))
108                     return 0;
109                 (*num)++;
110             }
111             break;
112         case ODR_ENCODE: case ODR_PRINT:
113             for (i = 0; i < *num; i++)
114             {
115                 if (!(*type)(o, *pp + i, 0, 0))
116                     return 0;
117             }
118             break;
119         default:
120             odr_seterror(o, OOTHER, 47);
121             return 0;
122     }
123     return odr_sequence_end(o);
124 }
125
126 int odr_set_of(ODR o, Odr_fun type, void *p, int *num, const char *name)
127 {
128     if (!odr_set_begin(o, p, 0, name)) {
129         if (o->direction == ODR_DECODE)
130             *num = 0;
131         return 0;
132     }
133     return odr_sequence_x (o, type, p, num);
134 }
135
136 int odr_sequence_of(ODR o, Odr_fun type, void *p, int *num,
137                     const char *name)
138 {
139     if (!odr_sequence_begin(o, p, 0, name)) {
140         if (o->direction == ODR_DECODE)
141             *num = 0;
142         return 0;
143     }
144     return odr_sequence_x (o, type, p, num);
145 }
146
147 /*
148  * Local variables:
149  * c-basic-offset: 4
150  * indent-tabs-mode: nil
151  * End:
152  * vim: shiftwidth=4 tabstop=8 expandtab
153  */
154