static ssize_t xer_decode__primitive_body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) { struct xdp_arg_s *arg = (struct xdp_arg_s *)key; enum xer_pbd_rval bret; size_t lead_wsp_size; if(arg->decoded_something) { if(xer_whitespace_span(chunk_buf, chunk_size) == chunk_size) { /* * Example: * "<INTEGER>123<!--/--> </INTEGER>" * ^- chunk_buf position. */ return chunk_size; } /* * Decoding was done once already. Prohibit doing it again. */ return -1; } if(!have_more) { /* * If we've received something like "1", we can't really * tell whether it is really `1` or `123`, until we know * that there is no more data coming. * The have_more argument will be set to 1 once something * like this is available to the caller of this callback: * "1<tag_start..." */ arg->want_more = 1; return -1; } lead_wsp_size = xer_whitespace_span(chunk_buf, chunk_size); chunk_buf = (const char *)chunk_buf + lead_wsp_size; chunk_size -= lead_wsp_size; bret = arg->prim_body_decoder(arg->type_descriptor, arg->struct_key, chunk_buf, chunk_size); switch(bret) { case XPBD_SYSTEM_FAILURE: case XPBD_DECODER_LIMIT: case XPBD_BROKEN_ENCODING: break; case XPBD_BODY_CONSUMED: /* Tag decoded successfully */ arg->decoded_something = 1; /* Fall through */ case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */ return lead_wsp_size + chunk_size; } return -1; }
enum xer_equivalence_e xer_equivalent(const struct asn_TYPE_descriptor_s *td, const void *struct1, const void *struct2, FILE *opt_debug_stream) { struct xer_buffer xb1 = {0, 0, 0}; struct xer_buffer xb2 = {0, 0, 0}; asn_enc_rval_t e1, e2; asn_dec_rval_t rval; void *sptr = NULL; if(!td || !struct1 || !struct2) { if(opt_debug_stream) { if(!td) fprintf(opt_debug_stream, "Type descriptor missing\n"); if(!struct1) fprintf(opt_debug_stream, "Structure 1 missing\n"); if(!struct2) fprintf(opt_debug_stream, "Structure 2 missing\n"); } return XEQ_FAILURE; } e1 = xer_encode(td, struct1, XER_F_BASIC, xer__buffer_append, &xb1); if(e1.encoded == -1) { if(opt_debug_stream) { fprintf(stderr, "XER Encoding of %s failed\n", td->name); } FREEMEM(xb1.buffer); return XEQ_ENCODE1_FAILED; } e2 = xer_encode(td, struct2, XER_F_BASIC, xer__buffer_append, &xb2); if(e2.encoded == -1) { if(opt_debug_stream) { fprintf(stderr, "XER Encoding of %s failed\n", td->name); } FREEMEM(xb1.buffer); FREEMEM(xb2.buffer); return XEQ_ENCODE1_FAILED; } if(xb1.buffer_size != xb2.buffer_size || memcmp(xb1.buffer, xb2.buffer, xb1.buffer_size) != 0) { if(opt_debug_stream) { fprintf(opt_debug_stream, "Structures XER-encoded into different byte streams:\n=== " "Structure 1 ===\n%s\n=== Structure 2 ===\n%s\n", xb1.buffer, xb2.buffer); } FREEMEM(xb1.buffer); FREEMEM(xb2.buffer); return XEQ_DIFFERENT; } else { if(opt_debug_stream) { fprintf(opt_debug_stream, "Both structures encoded into the same XER byte stream " "of size %" ASN_PRI_SIZE ":\n%s", xb1.buffer_size, xb1.buffer); } } rval = xer_decode(NULL, td, (void **)&sptr, xb1.buffer, xb1.buffer_size); switch(rval.code) { case RC_OK: break; case RC_WMORE: if(opt_debug_stream) { fprintf(opt_debug_stream, "Structure %s XER decode unexpectedly requires " "more data:\n%s\n", td->name, xb1.buffer); } /* Fall through */ case RC_FAIL: default: if(opt_debug_stream) { fprintf(opt_debug_stream, "Structure %s XER decoding resulted in failure.\n", td->name); } ASN_STRUCT_FREE(*td, sptr); FREEMEM(xb1.buffer); FREEMEM(xb2.buffer); return XEQ_DECODE_FAILED; } if(rval.consumed != xb1.buffer_size && ((rval.consumed > xb1.buffer_size) || xer_whitespace_span(xb1.buffer + rval.consumed, xb1.buffer_size - rval.consumed) != (xb1.buffer_size - rval.consumed))) { if(opt_debug_stream) { fprintf(opt_debug_stream, "Round-trip decode of %s required less bytes (%" ASN_PRI_SIZE ") than " "encoded (%" ASN_PRI_SIZE ")\n", td->name, rval.consumed, xb1.buffer_size); } ASN_STRUCT_FREE(*td, sptr); FREEMEM(xb1.buffer); FREEMEM(xb2.buffer); return XEQ_ROUND_TRIP_FAILED; } /* * Reuse xb2 to encode newly decoded structure. */ FREEMEM(xb2.buffer); memset(&xb2, 0, sizeof(xb2)); e2 = xer_encode(td, sptr, XER_F_BASIC, xer__buffer_append, &xb2); if(e2.encoded == -1) { if(opt_debug_stream) { fprintf(stderr, "XER Encoding of round-trip decode of %s failed\n", td->name); } ASN_STRUCT_FREE(*td, sptr); FREEMEM(xb1.buffer); FREEMEM(xb2.buffer); return XEQ_ROUND_TRIP_FAILED; } ASN_STRUCT_FREE(*td, sptr); sptr = 0; if(xb1.buffer_size != xb2.buffer_size || memcmp(xb1.buffer, xb2.buffer, xb1.buffer_size) != 0) { if(opt_debug_stream) { fprintf(opt_debug_stream, "XER Encoding of round-trip decode of %s resulted in " "different byte stream:\n" "=== Original ===\n%s\n" "=== Round-tripped ===\n%s\n", xb1.buffer, xb2.buffer, td->name); } FREEMEM(xb1.buffer); FREEMEM(xb2.buffer); return XEQ_ROUND_TRIP_FAILED; } FREEMEM(xb1.buffer); FREEMEM(xb2.buffer); return XEQ_SUCCESS; }