]> git.stg.codes - stg.git/blob - libs/smux/OPEN_TYPE_oer.c
Update README.
[stg.git] / libs / smux / OPEN_TYPE_oer.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 <errno.h>
9
10 asn_dec_rval_t
11 OPEN_TYPE_oer_get(const asn_codec_ctx_t *opt_codec_ctx,
12                   const asn_TYPE_descriptor_t *td, void *sptr,
13                   asn_TYPE_member_t *elm, const void *ptr, size_t size) {
14     asn_type_selector_result_t selected;
15     void *memb_ptr;   /* Pointer to the member */
16     void **memb_ptr2; /* Pointer to that pointer */
17     void *inner_value;
18     asn_dec_rval_t rv;
19     size_t ot_ret;
20
21
22     if(!(elm->flags & ATF_OPEN_TYPE)) {
23         ASN__DECODE_FAILED;
24     }
25
26     if(!elm->type_selector) {
27         ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s",
28                   td->name, elm->name, elm->type->name);
29         ASN__DECODE_FAILED;
30     }
31
32     selected = elm->type_selector(td, sptr);
33     if(!selected.presence_index) {
34         ASN__DECODE_FAILED;
35     }
36
37     /* Fetch the pointer to this member */
38     if(elm->flags & ATF_POINTER) {
39         memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
40     } else {
41         memb_ptr = (char *)sptr + elm->memb_offset;
42         memb_ptr2 = &memb_ptr;
43     }
44     if(*memb_ptr2 != NULL) {
45         /* Make sure we reset the structure first before encoding */
46         if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0) != 0) {
47             ASN__DECODE_FAILED;
48         }
49     }
50
51     inner_value =
52         (char *)*memb_ptr2
53         + elm->type->elements[selected.presence_index - 1].memb_offset;
54
55     ot_ret = oer_open_type_get(opt_codec_ctx, selected.type_descriptor, NULL,
56                                &inner_value, ptr, size);
57     switch(ot_ret) {
58     default:
59         if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
60                                        selected.presence_index)
61            == 0) {
62             rv.code = RC_OK;
63             rv.consumed = ot_ret;
64             return rv;
65         } else {
66             /* Oh, now a full-blown failure failure */
67         }
68         /* Fall through */
69     case -1:
70         rv.code = RC_FAIL;
71         rv.consumed = ot_ret;
72         break;
73     case 0:
74         rv.code = RC_WMORE;
75         rv.consumed = 0;
76         break;
77     }
78
79     if(*memb_ptr2) {
80         const asn_CHOICE_specifics_t *specs =
81             selected.type_descriptor->specifics;
82         if(elm->flags & ATF_POINTER) {
83             ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
84             *memb_ptr2 = NULL;
85         } else {
86             ASN_STRUCT_FREE_CONTENTS_ONLY(*selected.type_descriptor,
87                                           inner_value);
88             memset(*memb_ptr2, 0, specs->struct_size);
89         }
90     }
91     return rv;
92 }