SIM-115: update simulator to use latest E2SM KPM version 3
[sim/e2-interface.git] / e2sim / asn1c / constr_CHOICE_aper.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 <constr_CHOICE.h>
8 #include <aper_opentype.h>
9
10 asn_dec_rval_t
11 CHOICE_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
12                    const asn_TYPE_descriptor_t *td,
13                    const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
14     const asn_CHOICE_specifics_t *specs = (const asn_CHOICE_specifics_t *)td->specifics;
15     asn_dec_rval_t rv;
16     const asn_per_constraint_t *ct = NULL;
17     asn_TYPE_member_t *elm = NULL;  /* CHOICE's element */
18     void *memb_ptr = NULL;
19     void **memb_ptr2 = NULL;
20     void *st = *sptr;
21     int value = 0;
22
23     if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))
24         ASN__DECODE_FAILED;
25
26     /*
27      * Create the target structure if it is not present already.
28      */
29     if(!st) {
30         st = *sptr = CALLOC(1, specs->struct_size);
31         if(!st) ASN__DECODE_FAILED;
32     }
33
34     if(constraints) ct = &constraints->value;
35     else if(td->encoding_constraints.per_constraints)
36         ct = &td->encoding_constraints.per_constraints->value;
37     else ct = 0;
38
39     if(ct && ct->flags & APC_EXTENSIBLE) {
40         value = per_get_few_bits(pd, 1);
41         if(value < 0) ASN__DECODE_STARVED;
42         if(value) ct = 0;  /* Not restricted */
43     }
44
45     if(ct && ct->range_bits >= 0) {
46         value = per_get_few_bits(pd, ct->range_bits);
47         if(value < 0) ASN__DECODE_STARVED;
48         ASN_DEBUG("CHOICE %s got index %d in range %d",
49                   td->name, value, ct->range_bits);
50         if(value > ct->upper_bound)
51             ASN__DECODE_FAILED;
52     } else {
53         if(specs->ext_start == -1)
54             ASN__DECODE_FAILED;
55
56         if(specs && specs->tag2el_count > specs->ext_start) {
57             value = aper_get_nsnnwn(pd, specs->tag2el_count - specs->ext_start); /* extension elements range */
58             if(value < 0) ASN__DECODE_STARVED;
59             value += specs->ext_start;
60             if((unsigned)value >= td->elements_count)
61                 ASN__DECODE_FAILED;
62         }
63     }
64
65     /* Adjust if canonical order is different from natural order */
66     if(specs->from_canonical_order)
67         value = specs->from_canonical_order[value];
68
69     /* Set presence to be able to free it later */
70     _set_present_idx(st, specs->pres_offset, specs->pres_size, value + 1);
71
72     elm = &td->elements[value];
73     if(elm->flags & ATF_POINTER) {
74         /* Member is a pointer to another structure */
75         memb_ptr2 = (void **)((char *)st + elm->memb_offset);
76     } else {
77         memb_ptr = (char *)st + elm->memb_offset;
78         memb_ptr2 = &memb_ptr;
79     }
80     ASN_DEBUG("Discovered CHOICE %s encodes %s", td->name, elm->name);
81
82     if(ct && ct->range_bits >= 0) {
83         rv = elm->type->op->aper_decoder(opt_codec_ctx, elm->type,
84                                          elm->encoding_constraints.per_constraints, memb_ptr2, pd);
85     } else {
86         rv = aper_open_type_get(opt_codec_ctx, elm->type,
87                                 elm->encoding_constraints.per_constraints, memb_ptr2, pd);
88     }
89
90     if(rv.code != RC_OK)
91         ASN_DEBUG("Failed to decode %s in %s (CHOICE) %d",
92                   elm->name, td->name, rv.code);
93     return rv;
94 }
95
96 asn_enc_rval_t
97 CHOICE_encode_aper(const asn_TYPE_descriptor_t *td,
98                    const asn_per_constraints_t *constraints,
99                    const void *sptr, asn_per_outp_t *po) {
100     const asn_CHOICE_specifics_t *specs = (const asn_CHOICE_specifics_t *)td->specifics;
101     const asn_TYPE_member_t *elm;  /* CHOICE's element */
102     const asn_per_constraint_t *ct;
103     const void *memb_ptr;
104     int present;
105
106     if(!sptr) ASN__ENCODE_FAILED;
107
108     ASN_DEBUG("Encoding %s as CHOICE using ALIGNED PER", td->name);
109
110     if(constraints) ct = &constraints->value;
111     else if(td->encoding_constraints.per_constraints)
112         ct = &td->encoding_constraints.per_constraints->value;
113     else ct = 0;
114
115     present = _fetch_present_idx(sptr,
116                                  specs->pres_offset, specs->pres_size);
117
118     /*
119      * If the structure was not initialized properly, it cannot be encoded:
120      * can't deduce what to encode in the choice type.
121      */
122     if(present <= 0 || (unsigned)present > td->elements_count)
123         ASN__ENCODE_FAILED;
124     else
125         present--;
126
127     /* Adjust if canonical order is different from natural order */
128     if(specs->to_canonical_order)
129         present = specs->to_canonical_order[present];
130
131     ASN_DEBUG("Encoding %s CHOICE element %d", td->name, present);
132
133     if(ct && ct->range_bits >= 0) {
134         if(present < ct->lower_bound
135                 || present > ct->upper_bound) {
136             if(ct->flags & APC_EXTENSIBLE) {
137                 if(per_put_few_bits(po, 1, 1))
138                     ASN__ENCODE_FAILED;
139             } else {
140                 ASN__ENCODE_FAILED;
141             }
142             ct = 0;
143         }
144     }
145     if(ct && ct->flags & APC_EXTENSIBLE) {
146         if(per_put_few_bits(po, 0, 1))
147             ASN__ENCODE_FAILED;
148     }
149
150     elm = &td->elements[present];
151     if(elm->flags & ATF_POINTER) {
152         /* Member is a pointer to another structure */
153         memb_ptr = *(const void *const *)((const char *)sptr + elm->memb_offset);
154         if(!memb_ptr) ASN__ENCODE_FAILED;
155     } else {
156         memb_ptr = (const char *)sptr + elm->memb_offset;
157     }
158
159     if(ct && ct->range_bits >= 0) {
160         if(per_put_few_bits(po, present, ct->range_bits))
161             ASN__ENCODE_FAILED;
162
163         return elm->type->op->aper_encoder(elm->type, elm->encoding_constraints.per_constraints,
164                                            memb_ptr, po);
165     } else {
166         asn_enc_rval_t rval = {0,0,0};
167         if(specs->ext_start == -1)
168             ASN__ENCODE_FAILED;
169         int n = present - specs->ext_start;
170         if(n <= 63) {
171             if(n < 0) ASN__ENCODE_FAILED;
172             if(per_put_few_bits(po, n, 7)) ASN__ENCODE_FAILED;
173         } else
174             ASN__ENCODE_FAILED;
175         if(aper_open_type_put(elm->type, elm->encoding_constraints.per_constraints,
176                               memb_ptr, po))
177             ASN__ENCODE_FAILED;
178         rval.encoded = 0;
179         ASN__ENCODED_OK(rval);
180     }
181 }