+++ /dev/null
-/*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
- * Redistribution and modifications are permitted subject to BSD license.
- */
-#include <asn_internal.h>
-#include <asn_codecs_prim.h>
-#include <errno.h>
-
-/*
- * Decode an always-primitive type.
- */
-asn_dec_rval_t
-ber_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
- asn_TYPE_descriptor_t *td,
- void **sptr, const void *buf_ptr, size_t size, int tag_mode) {
- ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr;
- asn_dec_rval_t rval;
- ber_tlv_len_t length;
-
- /*
- * If the structure is not there, allocate it.
- */
- if(st == NULL) {
- st = (ASN__PRIMITIVE_TYPE_t *)CALLOC(1, sizeof(*st));
- if(st == NULL) _ASN_DECODE_FAILED;
- *sptr = (void *)st;
- }
-
- ASN_DEBUG("Decoding %s as plain primitive (tm=%d)",
- td->name, tag_mode);
-
- /*
- * Check tags and extract value length.
- */
- rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
- tag_mode, 0, &length, 0);
- if(rval.code != RC_OK)
- return rval;
-
- ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
-
- /*
- * Make sure we have this length.
- */
- buf_ptr = ((const char *)buf_ptr) + rval.consumed;
- size -= rval.consumed;
- if(length > (ber_tlv_len_t)size) {
- rval.code = RC_WMORE;
- rval.consumed = 0;
- return rval;
- }
-
- st->size = (int)length;
- /* The following better be optimized away. */
- if(sizeof(st->size) != sizeof(length)
- && (ber_tlv_len_t)st->size != length) {
- st->size = 0;
- _ASN_DECODE_FAILED;
- }
-
- st->buf = (uint8_t *)MALLOC(length + 1);
- if(!st->buf) {
- st->size = 0;
- _ASN_DECODE_FAILED;
- }
-
- memcpy(st->buf, buf_ptr, length);
- st->buf[length] = '\0'; /* Just in case */
-
- rval.code = RC_OK;
- rval.consumed += length;
-
- ASN_DEBUG("Took %ld/%ld bytes to encode %s",
- (long)rval.consumed,
- (long)length, td->name);
-
- return rval;
-}
-
-/*
- * Encode an always-primitive type using DER.
- */
-asn_enc_rval_t
-der_encode_primitive(asn_TYPE_descriptor_t *td, void *sptr,
- int tag_mode, ber_tlv_tag_t tag,
- asn_app_consume_bytes_f *cb, void *app_key) {
- asn_enc_rval_t erval;
- ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
-
- ASN_DEBUG("%s %s as a primitive type (tm=%d)",
- cb?"Encoding":"Estimating", td->name, tag_mode);
-
- erval.encoded = der_write_tags(td, st->size, tag_mode, 0, tag,
- cb, app_key);
- ASN_DEBUG("%s wrote tags %d", td->name, (int)erval.encoded);
- if(erval.encoded == -1) {
- erval.failed_type = td;
- erval.structure_ptr = sptr;
- return erval;
- }
-
- if(cb && st->buf) {
- if(cb(st->buf, st->size, app_key) < 0) {
- erval.encoded = -1;
- erval.failed_type = td;
- erval.structure_ptr = sptr;
- return erval;
- }
- } else {
- assert(st->buf || st->size == 0);
- }
-
- erval.encoded += st->size;
- _ASN_ENCODED_OK(erval);
-}
-
-void
-ASN__PRIMITIVE_TYPE_free(asn_TYPE_descriptor_t *td, void *sptr,
- int contents_only) {
- ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
-
- if(!td || !sptr)
- return;
-
- ASN_DEBUG("Freeing %s as a primitive type", td->name);
-
- if(st->buf)
- FREEMEM(st->buf);
-
- if(!contents_only)
- FREEMEM(st);
-}
-
-
-/*
- * Local internal type passed around as an argument.
- */
-struct xdp_arg_s {
- asn_TYPE_descriptor_t *type_descriptor;
- void *struct_key;
- xer_primitive_body_decoder_f *prim_body_decoder;
- int decoded_something;
- int want_more;
-};
-
-
-static int
-xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size) {
- struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
- enum xer_pbd_rval bret;
-
- if(arg->decoded_something) {
- if(xer_is_whitespace(chunk_buf, chunk_size))
- return 0; /* Skip it. */
- /*
- * Decoding was done once already. Prohibit doing it again.
- */
- return -1;
- }
-
- 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 0;
- }
-
- return -1;
-}
-
-static ssize_t
-xer_decode__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;
-
- if(arg->decoded_something) {
- if(xer_is_whitespace(chunk_buf, chunk_size))
- 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;
- }
-
- 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 chunk_size;
- }
-
- return -1;
-}
-
-
-asn_dec_rval_t
-xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
- asn_TYPE_descriptor_t *td,
- void **sptr,
- size_t struct_size,
- const char *opt_mname,
- const void *buf_ptr, size_t size,
- xer_primitive_body_decoder_f *prim_body_decoder
-) {
- const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
- asn_struct_ctx_t s_ctx;
- struct xdp_arg_s s_arg;
- asn_dec_rval_t rc;
-
- /*
- * Create the structure if does not exist.
- */
- if(!*sptr) {
- *sptr = CALLOC(1, struct_size);
- if(!*sptr) _ASN_DECODE_FAILED;
- }
-
- memset(&s_ctx, 0, sizeof(s_ctx));
- s_arg.type_descriptor = td;
- s_arg.struct_key = *sptr;
- s_arg.prim_body_decoder = prim_body_decoder;
- s_arg.decoded_something = 0;
- s_arg.want_more = 0;
-
- rc = xer_decode_general(opt_codec_ctx, &s_ctx, &s_arg,
- xml_tag, buf_ptr, size,
- xer_decode__unexpected_tag, xer_decode__body);
- switch(rc.code) {
- case RC_OK:
- if(!s_arg.decoded_something) {
- char ch;
- ASN_DEBUG("Primitive body is not recognized, "
- "supplying empty one");
- /*
- * Decoding opportunity has come and gone.
- * Where's the result?
- * Try to feed with empty body, see if it eats it.
- */
- if(prim_body_decoder(s_arg.type_descriptor,
- s_arg.struct_key, &ch, 0)
- != XPBD_BODY_CONSUMED) {
- /*
- * This decoder does not like empty stuff.
- */
- _ASN_DECODE_FAILED;
- }
- }
- break;
- case RC_WMORE:
- /*
- * Redo the whole thing later.
- * We don't have a context to save intermediate parsing state.
- */
- rc.consumed = 0;
- break;
- case RC_FAIL:
- rc.consumed = 0;
- if(s_arg.want_more)
- rc.code = RC_WMORE;
- else
- _ASN_DECODE_FAILED;
- break;
- }
- return rc;
-}
-