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 <uper_opentype.h>
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,
15 const asn_CHOICE_specifics_t *specs =
16 (const asn_CHOICE_specifics_t *)td->specifics;
18 const asn_per_constraint_t *ct;
19 asn_TYPE_member_t *elm; /* CHOICE's element */
25 if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))
29 * Create the target structure if it is not present already.
32 st = *sptr = CALLOC(1, specs->struct_size);
33 if(!st) ASN__DECODE_FAILED;
36 if(constraints) ct = &constraints->value;
37 else if(td->encoding_constraints.per_constraints) ct = &td->encoding_constraints.per_constraints->value;
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 */
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)
54 if(specs->ext_start == -1)
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)
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);
70 /* Set presence to be able to free it later */
71 _set_present_idx(st, specs->pres_offset, specs->pres_size, value + 1);
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);
78 memb_ptr = (char *)st + elm->memb_offset;
79 memb_ptr2 = &memb_ptr;
81 ASN_DEBUG("Discovered CHOICE %s encodes %s", td->name, elm->name);
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,
88 rv = uper_open_type_get(opt_codec_ctx, elm->type,
89 elm->encoding_constraints.per_constraints,
94 ASN_DEBUG("Failed to decode %s in %s (CHOICE) %d",
95 elm->name, td->name, rv.code);
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;
110 if(!sptr) ASN__ENCODE_FAILED;
112 ASN_DEBUG("Encoding %s as CHOICE", td->name);
114 if(constraints) ct = &constraints->value;
115 else if(td->encoding_constraints.per_constraints)
116 ct = &td->encoding_constraints.per_constraints->value;
119 present = _fetch_present_idx(sptr, specs->pres_offset, specs->pres_size);
122 * If the structure was not initialized properly, it cannot be encoded:
123 * can't deduce what to encode in the choice type.
125 if(present == 0 || present > td->elements_count)
130 ASN_DEBUG("Encoding %s CHOICE element %d", td->name, present);
132 /* Adjust if canonical order is different from natural order */
133 if(specs->to_canonical_order)
134 present_enc = specs->to_canonical_order[present];
136 present_enc = present;
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) {
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))
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))
161 elm = &td->elements[present];
162 ASN_DEBUG("CHOICE member \"%s\" %d (as %d)", elm->name, present,
164 if(elm->flags & ATF_POINTER) {
165 /* Member is a pointer to another structure */
167 *(const void *const *)((const char *)sptr + elm->memb_offset);
168 if(!memb_ptr) ASN__ENCODE_FAILED;
170 memb_ptr = (const char *)sptr + elm->memb_offset;
173 if(ct && ct->range_bits >= 0) {
174 if(per_put_few_bits(po, present_enc, ct->range_bits))
177 return elm->type->op->uper_encoder(
178 elm->type, elm->encoding_constraints.per_constraints, memb_ptr, po);
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))
184 if(uper_open_type_put(elm->type,
185 elm->encoding_constraints.per_constraints,
189 ASN__ENCODED_OK(rval);