2  * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
 
   3  * Redistribution and modifications are permitted subject to BSD license.
 
   5 #include <asn_internal.h>
 
   6 #include <asn_codecs_prim.h>
 
  10  * Decode an always-primitive type.
 
  13 ber_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
 
  14         asn_TYPE_descriptor_t *td,
 
  15         void **sptr, const void *buf_ptr, size_t size, int tag_mode) {
 
  16         ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr;
 
  21          * If the structure is not there, allocate it.
 
  24                 st = (ASN__PRIMITIVE_TYPE_t *)CALLOC(1, sizeof(*st));
 
  25                 if(st == NULL) _ASN_DECODE_FAILED;
 
  29         ASN_DEBUG("Decoding %s as plain primitive (tm=%d)",
 
  33          * Check tags and extract value length.
 
  35         rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
 
  36                         tag_mode, 0, &length, 0);
 
  37         if(rval.code != RC_OK)
 
  40         ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
 
  43          * Make sure we have this length.
 
  45         buf_ptr = ((const char *)buf_ptr) + rval.consumed;
 
  46         size -= rval.consumed;
 
  47         if(length > (ber_tlv_len_t)size) {
 
  53         st->size = (int)length;
 
  54         /* The following better be optimized away. */
 
  55         if(sizeof(st->size) != sizeof(length)
 
  56                         && (ber_tlv_len_t)st->size != length) {
 
  61         st->buf = (uint8_t *)MALLOC(length + 1);
 
  67         memcpy(st->buf, buf_ptr, length);
 
  68         st->buf[length] = '\0';         /* Just in case */
 
  71         rval.consumed += length;
 
  73         ASN_DEBUG("Took %ld/%ld bytes to encode %s",
 
  75                 (long)length, td->name);
 
  81  * Encode an always-primitive type using DER.
 
  84 der_encode_primitive(asn_TYPE_descriptor_t *td, void *sptr,
 
  85         int tag_mode, ber_tlv_tag_t tag,
 
  86         asn_app_consume_bytes_f *cb, void *app_key) {
 
  88         ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
 
  90         ASN_DEBUG("%s %s as a primitive type (tm=%d)",
 
  91                 cb?"Encoding":"Estimating", td->name, tag_mode);
 
  93         erval.encoded = der_write_tags(td, st->size, tag_mode, 0, tag,
 
  95         ASN_DEBUG("%s wrote tags %d", td->name, (int)erval.encoded);
 
  96         if(erval.encoded == -1) {
 
  97                 erval.failed_type = td;
 
  98                 erval.structure_ptr = sptr;
 
 103                 if(cb(st->buf, st->size, app_key) < 0) {
 
 105                         erval.failed_type = td;
 
 106                         erval.structure_ptr = sptr;
 
 110                 assert(st->buf || st->size == 0);
 
 113         erval.encoded += st->size;
 
 114         _ASN_ENCODED_OK(erval);
 
 118 ASN__PRIMITIVE_TYPE_free(asn_TYPE_descriptor_t *td, void *sptr,
 
 120         ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
 
 125         ASN_DEBUG("Freeing %s as a primitive type", td->name);
 
 136  * Local internal type passed around as an argument.
 
 139         asn_TYPE_descriptor_t *type_descriptor;
 
 141         xer_primitive_body_decoder_f *prim_body_decoder;
 
 142         int decoded_something;
 
 148 xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size) {
 
 149         struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
 
 150         enum xer_pbd_rval bret;
 
 152         if(arg->decoded_something) {
 
 153                 if(xer_is_whitespace(chunk_buf, chunk_size))
 
 154                         return 0;       /* Skip it. */
 
 156                  * Decoding was done once already. Prohibit doing it again.
 
 161         bret = arg->prim_body_decoder(arg->type_descriptor,
 
 162                 arg->struct_key, chunk_buf, chunk_size);
 
 164         case XPBD_SYSTEM_FAILURE:
 
 165         case XPBD_DECODER_LIMIT:
 
 166         case XPBD_BROKEN_ENCODING:
 
 168         case XPBD_BODY_CONSUMED:
 
 169                 /* Tag decoded successfully */
 
 170                 arg->decoded_something = 1;
 
 172         case XPBD_NOT_BODY_IGNORE:      /* Safe to proceed further */
 
 180 xer_decode__body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) {
 
 181         struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
 
 182         enum xer_pbd_rval bret;
 
 184         if(arg->decoded_something) {
 
 185                 if(xer_is_whitespace(chunk_buf, chunk_size))
 
 188                  * Decoding was done once already. Prohibit doing it again.
 
 195                  * If we've received something like "1", we can't really
 
 196                  * tell whether it is really `1` or `123`, until we know
 
 197                  * that there is no more data coming.
 
 198                  * The have_more argument will be set to 1 once something
 
 199                  * like this is available to the caller of this callback:
 
 206         bret = arg->prim_body_decoder(arg->type_descriptor,
 
 207                 arg->struct_key, chunk_buf, chunk_size);
 
 209         case XPBD_SYSTEM_FAILURE:
 
 210         case XPBD_DECODER_LIMIT:
 
 211         case XPBD_BROKEN_ENCODING:
 
 213         case XPBD_BODY_CONSUMED:
 
 214                 /* Tag decoded successfully */
 
 215                 arg->decoded_something = 1;
 
 217         case XPBD_NOT_BODY_IGNORE:      /* Safe to proceed further */
 
 226 xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
 
 227         asn_TYPE_descriptor_t *td,
 
 230         const char *opt_mname,
 
 231         const void *buf_ptr, size_t size,
 
 232         xer_primitive_body_decoder_f *prim_body_decoder
 
 234         const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
 
 235         asn_struct_ctx_t s_ctx;
 
 236         struct xdp_arg_s s_arg;
 
 240          * Create the structure if does not exist.
 
 243                 *sptr = CALLOC(1, struct_size);
 
 244                 if(!*sptr) _ASN_DECODE_FAILED;
 
 247         memset(&s_ctx, 0, sizeof(s_ctx));
 
 248         s_arg.type_descriptor = td;
 
 249         s_arg.struct_key = *sptr;
 
 250         s_arg.prim_body_decoder = prim_body_decoder;
 
 251         s_arg.decoded_something = 0;
 
 254         rc = xer_decode_general(opt_codec_ctx, &s_ctx, &s_arg,
 
 255                 xml_tag, buf_ptr, size,
 
 256                 xer_decode__unexpected_tag, xer_decode__body);
 
 259                 if(!s_arg.decoded_something) {
 
 261                         ASN_DEBUG("Primitive body is not recognized, "
 
 262                                 "supplying empty one");
 
 264                          * Decoding opportunity has come and gone.
 
 265                          * Where's the result?
 
 266                          * Try to feed with empty body, see if it eats it.
 
 268                         if(prim_body_decoder(s_arg.type_descriptor,
 
 269                                 s_arg.struct_key, &ch, 0)
 
 270                                         != XPBD_BODY_CONSUMED) {
 
 272                                  * This decoder does not like empty stuff.
 
 280                  * Redo the whole thing later.
 
 281                  * We don't have a context to save intermediate parsing state.