2 * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
4 * Redistribution and modifications are permitted subject to BSD license.
6 #include <asn_internal.h>
7 #include <constr_CHOICE.h>
8 #include <aper_opentype.h>
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;
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;
23 if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))
27 * Create the target structure if it is not present already.
30 st = *sptr = CALLOC(1, specs->struct_size);
31 if(!st) ASN__DECODE_FAILED;
34 if(constraints) ct = &constraints->value;
35 else if(td->encoding_constraints.per_constraints)
36 ct = &td->encoding_constraints.per_constraints->value;
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 */
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)
53 if(specs->ext_start == -1)
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)
65 /* Adjust if canonical order is different from natural order */
66 if(specs->from_canonical_order)
67 value = specs->from_canonical_order[value];
69 /* Set presence to be able to free it later */
70 _set_present_idx(st, specs->pres_offset, specs->pres_size, value + 1);
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);
77 memb_ptr = (char *)st + elm->memb_offset;
78 memb_ptr2 = &memb_ptr;
80 ASN_DEBUG("Discovered CHOICE %s encodes %s", td->name, elm->name);
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);
86 rv = aper_open_type_get(opt_codec_ctx, elm->type,
87 elm->encoding_constraints.per_constraints, memb_ptr2, pd);
91 ASN_DEBUG("Failed to decode %s in %s (CHOICE) %d",
92 elm->name, td->name, rv.code);
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;
106 if(!sptr) ASN__ENCODE_FAILED;
108 ASN_DEBUG("Encoding %s as CHOICE using ALIGNED PER", td->name);
110 if(constraints) ct = &constraints->value;
111 else if(td->encoding_constraints.per_constraints)
112 ct = &td->encoding_constraints.per_constraints->value;
115 present = _fetch_present_idx(sptr,
116 specs->pres_offset, specs->pres_size);
119 * If the structure was not initialized properly, it cannot be encoded:
120 * can't deduce what to encode in the choice type.
122 if(present <= 0 || (unsigned)present > td->elements_count)
127 /* Adjust if canonical order is different from natural order */
128 if(specs->to_canonical_order)
129 present = specs->to_canonical_order[present];
131 ASN_DEBUG("Encoding %s CHOICE element %d", td->name, present);
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))
145 if(ct && ct->flags & APC_EXTENSIBLE) {
146 if(per_put_few_bits(po, 0, 1))
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;
156 memb_ptr = (const char *)sptr + elm->memb_offset;
159 if(ct && ct->range_bits >= 0) {
160 if(per_put_few_bits(po, present, ct->range_bits))
163 return elm->type->op->aper_encoder(elm->type, elm->encoding_constraints.per_constraints,
166 asn_enc_rval_t rval = {0,0,0};
167 if(specs->ext_start == -1)
169 int n = present - specs->ext_start;
171 if(n < 0) ASN__ENCODE_FAILED;
172 if(per_put_few_bits(po, n, 7)) ASN__ENCODE_FAILED;
175 if(aper_open_type_put(elm->type, elm->encoding_constraints.per_constraints,
179 ASN__ENCODED_OK(rval);