port/merge Eurecom APER support from OPENAIRMME
Eurecom has developed APER support for asn1c as part of the OPENAIRMME
softare (a LTE MME). This is too important to let it bit-rout out
of asn1c. Let's forward-port and merge it.
diff --git a/skeletons/constr_CHOICE.c b/skeletons/constr_CHOICE.c
index f366f75..00863a4 100644
--- a/skeletons/constr_CHOICE.c
+++ b/skeletons/constr_CHOICE.c
@@ -904,7 +904,88 @@
elm->name, td->name, rv.code);
return rv;
}
-
+
+asn_dec_rval_t
+CHOICE_decode_aper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+ asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
+ asn_dec_rval_t rv;
+ asn_per_constraint_t *ct;
+ asn_TYPE_member_t *elm; /* CHOICE's element */
+ void *memb_ptr;
+ void **memb_ptr2;
+ void *st = *sptr;
+ int value;
+
+ if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
+ _ASN_DECODE_FAILED;
+
+ /*
+ * Create the target structure if it is not present already.
+ */
+ if(!st) {
+ st = *sptr = CALLOC(1, specs->struct_size);
+ if(!st) _ASN_DECODE_FAILED;
+ }
+
+ if(constraints) ct = &constraints->value;
+ else if(td->per_constraints) ct = &td->per_constraints->value;
+ else ct = 0;
+
+ if(ct && ct->flags & APC_EXTENSIBLE) {
+ value = per_get_few_bits(pd, 1);
+ if(value < 0) _ASN_DECODE_STARVED;
+ if(value) ct = 0; /* Not restricted */
+ }
+
+ if(ct && ct->range_bits >= 0) {
+ value = per_get_few_bits(pd, ct->range_bits);
+ if(value < 0) _ASN_DECODE_STARVED;
+ ASN_DEBUG("CHOICE %s got index %d in range %d",
+ td->name, value, ct->range_bits);
+ if(value > ct->upper_bound)
+ _ASN_DECODE_FAILED;
+ } else {
+ if(specs->ext_start == -1)
+ _ASN_DECODE_FAILED;
+ value = uper_get_nsnnwn(pd);
+ if(value < 0) _ASN_DECODE_STARVED;
+ value += specs->ext_start;
+ if(value >= td->elements_count)
+ _ASN_DECODE_FAILED;
+ }
+
+ /* Adjust if canonical order is different from natural order */
+ if(specs->canonical_order)
+ value = specs->canonical_order[value];
+
+ /* Set presence to be able to free it later */
+ _set_present_idx(st, specs->pres_offset, specs->pres_size, value + 1);
+
+ elm = &td->elements[value];
+ if(elm->flags & ATF_POINTER) {
+ /* Member is a pointer to another structure */
+ memb_ptr2 = (void **)((char *)st + elm->memb_offset);
+ } else {
+ memb_ptr = (char *)st + elm->memb_offset;
+ memb_ptr2 = &memb_ptr;
+ }
+ ASN_DEBUG("Discovered CHOICE %s encodes %s", td->name, elm->name);
+
+ if(ct && ct->range_bits >= 0) {
+ rv = elm->type->aper_decoder(opt_codec_ctx, elm->type,
+ elm->per_constraints, memb_ptr2, pd);
+ } else {
+ rv = uper_open_type_get(opt_codec_ctx, elm->type,
+ elm->per_constraints, memb_ptr2, pd);
+ }
+
+ if(rv.code != RC_OK)
+ ASN_DEBUG("Failed to decode %s in %s (CHOICE) %d",
+ elm->name, td->name, rv.code);
+ return rv;
+}
+
asn_enc_rval_t
CHOICE_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
@@ -917,7 +998,7 @@
if(!sptr) _ASN_ENCODE_FAILED;
- ASN_DEBUG("Encoding %s as CHOICE", td->name);
+ ASN_DEBUG("Encoding %s as CHOICE using UPER", td->name);
if(constraints) ct = &constraints->value;
else if(td->per_constraints) ct = &td->per_constraints->value;
@@ -987,7 +1068,87 @@
_ASN_ENCODED_OK(rval);
}
}
-
+
+asn_enc_rval_t
+CHOICE_encode_aper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
+ asn_TYPE_member_t *elm; /* CHOICE's element */
+ asn_per_constraint_t *ct;
+ void *memb_ptr;
+ int present;
+
+ if(!sptr) _ASN_ENCODE_FAILED;
+
+ ASN_DEBUG("Encoding %s as CHOICE using ALIGNED PER", td->name);
+
+ if(constraints) ct = &constraints->value;
+ else if(td->per_constraints) ct = &td->per_constraints->value;
+ else ct = 0;
+
+ present = _fetch_present_idx(sptr,
+ specs->pres_offset, specs->pres_size);
+
+ /*
+ * If the structure was not initialized properly, it cannot be encoded:
+ * can't deduce what to encode in the choice type.
+ */
+ if(present <= 0 || present > td->elements_count)
+ _ASN_ENCODE_FAILED;
+ else
+ present--;
+
+ /* Adjust if canonical order is different from natural order */
+ if(specs->canonical_order)
+ present = specs->canonical_order[present];
+
+ ASN_DEBUG("Encoding %s CHOICE element %d", td->name, present);
+
+ if(ct && ct->range_bits >= 0) {
+ if(present < ct->lower_bound
+ || present > ct->upper_bound) {
+ if(ct->flags & APC_EXTENSIBLE) {
+ if(per_put_few_bits(po, 1, 1))
+ _ASN_ENCODE_FAILED;
+ } else {
+ _ASN_ENCODE_FAILED;
+ }
+ ct = 0;
+ }
+ }
+ if(ct && ct->flags & APC_EXTENSIBLE) {
+ if(per_put_few_bits(po, 0, 1))
+ _ASN_ENCODE_FAILED;
+ }
+
+ elm = &td->elements[present];
+ if(elm->flags & ATF_POINTER) {
+ /* Member is a pointer to another structure */
+ memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
+ if(!memb_ptr) _ASN_ENCODE_FAILED;
+ } else {
+ memb_ptr = (char *)sptr + elm->memb_offset;
+ }
+
+ if(ct && ct->range_bits >= 0) {
+ if(per_put_few_bits(po, present, ct->range_bits))
+ _ASN_ENCODE_FAILED;
+
+ return elm->type->aper_encoder(elm->type, elm->per_constraints,
+ memb_ptr, po);
+ } else {
+ asn_enc_rval_t rval;
+ if(specs->ext_start == -1)
+ _ASN_ENCODE_FAILED;
+ if(aper_put_nsnnwn(po, ct->range_bits, present - specs->ext_start))
+ _ASN_ENCODE_FAILED;
+ if(aper_open_type_put(elm->type, elm->per_constraints,
+ memb_ptr, po))
+ _ASN_ENCODE_FAILED;
+ rval.encoded = 0;
+ _ASN_ENCODED_OK(rval);
+ }
+}
int
CHOICE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,