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