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