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