diff options
author | Lev Walkin <vlm@lionet.info> | 2005-11-26 11:25:14 +0000 |
---|---|---|
committer | Lev Walkin <vlm@lionet.info> | 2005-11-26 11:25:14 +0000 |
commit | 59b176ee355b3e82e6a8649b164c187c7a17a28f (patch) | |
tree | 6d864f02cd16eb75f4ae6e40199d1879d8363152 /skeletons/constr_SET_OF.c | |
parent | 708530582f5ba965fb596c3e189eec23c52337d9 (diff) |
upgrade: PER related changes
Diffstat (limited to 'skeletons/constr_SET_OF.c')
-rw-r--r-- | skeletons/constr_SET_OF.c | 94 |
1 files changed, 90 insertions, 4 deletions
diff --git a/skeletons/constr_SET_OF.c b/skeletons/constr_SET_OF.c index bd25b3d8..251da390 100644 --- a/skeletons/constr_SET_OF.c +++ b/skeletons/constr_SET_OF.c @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved. + * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>. + * All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ #include <asn_internal.h> @@ -356,7 +357,7 @@ SET_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr, if(!cb) { erval.encoded = computed_size; - return erval; + _ASN_ENCODED_OK(erval); } /* @@ -448,7 +449,7 @@ SET_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr, erval.encoded = computed_size; } - return erval; + _ASN_ENCODED_OK(erval); } #undef XER_ADVANCE @@ -748,7 +749,7 @@ cleanup: } free(encs); } - return er; + _ASN_ENCODED_OK(er); } int @@ -850,3 +851,88 @@ SET_OF_constraint(asn_TYPE_descriptor_t *td, const void *sptr, return 0; } + +asn_dec_rval_t +SET_OF_decode_uper(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_dec_rval_t rv; + asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; + asn_TYPE_member_t *elm = td->elements; /* Single one */ + void *st = *sptr; + asn_anonymous_set_ *list; + asn_per_constraint_t *ct; + int repeat = 0; + ssize_t nelems; + + /* + * Create the target structure if it is not present already. + */ + if(!st) { + st = *sptr = CALLOC(1, specs->struct_size); + if(!st) _ASN_DECODE_FAILED; + } + list = _A_SET_FROM_VOID(st); + + /* Figure out which constraints to use */ + if(constraints) ct = &constraints->size; + else if(td->per_constraints) ct = &td->per_constraints->size; + else ct = 0; + + if(ct && ct->flags & APC_EXTENSIBLE) { + int value = per_get_few_bits(pd, 1); + if(value < 0) _ASN_DECODE_FAILED; + if(value) ct = 0; /* Not restricted! */ + } + + if(ct && ct->effective_bits >= 0) { + /* X.691, #19.5: No length determinant */ + nelems = per_get_few_bits(pd, ct->effective_bits); + ASN_DEBUG("Preparing to fetch %ld+%ld elements from %s", + (long)nelems, ct->lower_bound, td->name); + if(nelems < 0) _ASN_DECODE_FAILED; + nelems += ct->lower_bound; + } else { + nelems = -1; + } + + do { + int i; + if(nelems < 0) { + nelems = uper_get_length(pd, + ct ? ct->effective_bits : -1, &repeat); + ASN_DEBUG("Got to decode %d elements (eff %d)", + nelems, ct ? ct->effective_bits : -1); + if(nelems < 0) _ASN_DECODE_FAILED; + } + + for(i = 0; i < nelems; i++) { + void *ptr = 0; + ASN_DEBUG("SET OF %s decoding", elm->type->name); + rv = elm->type->uper_decoder(opt_codec_ctx, elm->type, + elm->per_constraints, &ptr, pd); + ASN_DEBUG("%s SET OF %s decoded %d, %p", + td->name, elm->type->name, rv.code, ptr); + if(rv.code == RC_OK) { + if(ASN_SET_ADD(list, ptr) == 0) + continue; + ASN_DEBUG("Failed to add element into %s", + td->name); + /* Fall through */ + } else { + ASN_DEBUG("Failed decoding %s of %s (SET OF)", + elm->type->name, td->name); + } + if(ptr) elm->type->free_struct(elm->type, ptr, 0); + _ASN_DECODE_FAILED; + } + + nelems = -1; /* Allow uper_get_length() */ + } while(repeat); + + ASN_DEBUG("Decoded %s as SET OF", td->name); + + rv.code = RC_OK; + rv.consumed = 0; + return rv; +} + |