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