diff --git a/skeletons/constr_CHOICE.c b/skeletons/constr_CHOICE.c index b1360653..175ef246 100644 --- a/skeletons/constr_CHOICE.c +++ b/skeletons/constr_CHOICE.c @@ -569,7 +569,6 @@ CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, 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 @@ CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, * 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 @@ CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, 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 @@ CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* 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 @@ CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* * 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 14309462..31f0c422 100644 --- a/skeletons/constr_SEQUENCE.c +++ b/skeletons/constr_SEQUENCE.c @@ -621,7 +621,6 @@ SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, 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 @@ SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, * 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 @@ SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, 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 @@ SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* * 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 @@ SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, 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 @@ SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, > 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 @@ SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* 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 + * tags. */ + if(tcv & XCT_CLOSING) { + /* Found without body */ + } else { + ctx->left = 1; + ctx->phase = 3; /* Skip ...'s */ + } + XER_ADVANCE(ch_size); + continue; } /* Fall through */ @@ -800,7 +827,7 @@ SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, 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 120acb21..c5bb201d 100644 --- a/skeletons/constr_SET.c +++ b/skeletons/constr_SET.c @@ -600,7 +600,6 @@ SET_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, 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 @@ SET_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, * 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 @@ SET_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, 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 @@ SET_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* * 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 @@ SET_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, 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 @@ SET_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, 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 @@ SET_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, * 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 @@ SET_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* 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 + * tags. */ + if(tcv & XCT_CLOSING) { + /* Found without body */ + } else { + ctx->left = 1; + ctx->phase = 3; /* Skip ...'s */ + } + XER_ADVANCE(ch_size); + continue; } /* Fall through */ @@ -766,7 +792,7 @@ SET_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, 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 eed604ed..7df1e5cf 100644 --- a/skeletons/constr_SET_OF.c +++ b/skeletons/constr_SET_OF.c @@ -482,7 +482,6 @@ SET_OF_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, 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 @@ SET_OF_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, * 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 @@ SET_OF_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, 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 @@ SET_OF_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* * 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 e81d7de2..ed1fff46 100644 --- a/skeletons/xer_decoder.c +++ b/skeletons/xer_decoder.c @@ -51,14 +51,13 @@ xer__token_cb(pxml_chunk_type_e type, void *_chunk_data, size_t _chunk_size, voi * 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 @@ xer_next_token(int *stateContext, void *buffer, size_t size, } else { assert(arg.chunk_size); assert(arg.chunk_buf == buffer); + assert(stateContext == 0); } /* @@ -85,7 +85,6 @@ xer_next_token(int *stateContext, void *buffer, size_t size, break; } - *stateContext = new_stateContext; /* Update the context */ return arg.chunk_size; } @@ -169,10 +168,8 @@ xer_check_tag(const void *buf_ptr, int size, const char *need_tag) { (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 @@ xer_decode_general(asn_codec_ctx_t *opt_codec_ctx, 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 @@ xer_decode_general(asn_codec_ctx_t *opt_codec_ctx, * 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 @@ xer_decode_general(asn_codec_ctx_t *opt_codec_ctx, /* * 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 @@ xer_is_whitespace(void *chunk_buf, size_t chunk_size) { 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 c3df005d..c0e23b9e 100644 --- a/skeletons/xer_decoder.h +++ b/skeletons/xer_decoder.h @@ -63,8 +63,7 @@ asn_dec_rval_t xer_decode_general(asn_codec_ctx_t *opt_codec_ctx, 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 @@ xer_check_tag_e xer_check_tag(const void *buf_ptr, int size, */ 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_ */