]> git.stg.codes - stg.git/blob - libs/smux/OPEN_TYPE.c
Add an option to opt-out Firebird store.
[stg.git] / libs / smux / OPEN_TYPE.c
1 /*
2  * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
3  * Redistribution and modifications are permitted subject to BSD license.
4  */
5 #include <asn_internal.h>
6 #include <OPEN_TYPE.h>
7 #include <constr_CHOICE.h>
8 #include <per_opentype.h>
9 #include <errno.h>
10
11 asn_TYPE_operation_t asn_OP_OPEN_TYPE = {
12         OPEN_TYPE_free,
13         OPEN_TYPE_print,
14         OPEN_TYPE_compare,
15         OPEN_TYPE_decode_ber,
16         OPEN_TYPE_encode_der,
17         OPEN_TYPE_decode_xer,
18         OPEN_TYPE_encode_xer,
19         0, 0,   /* No OER support, use "-gen-OER" to enable */
20 #ifdef ASN_DISABLE_PER_SUPPORT
21         0, 0,
22 #else
23         OPEN_TYPE_decode_uper,
24         OPEN_TYPE_encode_uper,
25 #endif
26         0,  /* Random fill is not supported for open type */
27         0,      /* Use generic outmost tag fetcher */
28 };
29
30 #undef  ADVANCE
31 #define ADVANCE(num_bytes)               \
32     do {                                 \
33         size_t num = num_bytes;          \
34         ptr = ((const char *)ptr) + num; \
35         size -= num;                     \
36         consumed_myself += num;          \
37     } while(0)
38
39 asn_dec_rval_t
40 OPEN_TYPE_ber_get(const asn_codec_ctx_t *opt_codec_ctx,
41                   const asn_TYPE_descriptor_t *td, void *sptr,
42                   const asn_TYPE_member_t *elm, const void *ptr, size_t size) {
43     size_t consumed_myself = 0;
44     asn_type_selector_result_t selected;
45     void *memb_ptr;   /* Pointer to the member */
46     void **memb_ptr2; /* Pointer to that pointer */
47     void *inner_value;
48     asn_dec_rval_t rv;
49
50     if(!(elm->flags & ATF_OPEN_TYPE)) {
51         ASN__DECODE_FAILED;
52     }
53
54     if(!elm->type_selector) {
55         ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s",
56                   td->name, elm->name, elm->type->name);
57         ASN__DECODE_FAILED;
58     }
59
60     selected = elm->type_selector(td, sptr);
61     if(!selected.presence_index) {
62         ASN__DECODE_FAILED;
63     }
64
65     /* Fetch the pointer to this member */
66     if(elm->flags & ATF_POINTER) {
67         memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
68     } else {
69         memb_ptr = (char *)sptr + elm->memb_offset;
70         memb_ptr2 = &memb_ptr;
71     }
72     if(*memb_ptr2 != NULL) {
73         /* Make sure we reset the structure first before encoding */
74         if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0) != 0) {
75             ASN__DECODE_FAILED;
76         }
77     }
78
79     inner_value =
80         (char *)*memb_ptr2
81         + elm->type->elements[selected.presence_index - 1].memb_offset;
82
83     ASN_DEBUG("presence %d\n", selected.presence_index);
84
85     rv = selected.type_descriptor->op->ber_decoder(
86         opt_codec_ctx, selected.type_descriptor, &inner_value, ptr, size,
87         elm->tag_mode);
88     ADVANCE(rv.consumed);
89     rv.consumed = 0;
90     switch(rv.code) {
91     case RC_OK:
92         if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
93                                        selected.presence_index)
94            == 0) {
95             rv.code = RC_OK;
96             rv.consumed = consumed_myself;
97             return rv;
98         } else {
99             /* Oh, now a full-blown failure failure */
100         }
101         /* Fall through */
102     case RC_FAIL:
103         rv.consumed = consumed_myself;
104         /* Fall through */
105     case RC_WMORE:
106         break;
107     }
108
109     if(*memb_ptr2) {
110         const asn_CHOICE_specifics_t *specs =
111             selected.type_descriptor->specifics;
112         if(elm->flags & ATF_POINTER) {
113             ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
114             *memb_ptr2 = NULL;
115         } else {
116             ASN_STRUCT_FREE_CONTENTS_ONLY(*selected.type_descriptor,
117                                           inner_value);
118             memset(*memb_ptr2, 0, specs->struct_size);
119         }
120     }
121     return rv;
122 }
123
124 asn_dec_rval_t
125 OPEN_TYPE_xer_get(const asn_codec_ctx_t *opt_codec_ctx,
126                   const asn_TYPE_descriptor_t *td, void *sptr,
127                   const asn_TYPE_member_t *elm, const void *ptr, size_t size) {
128     size_t consumed_myself = 0;
129     asn_type_selector_result_t selected;
130     void *memb_ptr;   /* Pointer to the member */
131     void **memb_ptr2; /* Pointer to that pointer */
132     void *inner_value;
133     asn_dec_rval_t rv;
134
135     int xer_context = 0;
136     ssize_t ch_size;
137     pxer_chunk_type_e ch_type;
138
139     if(!(elm->flags & ATF_OPEN_TYPE)) {
140         ASN__DECODE_FAILED;
141     }
142
143     if(!elm->type_selector) {
144         ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s",
145                   td->name, elm->name, elm->type->name);
146         ASN__DECODE_FAILED;
147     }
148
149     selected = elm->type_selector(td, sptr);
150     if(!selected.presence_index) {
151         ASN__DECODE_FAILED;
152     }
153
154     /* Fetch the pointer to this member */
155     assert(elm->flags == ATF_OPEN_TYPE);
156     if(elm->flags & ATF_POINTER) {
157         memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
158     } else {
159         memb_ptr = (char *)sptr + elm->memb_offset;
160         memb_ptr2 = &memb_ptr;
161     }
162     if(*memb_ptr2 != NULL) {
163         /* Make sure we reset the structure first before encoding */
164         if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0)
165            != 0) {
166             ASN__DECODE_FAILED;
167         }
168     }
169
170     /*
171      * Confirm wrapper.
172      */
173     for(;;) {
174         ch_size = xer_next_token(&xer_context, ptr, size, &ch_type);
175         if(ch_size < 0) {
176             ASN__DECODE_FAILED;
177         } else {
178             switch(ch_type) {
179             case PXER_WMORE:
180                 ASN__DECODE_STARVED;
181             case PXER_COMMENT:
182             case PXER_TEXT:
183                 ADVANCE(ch_size);
184                 continue;
185             case PXER_TAG:
186                 break;
187             }
188             break;
189         }
190     }
191
192     /*
193      * Wrapper value confirmed.
194      */
195     switch(xer_check_tag(ptr, ch_size, elm->name)) {
196     case XCT_OPENING:
197         ADVANCE(ch_size);
198         break;
199     case XCT_BROKEN:
200     default:
201         ASN__DECODE_FAILED;
202     }
203
204     inner_value =
205         (char *)*memb_ptr2
206         + elm->type->elements[selected.presence_index - 1].memb_offset;
207
208     rv = selected.type_descriptor->op->xer_decoder(
209         opt_codec_ctx, selected.type_descriptor, &inner_value, NULL, ptr, size);
210     ADVANCE(rv.consumed);
211     rv.consumed = 0;
212     switch(rv.code) {
213     case RC_OK:
214         if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
215                                        selected.presence_index)
216            == 0) {
217             break;
218         } else {
219             rv.code = RC_FAIL;
220         }
221         /* Fall through */
222     case RC_FAIL:
223         /* Point to a best position where failure occurred */
224         rv.consumed = consumed_myself;
225         /* Fall through */
226     case RC_WMORE:
227         /* Wrt. rv.consumed==0:
228          * In case a genuine RC_WMORE, the whole Open Type decoding
229          * will have to be restarted.
230          */
231         if(*memb_ptr2) {
232             const asn_CHOICE_specifics_t *specs =
233                 selected.type_descriptor->specifics;
234             if(elm->flags & ATF_POINTER) {
235                 ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
236                 *memb_ptr2 = NULL;
237             } else {
238                 ASN_STRUCT_FREE_CONTENTS_ONLY(*selected.type_descriptor,
239                                               inner_value);
240                 memset(*memb_ptr2, 0, specs->struct_size);
241             }
242         }
243         return rv;
244     }
245
246     /*
247      * Finalize wrapper.
248      */
249     for(;;) {
250         ch_size = xer_next_token(&xer_context, ptr, size, &ch_type);
251         if(ch_size < 0) {
252             ASN__DECODE_FAILED;
253         } else {
254             switch(ch_type) {
255             case PXER_WMORE:
256                 ASN__DECODE_STARVED;
257             case PXER_COMMENT:
258             case PXER_TEXT:
259                 ADVANCE(ch_size);
260                 continue;
261             case PXER_TAG:
262                 break;
263             }
264             break;
265         }
266     }
267
268     /*
269      * Wrapper value confirmed.
270      */
271     switch(xer_check_tag(ptr, ch_size, elm->name)) {
272     case XCT_CLOSING:
273         ADVANCE(ch_size);
274         break;
275     case XCT_BROKEN:
276     default:
277         ASN__DECODE_FAILED;
278     }
279
280     rv.consumed += consumed_myself;
281
282     return rv;
283 }
284
285
286 #ifndef  ASN_DISABLE_PER_SUPPORT
287
288 asn_dec_rval_t
289 OPEN_TYPE_uper_get(const asn_codec_ctx_t *opt_codec_ctx,
290                    const asn_TYPE_descriptor_t *td, void *sptr,
291                    const asn_TYPE_member_t *elm, asn_per_data_t *pd) {
292     asn_type_selector_result_t selected;
293     void *memb_ptr;   /* Pointer to the member */
294     void **memb_ptr2; /* Pointer to that pointer */
295     void *inner_value;
296     asn_dec_rval_t rv;
297
298     if(!(elm->flags & ATF_OPEN_TYPE)) {
299         ASN__DECODE_FAILED;
300     }
301
302     if(!elm->type_selector) {
303         ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s",
304                   td->name, elm->name, elm->type->name);
305         ASN__DECODE_FAILED;
306     }
307
308     selected = elm->type_selector(td, sptr);
309     if(!selected.presence_index) {
310         ASN__DECODE_FAILED;
311     }
312
313     /* Fetch the pointer to this member */
314     assert(elm->flags == ATF_OPEN_TYPE);
315     if(elm->flags & ATF_POINTER) {
316         memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
317     } else {
318         memb_ptr = (char *)sptr + elm->memb_offset;
319         memb_ptr2 = &memb_ptr;
320     }
321     if(*memb_ptr2 != NULL) {
322         /* Make sure we reset the structure first before encoding */
323         if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0)
324            != 0) {
325             ASN__DECODE_FAILED;
326         }
327     }
328
329     inner_value =
330         (char *)*memb_ptr2
331         + elm->type->elements[selected.presence_index - 1].memb_offset;
332
333     rv = uper_open_type_get(opt_codec_ctx, selected.type_descriptor, NULL,
334                             &inner_value, pd);
335     switch(rv.code) {
336     case RC_OK:
337         if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
338                                        selected.presence_index)
339            == 0) {
340             break;
341         } else {
342             rv.code = RC_FAIL;
343         }
344         /* Fall through */
345     case RC_WMORE:
346     case RC_FAIL:
347         if(*memb_ptr2) {
348             const asn_CHOICE_specifics_t *specs =
349                 selected.type_descriptor->specifics;
350             if(elm->flags & ATF_POINTER) {
351                 ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
352                 *memb_ptr2 = NULL;
353             } else {
354                 ASN_STRUCT_FREE_CONTENTS_ONLY(*selected.type_descriptor,
355                                               inner_value);
356                 memset(*memb_ptr2, 0, specs->struct_size);
357             }
358         }
359     }
360     return rv;
361 }
362
363 asn_enc_rval_t
364 OPEN_TYPE_encode_uper(const asn_TYPE_descriptor_t *td,
365                       const asn_per_constraints_t *constraints,
366                       const void *sptr, asn_per_outp_t *po) {
367     const void *memb_ptr;   /* Pointer to the member */
368     asn_TYPE_member_t *elm; /* CHOICE's element */
369     asn_enc_rval_t er;
370     unsigned present;
371
372     (void)constraints;
373
374     present = CHOICE_variant_get_presence(td, sptr);
375     if(present == 0 || present > td->elements_count) {
376         ASN__ENCODE_FAILED;
377     } else {
378         present--;
379     }
380
381     ASN_DEBUG("Encoding %s OPEN TYPE element %d", td->name, present);
382
383     elm = &td->elements[present];
384     if(elm->flags & ATF_POINTER) {
385         /* Member is a pointer to another structure */
386         memb_ptr =
387             *(const void *const *)((const char *)sptr + elm->memb_offset);
388         if(!memb_ptr) ASN__ENCODE_FAILED;
389     } else {
390         memb_ptr = (const char *)sptr + elm->memb_offset;
391     }
392
393     if(uper_open_type_put(elm->type, NULL, memb_ptr, po) < 0) {
394         ASN__ENCODE_FAILED;
395     }
396
397     er.encoded = 0;
398     ASN__ENCODED_OK(er);
399 }
400
401
402 #endif  /* ASN_DISABLE_PER_SUPPORT */