Fix.
[yaz-moved-to-github.git] / odr / odr_seq.c
1 /*
2  * Copyright (c) 1995-1998, Index Data
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: odr_seq.c,v $
7  * Revision 1.23  1998-03-20 14:45:01  adam
8  * Implemented odr_enum and odr_set_of.
9  *
10  * Revision 1.22  1998/02/11 11:53:34  adam
11  * Changed code so that it compiles as C++.
12  *
13  * Revision 1.21  1997/11/24 11:33:56  adam
14  * Using function odr_nullval() instead of global ODR_NULLVAL when
15  * appropriate.
16  *
17  * Revision 1.20  1997/09/29 07:17:31  adam
18  * Added typecast to avoid warnings on MSVC.
19  *
20  * Revision 1.19  1997/06/23 10:31:11  adam
21  * Added RVDM's SEQUENCE OF patch again!
22  *
23  * Revision 1.18  1997/05/14 06:53:58  adam
24  * C++ support.
25  *
26  * Revision 1.17  1997/05/05 11:21:09  adam
27  * In handling of SEQUENCE OF: Counter set to zero when SEQUENCE
28  * OF isn't there at all.
29  *
30  * Revision 1.16  1995/09/29 17:12:26  quinn
31  * Smallish
32  *
33  * Revision 1.15  1995/09/27  15:03:00  quinn
34  * Modified function heads & prototypes.
35  *
36  * Revision 1.14  1995/08/15  11:16:39  quinn
37  * Fixed pretty-printers.
38  *
39  * Revision 1.13  1995/05/22  14:56:57  quinn
40  * Fixed problem in decoding empty sequence.
41  *
42  * Revision 1.12  1995/05/18  13:06:32  quinn
43  * Smallish.
44  *
45  * Revision 1.11  1995/05/17  08:41:54  quinn
46  * Small, hopefully insignificant change.
47  *
48  * Revision 1.10  1995/05/16  08:50:59  quinn
49  * License, documentation, and memory fixes
50  *
51  * Revision 1.9  1995/03/17  10:17:57  quinn
52  * Added memory management.
53  *
54  * Revision 1.8  1995/03/15  11:18:05  quinn
55  * Fixed serious bug in odr_cons
56  *
57  * Revision 1.7  1995/03/08  12:12:30  quinn
58  * Added better error checking.
59  *
60  * Revision 1.6  1995/02/10  15:55:29  quinn
61  * Bug fixes, mostly.
62  *
63  * Revision 1.5  1995/02/09  15:51:49  quinn
64  * Works better now.
65  *
66  * Revision 1.4  1995/02/07  17:53:00  quinn
67  * A damn mess, but now things work, I think.
68  *
69  * Revision 1.3  1995/02/07  14:13:46  quinn
70  * Bug fixes.
71  *
72  * Revision 1.2  1995/02/06  16:45:03  quinn
73  * Small mods.
74  *
75  * Revision 1.1  1995/02/02  16:21:54  quinn
76  * First kick.
77  *
78  */
79
80 #include <odr.h>
81 #include <assert.h>
82
83 int odr_sequence_begin(ODR o, void *p, int size)
84 {
85     char **pp = (char**) p;
86
87     if (o->error)
88         return 0;
89     if (o->t_class < 0)
90     {
91         o->t_class = ODR_UNIVERSAL;
92         o->t_tag = ODR_SEQUENCE;
93     }
94     if (o->direction == ODR_DECODE)
95         *pp = 0;
96     if (odr_constructed_begin(o, p, o->t_class, o->t_tag))
97     {
98         if (o->direction == ODR_DECODE && size)
99             *pp = (char *)odr_malloc(o, size);
100         return 1;
101     }
102     else
103         return 0;
104 }
105
106 int odr_set_begin(ODR o, void *p, int size)
107 {
108     char **pp = (char**) p;
109
110     if (o->error)
111         return 0;
112     if (o->t_class < 0)
113     {
114         o->t_class = ODR_UNIVERSAL;
115         o->t_tag = ODR_SET;
116     }
117     if (o->direction == ODR_DECODE)
118         *pp = 0;
119     if (odr_constructed_begin(o, p, o->t_class, o->t_tag))
120     {
121         if (o->direction == ODR_DECODE && size)
122             *pp = (char *)odr_malloc(o, size);
123         return 1;
124     }
125     else
126         return 0;
127 }
128
129 int odr_sequence_end(ODR o)
130 {
131     return odr_constructed_end(o);    
132 }
133
134 int odr_set_end(ODR o)
135 {
136     return odr_constructed_end(o);    
137 }
138
139 static int odr_sequence_more(ODR o)
140 {
141     return odr_constructed_more(o);
142 }
143
144 static int odr_sequence_x (ODR o, Odr_fun type, void *p, int *num)
145 {
146     char ***pp = (char***) p;  /* for dereferencing */
147     char **tmp = 0;
148     int size = 0, i;
149
150     switch (o->direction)
151     {
152         case ODR_DECODE:
153             *num = 0;
154             *pp = (char **)odr_nullval();
155             while (odr_sequence_more(o))
156             {
157                 /* outgrown array? */
158                 if (*num * (int) sizeof(void*) >= size)
159                 {
160                     /* double the buffer size */
161                     tmp = (char **)odr_malloc(o, sizeof(void*) *
162                                               (size += size ? size : 128));
163                     if (*num)
164                     {
165                         memcpy(tmp, *pp, *num * sizeof(void*));
166                         /*
167                          * For now, we just throw the old *p away, since we use
168                          * nibble memory anyway (disgusting, isn't it?).
169                          */
170                     }
171                     *pp = tmp;
172                 }
173                 if (!(*type)(o, (*pp) + *num, 0))
174                     return 0;
175                 (*num)++;
176             }
177             break;
178         case ODR_ENCODE: case ODR_PRINT:
179 #ifdef ODR_DEBUG
180             fprintf(stderr, "[seqof: num=%d]", *num);
181 #endif
182             for (i = 0; i < *num; i++)
183             {
184 #ifdef ODR_DEBUG
185                 fprintf(stderr, "[seqof: elem #%d]", i);
186 #endif
187                 if (!(*type)(o, *pp + i, 0))
188                     return 0;
189             }
190             break;
191         default:
192             o->error = OOTHER;
193             return 0;
194     }
195     return odr_sequence_end(o);
196 }
197
198 int odr_set_of(ODR o, Odr_fun type, void *p, int *num)
199 {
200     if (!odr_set_begin(o, p, 0)) {
201         if (o->direction == ODR_DECODE)
202             *num = 0;
203         return 0;
204     }
205     return odr_sequence_x (o, type, p, num);
206 }
207
208 int odr_sequence_of(ODR o, Odr_fun type, void *p, int *num)
209 {
210     if (!odr_sequence_begin(o, p, 0)) {
211         if (o->direction == ODR_DECODE)
212             *num = 0;
213         return 0;
214     }
215     return odr_sequence_x (o, type, p, num);
216 }
217