decode Open Type in XER
diff --git a/skeletons/Makefile.am b/skeletons/Makefile.am
index 1af93c2..3d33484 100644
--- a/skeletons/Makefile.am
+++ b/skeletons/Makefile.am
@@ -42,7 +42,8 @@
NumericString.c NumericString.h \
OBJECT_IDENTIFIER.c OBJECT_IDENTIFIER.h \
OCTET_STRING.c OCTET_STRING.h \
- OCTET_STRING_oer.c \
+ OCTET_STRING_oer.c \
+ OPEN_TYPE.c OPEN_TYPE.h \
ObjectDescriptor.c ObjectDescriptor.h \
PrintableString.c PrintableString.h \
REAL.c REAL.h \
diff --git a/skeletons/OPEN_TYPE.c b/skeletons/OPEN_TYPE.c
index 6f90028..6c73eef 100644
--- a/skeletons/OPEN_TYPE.c
+++ b/skeletons/OPEN_TYPE.c
@@ -23,6 +23,171 @@
0, /* Use generic outmost tag fetcher */
};
+#undef XER_ADVANCE
+#define XER_ADVANCE(num_bytes) \
+ do { \
+ size_t num = num_bytes; \
+ ptr = ((const char *)ptr) + num; \
+ size -= num; \
+ consumed_myself += num; \
+ } while(0)
+
+asn_dec_rval_t
+OPEN_TYPE_xer_get(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+ void *sptr, asn_TYPE_member_t *elm, const void *ptr,
+ size_t size) {
+ size_t consumed_myself = 0;
+ asn_type_selector_result_t selected;
+ void *memb_ptr; /* Pointer to the member */
+ void **memb_ptr2; /* Pointer to that pointer */
+ void *inner_value;
+ const char *xml_tag;
+ asn_dec_rval_t rv;
+
+ int xer_context = 0;
+ ssize_t ch_size;
+ pxer_chunk_type_e ch_type;
+
+ if(!(elm->flags & ATF_OPEN_TYPE) || !elm->type_selector) {
+ ASN__DECODE_FAILED;
+ }
+
+ selected = elm->type_selector(td, sptr);
+ if(!selected.presence_index) {
+ ASN__DECODE_FAILED;
+ }
+
+ /* Fetch the pointer to this member */
+ assert(elm->flags == ATF_OPEN_TYPE);
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
+ } else {
+ memb_ptr = (char *)sptr + elm->memb_offset;
+ memb_ptr2 = &memb_ptr;
+ }
+ if(*memb_ptr2 != NULL) {
+ /* Make sure we reset the structure first before encoding */
+ if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0)
+ != 0) {
+ ASN__DECODE_FAILED;
+ }
+ }
+
+ /*
+ * Confirm wrapper.
+ */
+ for(;;) {
+ ch_size = xer_next_token(&xer_context, ptr, size, &ch_type);
+ if(ch_size <= 0) {
+ ASN__DECODE_FAILED;
+ } else {
+ switch(ch_type) {
+ case PXER_WMORE:
+ ASN__DECODE_STARVED;
+ case PXER_COMMENT:
+ case PXER_TEXT:
+ XER_ADVANCE(ch_size);
+ continue;
+ case PXER_TAG:
+ break;
+ }
+ break;
+ }
+ }
+
+ /*
+ * Wrapper value confirmed.
+ */
+ switch(xer_check_tag(ptr, ch_size, elm->name)) {
+ case XCT_OPENING:
+ XER_ADVANCE(ch_size);
+ break;
+ case XCT_BROKEN:
+ default:
+ ASN__DECODE_FAILED;
+ }
+
+ inner_value =
+ (char *)*memb_ptr2
+ + elm->type->elements[selected.presence_index - 1].memb_offset;
+
+ rv = selected.type_descriptor->op->xer_decoder(
+ opt_codec_ctx, selected.type_descriptor, &inner_value, NULL, ptr, size);
+ XER_ADVANCE(rv.consumed);
+ rv.consumed = 0;
+ switch(rv.code) {
+ case RC_OK:
+ if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
+ selected.presence_index)
+ == 0) {
+ break;
+ } else {
+ rv.code = RC_FAIL;
+ }
+ /* Fall through */
+ case RC_FAIL:
+ /* Point to a best position where failure occurred */
+ rv.consumed = consumed_myself;
+ /* Fall through */
+ case RC_WMORE:
+ /* Wrt. rv.consumed==0:
+ * In case a genuine RC_WMORE, the whole Open Type decoding
+ * will have to be restarted.
+ */
+ if(*memb_ptr2) {
+ asn_CHOICE_specifics_t *specs = selected.type_descriptor->specifics;
+ if(elm->flags & ATF_POINTER) {
+ ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
+ *memb_ptr2 = NULL;
+ } else {
+ ASN_STRUCT_FREE_CONTENTS_ONLY(*selected.type_descriptor,
+ inner_value);
+ memset(*memb_ptr2, 0, specs->struct_size);
+ }
+ }
+ return rv;
+ }
+
+ /*
+ * Finalize wrapper.
+ */
+ for(;;) {
+ ch_size = xer_next_token(&xer_context, ptr, size, &ch_type);
+ if(ch_size <= 0) {
+ ASN__DECODE_FAILED;
+ } else {
+ switch(ch_type) {
+ case PXER_WMORE:
+ ASN__DECODE_STARVED;
+ case PXER_COMMENT:
+ case PXER_TEXT:
+ XER_ADVANCE(ch_size);
+ continue;
+ case PXER_TAG:
+ break;
+ }
+ break;
+ }
+ }
+
+ /*
+ * Wrapper value confirmed.
+ */
+ switch(xer_check_tag(ptr, ch_size, elm->name)) {
+ case XCT_CLOSING:
+ XER_ADVANCE(ch_size);
+ break;
+ case XCT_BROKEN:
+ default:
+ ASN__DECODE_FAILED;
+ }
+
+ rv.consumed += consumed_myself;
+
+ return rv;
+}
+
+
#ifndef ASN_DISABLE_PER_SUPPORT
asn_dec_rval_t
@@ -32,6 +197,7 @@
asn_type_selector_result_t selected;
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
+ void *inner_value;
asn_dec_rval_t rv;
if(!(elm->flags & ATF_OPEN_TYPE) || !elm->type_selector) {
@@ -59,7 +225,7 @@
}
}
- void *inner_value =
+ inner_value =
(char *)*memb_ptr2
+ elm->type->elements[selected.presence_index - 1].memb_offset;
diff --git a/skeletons/OPEN_TYPE.h b/skeletons/OPEN_TYPE.h
index 060675a..ff49ada 100644
--- a/skeletons/OPEN_TYPE.h
+++ b/skeletons/OPEN_TYPE.h
@@ -28,11 +28,11 @@
* Decode an Open Type which is potentially constraiend
* by the other members of the parent structure.
*/
-asn_dec_rval_t OPEN_TYPE_uper_get(asn_codec_ctx_t *opt_codec_ctx,
- asn_TYPE_descriptor_t *parent_type,
- void *parent_structure,
- asn_TYPE_member_t *element,
- asn_per_data_t *pd);
+asn_dec_rval_t OPEN_TYPE_xer_get(asn_codec_ctx_t *opt_codec_ctx,
+ asn_TYPE_descriptor_t *parent_type,
+ void *parent_structure,
+ asn_TYPE_member_t *element, const void *ptr,
+ size_t size);
asn_dec_rval_t OPEN_TYPE_oer_get(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *parent_type,
@@ -40,6 +40,12 @@
asn_TYPE_member_t *element,
const void *ptr, size_t size);
+asn_dec_rval_t OPEN_TYPE_uper_get(asn_codec_ctx_t *opt_codec_ctx,
+ asn_TYPE_descriptor_t *parent_type,
+ void *parent_structure,
+ asn_TYPE_member_t *element,
+ asn_per_data_t *pd);
+
#ifdef __cplusplus
}
diff --git a/skeletons/constr_SEQUENCE.c b/skeletons/constr_SEQUENCE.c
index b863d5f..ba74067 100644
--- a/skeletons/constr_SEQUENCE.c
+++ b/skeletons/constr_SEQUENCE.c
@@ -594,12 +594,13 @@
#undef XER_ADVANCE
-#define XER_ADVANCE(num_bytes) do { \
- size_t num = num_bytes; \
- buf_ptr = ((const char *)buf_ptr) + num;\
- size -= num; \
- consumed_myself += num; \
- } while(0)
+#define XER_ADVANCE(num_bytes) \
+ do { \
+ size_t num = (num_bytes); \
+ ptr = ((const char *)ptr) + num; \
+ size -= num; \
+ consumed_myself += num; \
+ } while(0)
/*
* Decode the XER (XML) data.
@@ -607,7 +608,7 @@
asn_dec_rval_t
SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
void **struct_ptr, const char *opt_mname,
- const void *buf_ptr, size_t size) {
+ const void *ptr, size_t size) {
/*
* Bring closer parts of structure description.
*/
@@ -672,10 +673,14 @@
memb_ptr2 = &memb_ptr;
}
- /* Invoke the inner type decoder, m.b. multiple times */
- tmprval = elm->type->op->xer_decoder(opt_codec_ctx,
- elm->type, memb_ptr2, elm->name,
- buf_ptr, size);
+ if((elm->flags & ATF_OPEN_TYPE) && elm->type_selector) {
+ tmprval = OPEN_TYPE_xer_get(opt_codec_ctx, td, st, elm, ptr, size);
+ } else {
+ /* Invoke the inner type decoder, m.b. multiple times */
+ tmprval = elm->type->op->xer_decoder(opt_codec_ctx,
+ elm->type, memb_ptr2, elm->name,
+ ptr, size);
+ }
XER_ADVANCE(tmprval.consumed);
if(tmprval.code != RC_OK)
RETURN(tmprval.code);
@@ -689,14 +694,14 @@
/*
* Get the next part of the XML stream.
*/
- ch_size = xer_next_token(&ctx->context, buf_ptr, size,
+ ch_size = xer_next_token(&ctx->context, ptr, size,
&ch_type);
if(ch_size == -1) {
RETURN(RC_FAIL);
- } else {
+ } else {
switch(ch_type) {
- case PXER_WMORE:
- RETURN(RC_WMORE);
+ case PXER_WMORE:
+ RETURN(RC_WMORE);
case PXER_COMMENT: /* Got XML comment */
case PXER_TEXT: /* Ignore free-standing text */
XER_ADVANCE(ch_size); /* Skip silently */
@@ -706,7 +711,7 @@
}
}
- tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
+ tcv = xer_check_tag(ptr, ch_size, xml_tag);
ASN_DEBUG("XER/SEQUENCE: tcv = %d, ph=%d [%s]",
tcv, ctx->phase, xml_tag);
@@ -782,8 +787,7 @@
edx_end = td->elements_count;
for(n = edx; n < edx_end; n++) {
elm = &td->elements[n];
- tcv = xer_check_tag(buf_ptr,
- ch_size, elm->name);
+ tcv = xer_check_tag(ptr, ch_size, elm->name);
switch(tcv) {
case XCT_BOTH:
case XCT_OPENING:
@@ -836,12 +840,12 @@
}
ASN_DEBUG("Unexpected XML tag in SEQUENCE [%c%c%c%c%c%c]",
- size>0?((const char *)buf_ptr)[0]:'.',
- size>1?((const char *)buf_ptr)[1]:'.',
- size>2?((const char *)buf_ptr)[2]:'.',
- size>3?((const char *)buf_ptr)[3]:'.',
- size>4?((const char *)buf_ptr)[4]:'.',
- size>5?((const char *)buf_ptr)[5]:'.');
+ size>0?((const char *)ptr)[0]:'.',
+ size>1?((const char *)ptr)[1]:'.',
+ size>2?((const char *)ptr)[2]:'.',
+ size>3?((const char *)ptr)[3]:'.',
+ size>4?((const char *)ptr)[4]:'.',
+ size>5?((const char *)ptr)[5]:'.');
break;
}
@@ -1135,7 +1139,7 @@
if((elm->flags & ATF_OPEN_TYPE) && elm->type_selector) {
rv = OPEN_TYPE_uper_get(opt_codec_ctx, td, st, elm, pd);
} else {
- rv = elm->type->op->uper_decoder(opt_codec_ctx, elm->type,
+ rv = elm->type->op->uper_decoder(opt_codec_ctx, elm->type,
elm->per_constraints, memb_ptr2, pd);
}
if(rv.code != RC_OK) {