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