uper extensions decoding
git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@1307 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/skeletons/constr_SEQUENCE.c b/skeletons/constr_SEQUENCE.c
index 9f870f7..5e16f57 100644
--- a/skeletons/constr_SEQUENCE.c
+++ b/skeletons/constr_SEQUENCE.c
@@ -1026,12 +1026,168 @@
return 0;
}
+/*
+ * #10.1, #10.2
+ */
+static int
+uper_put_open_type(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ void *buf;
+ ssize_t size;
+
+ ASN_DEBUG("Encoding as open type %s", td->name);
+ size = uper_encode_to_new_buffer(td, constraints, sptr, &buf);
+ if(size <= 0) return -1;
+
+ ASN_DEBUG("Putting %s of length %d", td->name, size);
+ while(size) {
+ ssize_t maySave = uper_put_length(po, size);
+ if(maySave < 0) break;
+ if(per_put_many_bits(po, buf, maySave * 8)) break;
+ buf = (char *)buf + maySave;
+ size -= maySave;
+ }
+
+ if(size) {
+ FREEMEM(buf);
+ return -1;
+ }
+
+ return 0;
+}
+
+typedef struct uper_ugot_key {
+ asn_per_data_t oldpd; /* Old per data source */
+ size_t unclaimed;
+ int repeat;
+} uper_ugot_key;
+static int
+uper_ugot_refill(asn_per_data_t *pd) {
+ uper_ugot_key *arg = pd->refill_key;
+ ssize_t next_chunk_bytes, next_chunk_bits;
+ ssize_t consumed;
+ ssize_t avail;
+
+ asn_per_data_t *oldpd = &arg->oldpd;
+
+ /* Advance our position to where pd is */
+ consumed = (pd->buffer - oldpd->buffer) << 3;
+ ASN_DEBUG("Refilling [consumed: %d bits from %d (%d->%d)] now [%d (%d->%d)]",
+ consumed,
+ oldpd->nbits - oldpd->nboff, oldpd->nboff, oldpd->nbits,
+ pd->nbits - pd->nboff, pd->nboff, pd->nbits);
+ oldpd->nbits -= consumed;
+ oldpd->buffer = pd->buffer;
+ oldpd->nboff = pd->nboff;
+
+ if(arg->unclaimed) {
+ /* Refill the container */
+ if(per_get_few_bits(oldpd, 0))
+ return -1;
+ assert(0);
+ }
+
+ if(!arg->repeat) {
+ ASN_DEBUG("Want more but refill doesn't have it");
+ assert(0);
+ return -1;
+ }
+
+ next_chunk_bytes = uper_get_length(oldpd, -1, &arg->repeat);
+ ASN_DEBUG("Open type length %d bytes, old %d (%d->%d)",
+ next_chunk_bytes, oldpd->nbits - oldpd->nboff, oldpd->nboff, oldpd->nbits);
+ if(next_chunk_bytes < 0) return -1;
+ if(next_chunk_bytes == 0 || !arg->repeat)
+ pd->refill = 0; /* No more refills, naturally */
+ pd->buffer = oldpd->buffer;
+ pd->nboff = oldpd->nboff;
+ pd->nbits = oldpd->nbits;
+ next_chunk_bits = next_chunk_bytes << 3;
+ avail = pd->nbits - pd->nboff;
+ if(avail >= next_chunk_bits) {
+ pd->nbits = pd->nboff + next_chunk_bits;
+ arg->unclaimed = 0;
+ } else {
+ arg->unclaimed = next_chunk_bits - avail;
+ }
+ return 0;
+}
+
+asn_dec_rval_t
+uper_get_open_type(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+ uper_ugot_key arg;
+ asn_dec_rval_t rv;
+ ssize_t padding;
+
+ _ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx);
+
+ ASN_DEBUG("Getting open type from %d bits (%d+%d), %p", pd->nbits - pd->nboff, pd->nboff, pd->nbits, pd->buffer);
+ arg.oldpd = *pd;
+ pd->refill = uper_ugot_refill;
+ pd->refill_key = &arg;
+ pd->nbits = pd->nboff; /* 0 bits at this point, wait for refill */
+ arg.unclaimed = 0;
+ arg.repeat = 1;
+
+ rv = td->uper_decoder(opt_codec_ctx, td, constraints, sptr, pd);
+
+ /* Skip data not consumed by the decoder */
+ while(arg.unclaimed) {
+ int toget = 24;
+ if(arg.unclaimed < toget) {
+ toget = arg.unclaimed;
+ arg.unclaimed = 0;
+ } else {
+ arg.unclaimed -= toget;
+ }
+ switch(per_get_few_bits(pd, toget)) {
+ case -1: _ASN_DECODE_STARVED;
+ case 0: continue;
+ default:
+ /* Padding must be blank */
+ ASN_DEBUG("Non-blank unconsumed padding");
+ _ASN_DECODE_FAILED;
+ }
+ }
+
+ if(arg.repeat) {
+ ASN_DEBUG("Not consumed the whole thing");
+ rv.code = RC_FAIL;
+ return rv;
+ }
+
+ padding = pd->nbits - pd->nboff;
+ if(padding > 7) {
+ ASN_DEBUG("Too large padding in open type %d", padding);
+ rv.code = RC_FAIL;
+ return rv;
+ }
+
+ ASN_DEBUG("nboff = %d, nbits %d, padding = %d, plus %d/%p", pd->nboff, pd->nbits, padding, pd->buffer - arg.oldpd.buffer, arg.oldpd.buffer);
+ pd->nboff += padding;
+ assert((ssize_t)pd->nboff <= (ssize_t)pd->nbits);
+ pd->refill = arg.oldpd.refill;
+ pd->refill_key = arg.oldpd.refill_key;
+
+ return rv;
+}
+
+static int
+uper_skip_open_type(asn_codec_ctx_t *opt_codec_ctx, asn_per_data_t *pd) {
+ asn_dec_rval_t rv;
+ rv = uper_get_open_type(opt_codec_ctx, 0, 0, 0, pd);
+ if(rv.code != RC_OK)
+ return -1;
+ else
+ return 0;
+}
+
asn_dec_rval_t
SEQUENCE_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_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
void *st = *sptr; /* Target structure. */
- int extpresent = 0; /* Extension additions are present */
+ int extpresent; /* Extension additions are present */
uint8_t *opres; /* Presence of optional root members */
asn_per_data_t opmd;
asn_dec_rval_t rv;
@@ -1053,6 +1209,8 @@
if(specs->ext_before >= 0) {
extpresent = per_get_few_bits(pd, 1);
if(extpresent < 0) _ASN_DECODE_STARVED;
+ } else {
+ extpresent = 0;
}
/* Prepare a place and read-in the presence bitmap */
@@ -1077,12 +1235,14 @@
/*
* Get the sequence ROOT elements.
*/
- for(edx = 0; edx < ((specs->ext_before < 0)
- ? td->elements_count : specs->ext_before - 1); edx++) {
+ for(edx = 0; edx < td->elements_count; edx++) {
asn_TYPE_member_t *elm = &td->elements[edx];
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
+ if(IN_EXTENSION_GROUP(specs, edx))
+ continue;
+
/* Fetch the pointer to this member */
if(elm->flags & ATF_POINTER) {
memb_ptr2 = (void **)((char *)st + elm->memb_offset);
@@ -1124,73 +1284,110 @@
}
}
+ /* Optionality map is not needed anymore */
+ FREEMEM(opres);
+
/*
* Deal with extensions.
*/
if(extpresent) {
- ASN_DEBUG("Extensibility for %s: NOT IMPLEMENTED", td->name);
- _ASN_DECODE_FAILED;
- } else {
- for(edx = specs->roms_count; edx < specs->roms_count
- + specs->aoms_count; edx++) {
- asn_TYPE_member_t *elm = &td->elements[edx];
- void *memb_ptr; /* Pointer to the member */
- void **memb_ptr2; /* Pointer to that pointer */
+ ssize_t bmlength;
+ uint8_t *epres; /* Presence of extension members */
+ asn_per_data_t epmd;
- if(!elm->default_value) continue;
+ bmlength = uper_get_nslength(pd);
+ if(bmlength < 0) _ASN_DECODE_STARVED;
- /* Fetch the pointer to this member */
- if(elm->flags & ATF_POINTER) {
- memb_ptr2 = (void **)((char *)st
- + elm->memb_offset);
- } else {
- memb_ptr = (char *)st + elm->memb_offset;
- memb_ptr2 = &memb_ptr;
+ ASN_DEBUG("Extensions %d present in %s", bmlength, td->name);
+
+ epres = (uint8_t *)MALLOC((bmlength + 15) >> 3);
+ if(!epres) _ASN_DECODE_STARVED;
+
+ /* Get the extensions map */
+ if(per_get_many_bits(pd, epres, 0, bmlength))
+ _ASN_DECODE_STARVED;
+
+ epmd.buffer = epres;
+ epmd.nboff = 0;
+ epmd.nbits = bmlength;
+ ASN_DEBUG("Read in extensions bitmap for %s of %d bits (%x..)",
+ td->name, bmlength, *epres);
+
+ /* Go over extensions and read them in */
+ for(edx = specs->ext_after + 1; edx < td->elements_count; edx++) {
+ asn_TYPE_member_t *elm = &td->elements[edx];
+ void *memb_ptr; /* Pointer to the member */
+ void **memb_ptr2; /* Pointer to that pointer */
+ int present;
+
+ if(!IN_EXTENSION_GROUP(specs, edx)) {
+ ASN_DEBUG("%d is not extension", edx);
+ continue;
+ }
+
+ /* Fetch the pointer to this member */
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr2 = (void **)((char *)st + elm->memb_offset);
+ } else {
+ memb_ptr = (void *)((char *)st + elm->memb_offset);
+ memb_ptr2 = &memb_ptr;
+ }
+
+ present = per_get_few_bits(&epmd, 1);
+ if(present <= 0) {
+ if(present < 0) break; /* No more extensions */
+ continue;
+ }
+
+ ASN_DEBUG("Decoding member %s in %s %p", elm->name, td->name, *memb_ptr2);
+ rv = uper_get_open_type(opt_codec_ctx, elm->type,
+ elm->per_constraints, memb_ptr2, pd);
+ if(rv.code != RC_OK) {
+ FREEMEM(epres);
+ return rv;
+ }
+ }
+
+ /* Skip over overflow extensions which aren't present
+ * in this system's version of the protocol */
+ while(per_get_few_bits(&epmd, 1) >= 0) {
+ if(uper_skip_open_type(opt_codec_ctx, pd)) {
+ FREEMEM(epres);
+ _ASN_DECODE_STARVED;
}
+ }
- /* Set default value */
- if(elm->default_value(1, memb_ptr2)) {
- FREEMEM(opres);
- _ASN_DECODE_FAILED;
- }
+ FREEMEM(epres);
+ }
+
+ /* Fill DEFAULT members in extensions */
+ for(edx = specs->roms_count; edx < specs->roms_count
+ + specs->aoms_count; edx++) {
+ asn_TYPE_member_t *elm = &td->elements[edx];
+ void **memb_ptr2; /* Pointer to member pointer */
+
+ if(!elm->default_value) continue;
+
+ /* Fetch the pointer to this member */
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr2 = (void **)((char *)st
+ + elm->memb_offset);
+ if(*memb_ptr2) continue;
+ } else {
+ continue; /* Extensions are all optionals */
+ }
+
+ /* Set default value */
+ if(elm->default_value(1, memb_ptr2)) {
+ _ASN_DECODE_FAILED;
}
}
rv.consumed = 0;
rv.code = RC_OK;
- FREEMEM(opres);
return rv;
}
-/*
- * #10.1, #10.2
- */
-static int
-uper_put_open_type(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
- void *buf;
- ssize_t size;
-
- ASN_DEBUG("Encoding as open type %s", td->name);
- size = uper_encode_to_new_buffer(td, constraints, sptr, &buf);
- if(size <= 0) return -1;
-
- ASN_DEBUG("Putting %s of length %d", td->name, size);
- while(size) {
- ssize_t maySave = uper_put_length(po, size);
- if(maySave < 0) break;
- if(per_put_many_bits(po, buf, maySave * 8)) break;
- buf = (char *)buf + maySave;
- size -= maySave;
- }
-
- if(size) {
- FREEMEM(buf);
- return -1;
- }
-
- return 0;
-}
-
static int
SEQUENCE_handle_extensions(asn_TYPE_descriptor_t *td, void *sptr,
asn_per_outp_t *po1, asn_per_outp_t *po2) {
@@ -1336,7 +1533,6 @@
if(elm->default_value && elm->default_value(0, memb_ptr2) == 1)
continue;
- ASN_DEBUG("encoding root %d", edx);
er = elm->type->uper_encoder(elm->type, elm->per_constraints,
*memb_ptr2, po);
if(er.encoded == -1)