diff options
author | Harald Welte <laforge@gnumonks.org> | 2015-08-31 08:56:53 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2015-08-31 09:35:13 +0200 |
commit | 41b85d5597119fa8105dc0641ffe5cd1bbae39b2 (patch) | |
tree | 1a425d76fafe089cca547eb9c79c6a9a631c34e2 /src/constr_CHOICE.c | |
parent | f6b9173b02bfac093177cf6fd0f48ad56c5786c7 (diff) |
update to asn1c aper branch commit 6e00cbce7304a6972e82a12bb5fa82e41fa541be
which is closes to Lev Walkins master 62913d8b8e1eb96d74315ff748475ca818b69752
Diffstat (limited to 'src/constr_CHOICE.c')
-rw-r--r-- | src/constr_CHOICE.c | 194 |
1 files changed, 179 insertions, 15 deletions
diff --git a/src/constr_CHOICE.c b/src/constr_CHOICE.c index 4f0d992..18c24cd 100644 --- a/src/constr_CHOICE.c +++ b/src/constr_CHOICE.c @@ -183,11 +183,11 @@ CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, } do { - asn_TYPE_tag2member_t *t2m; + const asn_TYPE_tag2member_t *t2m; asn_TYPE_tag2member_t key; key.el_tag = tlv_tag; - t2m = (asn_TYPE_tag2member_t *)bsearch(&key, + t2m = (const asn_TYPE_tag2member_t *)bsearch(&key, specs->tag2el, specs->tag2el_count, sizeof(specs->tag2el[0]), _search4tag); if(t2m) { @@ -445,7 +445,7 @@ CHOICE_encode_der(asn_TYPE_descriptor_t *td, void *sptr, } ber_tlv_tag_t -CHOICE_outmost_tag(asn_TYPE_descriptor_t *td, const void *ptr, int tag_mode, ber_tlv_tag_t tag) { +CHOICE_outmost_tag(const asn_TYPE_descriptor_t *td, const void *ptr, int tag_mode, ber_tlv_tag_t tag) { asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; int present; @@ -458,7 +458,7 @@ CHOICE_outmost_tag(asn_TYPE_descriptor_t *td, const void *ptr, int tag_mode, ber present = _fetch_present_idx(ptr, specs->pres_offset, specs->pres_size); if(present > 0 || present <= td->elements_count) { - asn_TYPE_member_t *elm = &td->elements[present-1]; + const asn_TYPE_member_t *elm = &td->elements[present-1]; const void *memb_ptr; if(elm->flags & ATF_POINTER) { @@ -535,7 +535,7 @@ CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr, #undef XER_ADVANCE #define XER_ADVANCE(num_bytes) do { \ size_t num = num_bytes; \ - buf_ptr = ((const char *)buf_ptr) + num;\ + buf_ptr = (const void *)(((const char *)buf_ptr) + num); \ size -= num; \ consumed_myself += num; \ } while(0) @@ -904,7 +904,88 @@ CHOICE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, 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) { @@ -913,10 +994,11 @@ CHOICE_encode_uper(asn_TYPE_descriptor_t *td, asn_per_constraint_t *ct; void *memb_ptr; int present; + int present_enc; 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; @@ -934,15 +1016,17 @@ CHOICE_encode_uper(asn_TYPE_descriptor_t *td, else present--; + ASN_DEBUG("Encoding %s CHOICE element %d", td->name, 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); + present_enc = specs->canonical_order[present]; + else + present_enc = present; if(ct && ct->range_bits >= 0) { - if(present < ct->lower_bound - || present > ct->upper_bound) { + if(present_enc < ct->lower_bound + || present_enc > ct->upper_bound) { if(ct->flags & APC_EXTENSIBLE) { if(per_put_few_bits(po, 1, 1)) _ASN_ENCODE_FAILED; @@ -966,7 +1050,7 @@ CHOICE_encode_uper(asn_TYPE_descriptor_t *td, } if(ct && ct->range_bits >= 0) { - if(per_put_few_bits(po, present, ct->range_bits)) + if(per_put_few_bits(po, present_enc, ct->range_bits)) _ASN_ENCODE_FAILED; return elm->type->uper_encoder(elm->type, elm->per_constraints, @@ -975,7 +1059,7 @@ CHOICE_encode_uper(asn_TYPE_descriptor_t *td, asn_enc_rval_t rval; if(specs->ext_start == -1) _ASN_ENCODE_FAILED; - if(uper_put_nsnnwn(po, present - specs->ext_start)) + if(uper_put_nsnnwn(po, present_enc - specs->ext_start)) _ASN_ENCODE_FAILED; if(uper_open_type_put(elm->type, elm->per_constraints, memb_ptr, po)) @@ -984,7 +1068,87 @@ CHOICE_encode_uper(asn_TYPE_descriptor_t *td, _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, |