OER encode SEQUENCE
diff --git a/skeletons/constr_SEQUENCE_oer.c b/skeletons/constr_SEQUENCE_oer.c
index fba6702..c6d8609 100644
--- a/skeletons/constr_SEQUENCE_oer.c
+++ b/skeletons/constr_SEQUENCE_oer.c
@@ -50,6 +50,24 @@
return rval; \
} while(0)
+/*
+ * Return pointer to a member.
+ */
+static void **element_ptrptr(void *struct_ptr, asn_TYPE_member_t *elm) {
+ assert(elm->flags & ATF_POINTER);
+ /* Member is a pointer to another structure */
+ return (void **)((char *)struct_ptr + elm->memb_offset);
+}
+
+static void *element_ptr(void *struct_ptr, asn_TYPE_member_t *elm) {
+ if(elm->flags & ATF_POINTER) {
+ /* Member is a pointer to another structure */
+ return *(void **)((char *)struct_ptr + elm->memb_offset);
+ } else {
+ return (void *)((char *)struct_ptr + elm->memb_offset);
+ }
+}
+
asn_dec_rval_t
SEQUENCE_decode_oer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
asn_oer_constraints_t *constraints, void **struct_ptr,
@@ -90,15 +108,20 @@
*/
switch(ctx->phase) {
case 0: {
+ ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 0", td->name);
/*
* Fetch preamble.
*/
asn_per_data_t *preamble = ctx->ptr;
- int has_extensions = (specs->ext_before >= 0);
- size_t preamble_bits = (has_extensions + specs->roms_count);
- size_t preamble_bytes = (preamble_bits >> 3);
+ int has_extensions_bit = (specs->ext_before >= 0);
+ size_t preamble_bits = (has_extensions_bit + specs->roms_count);
+ size_t preamble_bytes = ((7 + preamble_bits) >> 3);
uint8_t *pbytes;
+ ASN_DEBUG(
+ "Expecting preamble bits %zu for %s (including %d extension bits)",
+ preamble_bits, td->name, has_extensions_bit);
+
if(size < preamble_bytes) {
ASN__DECODE_STARVED;
}
@@ -110,13 +133,14 @@
preamble->buffer = (const void *)pbytes;
memcpy(pbytes, ptr, preamble_bytes);
pbytes[preamble_bytes] = '\0'; /* Just in case */
- preamble->nboff = has_extensions;
+ preamble->nboff = has_extensions_bit;
preamble->nbits = preamble_bits;
ADVANCE(preamble_bytes);
}
NEXT_PHASE(ctx);
/* FALL THROUGH */
case 1: {
+ ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 1", td->name);
/* Decode components of the extension root */
asn_per_data_t *preamble = ctx->ptr;
size_t edx;
@@ -124,8 +148,11 @@
for(edx = (ctx->step >> 1); edx < td->elements_count;
edx++, ctx->step = (ctx->step & ~1) + 2) {
asn_TYPE_member_t *elm = &td->elements[edx];
+ void *memb_tmpptr; /* Temporary reference. */
void **memb_ptr2; /* Pointer to a pointer to a memmber */
+ ASN_DEBUG("Decoding %s->%s", td->name, elm->name);
+
if(ctx->step & 1) {
goto microphase2_decode_continues;
}
@@ -133,25 +160,18 @@
if(IN_EXTENSION_GROUP(specs, edx)) {
/* Ignore non-root components in PHASE 1 */
- continue;
+ break;
}
if(elm->optional) {
int32_t present = per_get_few_bits(preamble, 1);
if(present < 0) {
+ ASN_DEBUG("Presence map ended prematurely: %d", present);
RETURN(RC_FAIL);
} else if(present == 0) {
if(elm->default_value) {
- if(elm->flags & ATF_POINTER) {
- /* Member is a pointer to another structure */
- memb_ptr2 =
- (void **)((char *)st + elm->memb_offset);
- } else {
- void *memb_ptr = (char *)st + elm->memb_offset;
- memb_ptr2 = &memb_ptr;
- }
/* Fill-in DEFAULT */
- if(elm->default_value(1, memb_ptr2)) {
+ if(elm->default_value(1, element_ptrptr(st, elm))) {
RETURN(RC_FAIL);
}
}
@@ -170,8 +190,8 @@
/* Member is a pointer to another structure */
memb_ptr2 = (void **)((char *)st + elm->memb_offset);
} else {
- void *memb_ptr = (char *)st + elm->memb_offset;
- memb_ptr2 = &memb_ptr;
+ memb_tmpptr = (char *)st + elm->memb_offset;
+ memb_ptr2 = &memb_tmpptr; /* Ensure this & remains in scope! */
}
rval = elm->type->oer_decoder(opt_codec_ctx, elm->type,
@@ -182,9 +202,13 @@
ADVANCE(rval.consumed);
break;
case RC_WMORE:
+ ASN_DEBUG("More bytes needed at element %s \"%s\"", td->name,
+ elm->name);
ADVANCE(rval.consumed);
RETURN(RC_WMORE);
case RC_FAIL:
+ ASN_DEBUG("Decoding failed at element %s \"%s\"", td->name,
+ elm->name);
RETURN(RC_FAIL);
}
} /* for(all root members) */
@@ -193,12 +217,13 @@
NEXT_PHASE(ctx);
/* FALL THROUGH */
case 2: {
+ ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 2", td->name);
/* Cleanup preamble. */
asn_per_data_t *preamble = ctx->ptr;
asn_per_data_t *extadds;
- int has_extensions = (specs->ext_before >= 0);
+ int has_extensions_bit = (specs->ext_before >= 0);
int extensions_present =
- has_extensions && (((const uint8_t *)preamble->buffer)[0] & 0x80);
+ has_extensions_bit && (((const uint8_t *)preamble->buffer)[0] & 0x80);
uint8_t unused_bits;
size_t len = 0;
ssize_t len_len;
@@ -266,20 +291,12 @@
ctx->step = (specs->ext_after + 1);
/* Fall through */
case 3:
- for(; ctx->step < specs->ext_before; ctx->step++) {
+ ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 3", td->name);
+ for(; ctx->step < specs->ext_before - 1; ctx->step++) {
asn_per_data_t *extadds = ctx->ptr;
size_t edx = ctx->step;
asn_TYPE_member_t *elm = &td->elements[edx];
- void **memb_ptr2;
-
- if(elm->flags & ATF_POINTER) {
- /* Member is a pointer to another structure */
- memb_ptr2 = (void **)((char *)st + elm->memb_offset);
- } else {
- void *memb_ptr = (char *)st + elm->memb_offset;
- memb_ptr2 = &memb_ptr;
- assert(elm->flags & ATF_POINTER); /* Extensions are indirect */
- }
+ void **memb_ptr2 = element_ptrptr(st, elm);
switch(per_get_few_bits(extadds, 1)) {
case -1:
@@ -320,6 +337,7 @@
NEXT_PHASE(ctx);
/* Fall through */
case 4:
+ ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 4", td->name);
/* Read in the rest of Open Types while ignoring them */
for(;;) {
asn_per_data_t *extadds = ctx->ptr;
@@ -358,17 +376,151 @@
SEQUENCE_encode_oer(asn_TYPE_descriptor_t *td,
asn_oer_constraints_t *constraints, void *sptr,
asn_app_consume_bytes_f *cb, void *app_key) {
- asn_enc_rval_t er;
- const uint8_t *buf;
- const uint8_t *end;
- size_t useful_bytes;
- size_t req_bytes = 0;
- int encode_as_unsigned;
- int sign = 0;
+ asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
+ size_t computed_size = 0;
+ int has_extensions_bit = (specs->ext_before >= 0);
+ size_t preamble_bits = (has_extensions_bit + specs->roms_count);
+ uint32_t has_extensions = 0;
+ size_t edx;
+ int ret;
- er.encoded = -1;
+ if(preamble_bits) {
+ asn_per_outp_t preamble;
- return er;
+ memset(&preamble, 0, sizeof(preamble));
+ preamble.outper = cb;
+ preamble.op_key = app_key;
+
+ if(has_extensions_bit) {
+ for(edx = specs->ext_after + 1; edx < specs->ext_before - 1;
+ edx++) {
+ asn_TYPE_member_t *elm = &td->elements[edx];
+ if(element_ptr(sptr, elm)) {
+ has_extensions = 1;
+ break;
+ }
+ }
+ ret = per_put_few_bits(&preamble, has_extensions, 1);
+ assert(ret == 0);
+ if(ret < 0) {
+ ASN__ENCODE_FAILED;
+ }
+ }
+
+ /*
+ * Encode optional components bitmap.
+ */
+ if(specs->roms_count) {
+ for(edx = 0; edx < td->elements_count; edx++) {
+ asn_TYPE_member_t *elm = &td->elements[edx];
+
+ if(IN_EXTENSION_GROUP(specs, edx)) break;
+
+ if(elm->optional) {
+ uint32_t has_component = (element_ptr(sptr, elm) != NULL);
+ ret = per_put_few_bits(&preamble, has_component, 1);
+ if(ret < 0) {
+ ASN__ENCODE_FAILED;
+ }
+ }
+ }
+ }
+
+ per_put_aligned_flush(&preamble);
+ computed_size += preamble.flushed_bytes;
+ } /* if(preamble_bits) */
+
+ /*
+ * Put root components and extensions root.
+ */
+ for(edx = 0; edx < td->elements_count; edx++) {
+ asn_TYPE_member_t *elm = &td->elements[edx];
+ asn_enc_rval_t er;
+ void *memb_ptr;
+
+ if(IN_EXTENSION_GROUP(specs, edx)) break;
+
+ memb_ptr = element_ptr(sptr, elm);
+ if(!memb_ptr) {
+ if(elm->optional) continue;
+ /* Mandatory element is missing */
+ ASN__ENCODE_FAILED;
+ }
+ if(!elm->type->oer_encoder) {
+ ASN_DEBUG("OER encoder is not defined for type %s", elm->type->name);
+ ASN__ENCODE_FAILED;
+ }
+ er = elm->type->oer_encoder(elm->type, elm->oer_constraints, memb_ptr,
+ cb, app_key);
+ if(er.encoded == -1) {
+ ASN_DEBUG("... while encoding %s member \"%s\"\n", td->name,
+ elm->name);
+ return er;
+ }
+ computed_size += er.encoded;
+ }
+
+ /*
+ * Before encode extensions, encode extensions additions presense bitmap
+ # X.696 (08/2015) #16.4.
+ */
+ if(has_extensions) {
+ asn_per_outp_t extadds;
+
+ /* Special case allowing us to use exactly one byte for #8.6 */
+ size_t aoms_length_bits = specs->aoms_count;
+ size_t aoms_length_bytes = (7 + specs->aoms_count) >> 3;
+ uint8_t unused_bits = 0x07 & (8 - (aoms_length_bits & 0x07));
+
+ assert(1 + aoms_length_bytes <= 127);
+
+ memset(&extadds, 0, sizeof(extadds));
+ extadds.outper = cb;
+ extadds.op_key = app_key;
+
+ /* #8.6 length determinant */
+ ret = per_put_few_bits(&extadds, (1 + aoms_length_bytes), 8);
+ if(ret < 0) ASN__ENCODE_FAILED;
+
+ /* Number of unused bytes, #16.4.2 */
+ ret = per_put_few_bits(&extadds, unused_bits, 8);
+ if(ret < 0) ASN__ENCODE_FAILED;
+
+ /* Encode presence bitmap #16.4.3 */
+ for(edx = specs->ext_after + 1; edx < specs->ext_before - 1; edx++) {
+ asn_TYPE_member_t *elm = &td->elements[edx];
+ void *memb_ptr = element_ptr(sptr, elm);
+ ret |= per_put_few_bits(&extadds, memb_ptr ? 1 : 0, 1);
+ }
+ if(ret < 0) ASN__ENCODE_FAILED;
+
+ per_put_aligned_flush(&extadds);
+ computed_size += extadds.flushed_bytes;
+
+ /* Now, encode extensions */
+ for(edx = specs->ext_after + 1; edx < specs->ext_before - 1; edx++) {
+ asn_TYPE_member_t *elm = &td->elements[edx];
+ void *memb_ptr = element_ptr(sptr, elm);
+
+ if(memb_ptr) {
+ asn_enc_rval_t er = elm->type->oer_encoder(
+ elm->type, elm->oer_constraints, memb_ptr, cb, app_key);
+ if(er.encoded == -1) {
+ return er;
+ }
+ computed_size += er.encoded;
+ } else if(!elm->optional) {
+ ASN__ENCODE_FAILED;
+ }
+ }
+ } /* if(has_extensions) */
+
+
+ {
+ asn_enc_rval_t er = {0, 0, 0};
+ er.encoded = computed_size;
+ ASN__ENCODED_OK(er);
+ }
}
#endif /* ASN_DISABLE_OER_SUPPORT */