extensions support
git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@668 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/skeletons/constr_CHOICE.c b/skeletons/constr_CHOICE.c
index b136065..175ef24 100644
--- a/skeletons/constr_CHOICE.c
+++ b/skeletons/constr_CHOICE.c
@@ -569,7 +569,6 @@
asn_dec_rval_t rval; /* Return value of a decoder */
ssize_t consumed_myself = 0; /* Consumed bytes from ptr */
- int xer_state; /* XER low level parsing context */
int edx; /* Element index */
/*
@@ -593,7 +592,7 @@
* Phase 2: Processing inner type.
* Phase 3: Only waiting for closing tag
*/
- for(xer_state = ctx->left, edx = ctx->step; ctx->phase <= 3;) {
+ for(edx = ctx->step; ctx->phase <= 3;) {
pxer_chunk_type_e ch_type; /* XER chunk type */
ssize_t ch_size; /* Chunk size */
xer_check_tag_e tcv; /* Tag check value */
@@ -623,7 +622,7 @@
elm->type, memb_ptr2, elm->name,
buf_ptr, size);
XER_ADVANCE(tmprval.consumed);
- ASN_DEBUG("XER/CHOICE: itdf: code=%d, xs=%d", tmprval.code, xer_state);
+ ASN_DEBUG("XER/CHOICE: itdf: code=%d", tmprval.code);
if(tmprval.code != RC_OK)
RETURN(tmprval.code);
assert(_fetch_present_idx(st,
@@ -631,7 +630,6 @@
/* Record what we've got */
_set_present_idx(st,
specs->pres_offset, specs->pres_size, edx + 1);
- ctx->left = xer_state = 0; /* New, clean state */
ctx->phase = 3;
/* Fall through */
}
@@ -639,12 +637,10 @@
/*
* Get the next part of the XML stream.
*/
- ch_size = xer_next_token(&xer_state, buf_ptr, size, &ch_type);
+ ch_size = xer_next_token(buf_ptr, size, &ch_type);
switch(ch_size) {
case -1: RETURN(RC_FAIL);
- case 0:
- ctx->left = xer_state;
- RETURN(RC_WMORE);
+ case 0: RETURN(RC_WMORE);
default:
switch(ch_type) {
case PXER_COMMENT: /* Got XML comment */
diff --git a/skeletons/constr_SEQUENCE.c b/skeletons/constr_SEQUENCE.c
index 1430946..31f0c42 100644
--- a/skeletons/constr_SEQUENCE.c
+++ b/skeletons/constr_SEQUENCE.c
@@ -621,7 +621,6 @@
asn_dec_rval_t rval; /* Return value from a decoder */
ssize_t consumed_myself = 0; /* Consumed bytes from ptr */
- int xer_state; /* XER low level parsing context */
int edx; /* Element index */
int edx_end;
@@ -644,8 +643,10 @@
* Phase 0: Check that the opening tag matches our expectations.
* Phase 1: Processing body and reacting on closing tag.
* Phase 2: Processing inner type.
+ * Phase 3: Skipping unknown extensions.
+ * Phase 4: PHASED OUT
*/
- for(xer_state = ctx->left, edx = ctx->step; ctx->phase <= 2;) {
+ for(edx = ctx->step; ctx->phase <= 3;) {
pxer_chunk_type_e ch_type; /* XER chunk type */
ssize_t ch_size; /* Chunk size */
xer_check_tag_e tcv; /* Tag check value */
@@ -679,7 +680,6 @@
if(tmprval.code != RC_OK)
RETURN(tmprval.code);
ctx->phase = 1; /* Back to body processing */
- ctx->left = xer_state = 0; /* New, clean state */
ctx->step = ++edx;
ASN_DEBUG("XER/SEQUENCE phase => %d, step => %d",
ctx->phase, ctx->step);
@@ -689,12 +689,10 @@
/*
* Get the next part of the XML stream.
*/
- ch_size = xer_next_token(&xer_state, buf_ptr, size, &ch_type);
+ ch_size = xer_next_token(buf_ptr, size, &ch_type);
switch(ch_size) {
case -1: RETURN(RC_FAIL);
- case 0:
- ctx->left = xer_state;
- RETURN(RC_WMORE);
+ case 0: RETURN(RC_WMORE);
default:
switch(ch_type) {
case PXER_COMMENT: /* Got XML comment */
@@ -708,6 +706,26 @@
tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
ASN_DEBUG("XER/SEQUENCE: tcv = %d, ph=%d", tcv, ctx->phase);
+
+ /* Skip the extensions section */
+ if(ctx->phase == 3) {
+ switch(xer_skip_unknown(tcv, &ctx->left)) {
+ case -1:
+ ctx->phase = 4;
+ RETURN(RC_FAIL);
+ case 0:
+ XER_ADVANCE(ch_size);
+ continue;
+ case 1:
+ XER_ADVANCE(ch_size);
+ ctx->phase = 1;
+ continue;
+ case 2:
+ ctx->phase = 1;
+ break;
+ }
+ }
+
switch(tcv) {
case XCT_CLOSING:
if(ctx->phase == 0) break;
@@ -727,7 +745,7 @@
> td->elements_count)
) {
XER_ADVANCE(ch_size);
- ctx->phase = 3; /* Phase out */
+ ctx->phase = 4; /* Phase out */
RETURN(RC_OK);
} else {
ASN_DEBUG("Premature end of XER SEQUENCE");
@@ -784,11 +802,20 @@
/* It is expected extension */
if(IN_EXTENSION_GROUP(specs,
edx + elements[edx].optional)) {
- ASN_DEBUG("Got anticipated extension at %d, "
- "but NOT IMPLEMENTED YET", edx);
+ ASN_DEBUG("Got anticipated extension at %d", edx);
/*
- * TODO: implement skipping of extensions
+ * Check for (XCT_BOTH or XCT_UNKNOWN_BO)
+ * By using a mask. Only record a pure
+ * <opening> tags.
*/
+ if(tcv & XCT_CLOSING) {
+ /* Found </extension> without body */
+ } else {
+ ctx->left = 1;
+ ctx->phase = 3; /* Skip ...'s */
+ }
+ XER_ADVANCE(ch_size);
+ continue;
}
/* Fall through */
@@ -800,7 +827,7 @@
break;
}
- ctx->phase = 3; /* "Phase out" on hard failure */
+ ctx->phase = 4; /* "Phase out" on hard failure */
RETURN(RC_FAIL);
}
diff --git a/skeletons/constr_SET.c b/skeletons/constr_SET.c
index 120acb2..c5bb201 100644
--- a/skeletons/constr_SET.c
+++ b/skeletons/constr_SET.c
@@ -600,7 +600,6 @@
asn_dec_rval_t rval; /* Return value from a decoder */
ssize_t consumed_myself = 0; /* Consumed bytes from ptr */
- int xer_state; /* XER low level parsing context */
int edx; /* Element index */
/*
@@ -621,8 +620,10 @@
* Phase 0: Check that the opening tag matches our expectations.
* Phase 1: Processing body and reacting on closing tag.
* Phase 2: Processing inner type.
+ * Phase 3: Skipping unknown extensions.
+ * Phase 4: PHASED OUT
*/
- for(xer_state = ctx->left, edx = ctx->step; ctx->phase <= 2;) {
+ for(edx = ctx->step; ctx->phase <= 3;) {
pxer_chunk_type_e ch_type; /* XER chunk type */
ssize_t ch_size; /* Chunk size */
xer_check_tag_e tcv; /* Tag check value */
@@ -662,7 +663,6 @@
if(tmprval.code != RC_OK)
RETURN(tmprval.code);
ctx->phase = 1; /* Back to body processing */
- ctx->left = xer_state = 0; /* New, clean state */
ASN_SET_MKPRESENT((char *)st + specs->pres_offset, edx);
ASN_DEBUG("XER/SET phase => %d", ctx->phase);
/* Fall through */
@@ -671,12 +671,10 @@
/*
* Get the next part of the XML stream.
*/
- ch_size = xer_next_token(&xer_state, buf_ptr, size, &ch_type);
+ ch_size = xer_next_token(buf_ptr, size, &ch_type);
switch(ch_size) {
case -1: RETURN(RC_FAIL);
- case 0:
- ctx->left = xer_state;
- RETURN(RC_WMORE);
+ case 0: RETURN(RC_WMORE);
default:
switch(ch_type) {
case PXER_COMMENT: /* Got XML comment */
@@ -690,6 +688,26 @@
tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
ASN_DEBUG("XER/SET: tcv = %d, ph=%d", tcv, ctx->phase);
+
+ /* Skip the extensions section */
+ if(ctx->phase == 3) {
+ switch(xer_skip_unknown(tcv, &ctx->left)) {
+ case -1:
+ ctx->phase = 4;
+ RETURN(RC_FAIL);
+ case 0:
+ XER_ADVANCE(ch_size);
+ continue;
+ case 1:
+ XER_ADVANCE(ch_size);
+ ctx->phase = 1;
+ continue;
+ case 2:
+ ctx->phase = 1;
+ break;
+ }
+ }
+
switch(tcv) {
case XCT_CLOSING:
if(ctx->phase == 0) break;
@@ -699,7 +717,7 @@
if(ctx->phase == 0) {
if(_SET_is_populated(td, st)) {
XER_ADVANCE(ch_size);
- ctx->phase = 3; /* Phase out */
+ ctx->phase = 4; /* Phase out */
RETURN(RC_OK);
} else {
ASN_DEBUG("Premature end of XER SET");
@@ -725,9 +743,8 @@
* Search which member corresponds to this tag.
*/
for(edx = 0; edx < td->elements_count; edx++) {
- elm = &elements[edx];
- tcv = xer_check_tag(buf_ptr,ch_size,elm->name);
- switch(tcv) {
+ switch(xer_check_tag(buf_ptr, ch_size,
+ elements[edx].name)) {
case XCT_BOTH:
case XCT_OPENING:
/*
@@ -750,11 +767,20 @@
/* It is expected extension */
if(specs->extensible) {
- ASN_DEBUG("Got anticipated extension, "
- "but NOT IMPLEMENTED YET");
+ ASN_DEBUG("Got anticipated extension");
/*
- * TODO: implement skipping of extensions
+ * Check for (XCT_BOTH or XCT_UNKNOWN_BO)
+ * By using a mask. Only record a pure
+ * <opening> tags.
*/
+ if(tcv & XCT_CLOSING) {
+ /* Found </extension> without body */
+ } else {
+ ctx->left = 1;
+ ctx->phase = 3; /* Skip ...'s */
+ }
+ XER_ADVANCE(ch_size);
+ continue;
}
/* Fall through */
@@ -766,7 +792,7 @@
break;
}
- ctx->phase = 3; /* "Phase out" on hard failure */
+ ctx->phase = 4; /* "Phase out" on hard failure */
RETURN(RC_FAIL);
}
diff --git a/skeletons/constr_SET_OF.c b/skeletons/constr_SET_OF.c
index eed604e..7df1e5c 100644
--- a/skeletons/constr_SET_OF.c
+++ b/skeletons/constr_SET_OF.c
@@ -482,7 +482,6 @@
asn_dec_rval_t rval; /* Return value from a decoder */
ssize_t consumed_myself = 0; /* Consumed bytes from ptr */
- int xer_state; /* XER low level parsing context */
/*
* Create the target structure if it is not present already.
@@ -503,7 +502,7 @@
* Phase 1: Processing body and reacting on closing tag.
* Phase 2: Processing inner type.
*/
- for(xer_state = ctx->left; ctx->phase <= 2;) {
+ for(; ctx->phase <= 2;) {
pxer_chunk_type_e ch_type; /* XER chunk type */
ssize_t ch_size; /* Chunk size */
xer_check_tag_e tcv; /* Tag check value */
@@ -530,7 +529,6 @@
RETURN(tmprval.code);
}
ctx->phase = 1; /* Back to body processing */
- ctx->left = xer_state = 0; /* New, clean state */
ASN_DEBUG("XER/SET OF phase => %d", ctx->phase);
/* Fall through */
}
@@ -538,12 +536,10 @@
/*
* Get the next part of the XML stream.
*/
- ch_size = xer_next_token(&xer_state, buf_ptr, size, &ch_type);
+ ch_size = xer_next_token(buf_ptr, size, &ch_type);
switch(ch_size) {
case -1: RETURN(RC_FAIL);
- case 0:
- ctx->left = xer_state;
- RETURN(RC_WMORE);
+ case 0: RETURN(RC_WMORE);
default:
switch(ch_type) {
case PXER_COMMENT: /* Got XML comment */
diff --git a/skeletons/xer_decoder.c b/skeletons/xer_decoder.c
index e81d7de..ed1fff4 100644
--- a/skeletons/xer_decoder.c
+++ b/skeletons/xer_decoder.c
@@ -51,14 +51,13 @@
* Fetch the next token from the XER/XML stream.
*/
ssize_t
-xer_next_token(int *stateContext, void *buffer, size_t size,
- pxer_chunk_type_e *ch_type) {
+xer_next_token(void *buffer, size_t size, pxer_chunk_type_e *ch_type) {
struct xer__cb_arg arg;
+ int stateContext = 0;
ssize_t ret;
- int new_stateContext = *stateContext;
arg.callback_not_invoked = 1;
- ret = pxml_parse(&new_stateContext, buffer, size, xer__token_cb, &arg);
+ ret = pxml_parse(&stateContext, buffer, size, xer__token_cb, &arg);
if(ret < 0) return -1;
if(arg.callback_not_invoked) {
assert(ret == 0); /* No data was consumed */
@@ -66,6 +65,7 @@
} else {
assert(arg.chunk_size);
assert(arg.chunk_buf == buffer);
+ assert(stateContext == 0);
}
/*
@@ -85,7 +85,6 @@
break;
}
- *stateContext = new_stateContext; /* Update the context */
return arg.chunk_size;
}
@@ -169,10 +168,8 @@
(struct_key, chunk_buf, chunk_size, \
(size_t)chunk_size < size); \
if(converted_size == -1) RETURN(RC_FAIL); \
- if(converted_size == 0 && size == chunk_size) { \
- ctx->step = xer_state; \
+ if(converted_size == 0 && size == chunk_size) \
RETURN(RC_WMORE); \
- } \
chunk_size = converted_size; \
} while(0)
#define XER_GOT_EMPTY() do { \
@@ -198,7 +195,6 @@
asn_dec_rval_t rval;
ssize_t consumed_myself = 0;
- int xer_state; /* XER low level parsing context */
(void)opt_codec_ctx;
@@ -208,7 +204,7 @@
* Phase 1: Processing body and reacting on closing tag.
*/
if(ctx->phase > 1) RETURN(RC_FAIL);
- for(xer_state = ctx->step;;) {
+ for(;;) {
pxer_chunk_type_e ch_type; /* XER chunk type */
ssize_t ch_size; /* Chunk size */
xer_check_tag_e tcv; /* Tag check value */
@@ -216,11 +212,10 @@
/*
* Get the next part of the XML stream.
*/
- ch_size = xer_next_token(&xer_state, buf_ptr, size, &ch_type);
+ ch_size = xer_next_token(buf_ptr, size, &ch_type);
switch(ch_size) {
case -1: RETURN(RC_FAIL);
case 0:
- ctx->step = xer_state;
RETURN(RC_WMORE);
default:
switch(ch_type) {
@@ -320,3 +315,29 @@
return 1; /* All whitespace */
}
+/*
+ * This is a vastly simplified, non-validating XML tree skipper.
+ */
+int
+xer_skip_unknown(xer_check_tag_e tcv, ber_tlv_len_t *depth) {
+ assert(*depth > 0);
+ switch(tcv) {
+ case XCT_BOTH:
+ case XCT_UNKNOWN_BO:
+ /* These negate each other. */
+ return 0;
+ case XCT_OPENING:
+ case XCT_UNKNOWN_OP:
+ ++(*depth);
+ return 0;
+ case XCT_CLOSING:
+ case XCT_UNKNOWN_CL:
+ if(--(*depth) == 0)
+ return (tcv == XCT_CLOSING) ? 2 : 1;
+ return 0;
+ default:
+ return -1;
+ }
+}
+
+
diff --git a/skeletons/xer_decoder.h b/skeletons/xer_decoder.h
index c3df005..c0e23b9 100644
--- a/skeletons/xer_decoder.h
+++ b/skeletons/xer_decoder.h
@@ -63,8 +63,7 @@
PXER_TEXT, /* Plain text between XER tags */
PXER_COMMENT, /* A comment, may be part of */
} pxer_chunk_type_e;
-ssize_t xer_next_token(int *stateContext, void *buffer, size_t size,
- pxer_chunk_type_e *_ch_type);
+ssize_t xer_next_token(void *buffer, size_t size, pxer_chunk_type_e *_ch_type);
/*
* This function checks the buffer against the tag name is expected to occur.
@@ -90,4 +89,9 @@
*/
int xer_is_whitespace(void *chunk_buf, size_t chunk_size);
+/*
+ * Skip the series of anticipated extensions.
+ */
+int xer_skip_unknown(xer_check_tag_e tcv, ber_tlv_len_t *depth);
+
#endif /* _XER_DECODER_H_ */