SIM-115: update simulator to use latest E2SM KPM version 3
[sim/e2-interface.git] / e2sim / asn1c / OPEN_TYPE_uper.c
1 /*
2  * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
3  * All rights reserved.
4  * Redistribution and modifications are permitted subject to BSD license.
5  */
6 #include <asn_internal.h>
7 #include <OPEN_TYPE.h>
8 #include <constr_CHOICE.h>
9 #include <uper_opentype.h>
10
11 asn_dec_rval_t
12 OPEN_TYPE_uper_get(const asn_codec_ctx_t *opt_codec_ctx,
13                    const asn_TYPE_descriptor_t *td, void *sptr,
14                    const asn_TYPE_member_t *elm, asn_per_data_t *pd) {
15     asn_type_selector_result_t selected;
16     void *memb_ptr;   /* Pointer to the member */
17     void **memb_ptr2; /* Pointer to that pointer */
18     void *inner_value;
19     asn_dec_rval_t rv;
20
21     if(!(elm->flags & ATF_OPEN_TYPE)) {
22         ASN__DECODE_FAILED;
23     }
24
25     if(!elm->type_selector) {
26         ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s",
27                   td->name, elm->name, elm->type->name);
28         ASN__DECODE_FAILED;
29     }
30
31     selected = elm->type_selector(td, sptr);
32     if(!selected.presence_index) {
33         ASN__DECODE_FAILED;
34     }
35
36     /* Fetch the pointer to this member */
37     assert(elm->flags == ATF_OPEN_TYPE);
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)
47            != 0) {
48             ASN__DECODE_FAILED;
49         }
50     }
51
52     inner_value =
53         (char *)*memb_ptr2
54         + elm->type->elements[selected.presence_index - 1].memb_offset;
55
56     rv = uper_open_type_get(opt_codec_ctx, selected.type_descriptor, NULL,
57                             &inner_value, pd);
58     switch(rv.code) {
59     case RC_OK:
60         if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
61                                        selected.presence_index)
62            == 0) {
63             break;
64         } else {
65             rv.code = RC_FAIL;
66         }
67         /* Fall through */
68     case RC_WMORE:
69     case RC_FAIL:
70         if(*memb_ptr2) {
71             if(elm->flags & ATF_POINTER) {
72                 ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
73                 *memb_ptr2 = NULL;
74             } else {
75                 ASN_STRUCT_RESET(*selected.type_descriptor,
76                                               inner_value);
77             }
78         }
79     }
80     return rv;
81 }
82
83 asn_enc_rval_t
84 OPEN_TYPE_encode_uper(const asn_TYPE_descriptor_t *td,
85                       const asn_per_constraints_t *constraints,
86                       const void *sptr, asn_per_outp_t *po) {
87     const void *memb_ptr;   /* Pointer to the member */
88     asn_TYPE_member_t *elm; /* CHOICE's element */
89     asn_enc_rval_t er = {0,0,0};
90     unsigned present;
91
92     (void)constraints;
93
94     present = CHOICE_variant_get_presence(td, sptr);
95     if(present == 0 || present > td->elements_count) {
96         ASN__ENCODE_FAILED;
97     } else {
98         present--;
99     }
100
101     ASN_DEBUG("Encoding %s OPEN TYPE element %d", td->name, present);
102
103     elm = &td->elements[present];
104     if(elm->flags & ATF_POINTER) {
105         /* Member is a pointer to another structure */
106         memb_ptr =
107             *(const void *const *)((const char *)sptr + elm->memb_offset);
108         if(!memb_ptr) ASN__ENCODE_FAILED;
109     } else {
110         memb_ptr = (const char *)sptr + elm->memb_offset;
111     }
112
113     if(uper_open_type_put(elm->type, NULL, memb_ptr, po) < 0) {
114         ASN__ENCODE_FAILED;
115     }
116
117     er.encoded = 0;
118     ASN__ENCODED_OK(er);
119 }