/* * Copyright (c) 2017 Lev Walkin . All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ #include #include /* * The OER encoder of any type. */ asn_enc_rval_t oer_encode(const asn_TYPE_descriptor_t *type_descriptor, const void *struct_ptr, asn_app_consume_bytes_f *consume_bytes, void *app_key) { ASN_DEBUG("OER encoder invoked for %s", type_descriptor->name); /* * Invoke type-specific encoder. */ return type_descriptor->op->oer_encoder( type_descriptor, 0, struct_ptr, /* Pointer to the destination structure */ consume_bytes, app_key); } /* * Argument type and callback necessary for oer_encode_to_buffer(). */ typedef struct enc_to_buf_arg { void *buffer; size_t left; } enc_to_buf_arg; static int encode_to_buffer_cb(const void *buffer, size_t size, void *key) { enc_to_buf_arg *arg = (enc_to_buf_arg *)key; if(arg->left < size) return -1; /* Data exceeds the available buffer size */ memcpy(arg->buffer, buffer, size); arg->buffer = ((char *)arg->buffer) + size; arg->left -= size; return 0; } /* * A variant of the oer_encode() which encodes the data into the provided buffer */ asn_enc_rval_t oer_encode_to_buffer(const asn_TYPE_descriptor_t *type_descriptor, const asn_oer_constraints_t *constraints, const void *struct_ptr, /* Structure to be encoded */ void *buffer, /* Pre-allocated buffer */ size_t buffer_size /* Initial buffer size (maximum) */ ) { enc_to_buf_arg arg; asn_enc_rval_t ec; arg.buffer = buffer; arg.left = buffer_size; if(type_descriptor->op->oer_encoder == NULL) { ec.encoded = -1; ec.failed_type = type_descriptor; ec.structure_ptr = struct_ptr; ASN_DEBUG("OER encoder is not defined for %s", type_descriptor->name); } else { ec = type_descriptor->op->oer_encoder( type_descriptor, constraints, struct_ptr, /* Pointer to the destination structure */ encode_to_buffer_cb, &arg); if(ec.encoded != -1) { assert(ec.encoded == (ssize_t)(buffer_size - arg.left)); /* Return the encoded contents size */ } } return ec; } asn_enc_rval_t oer_encode_primitive(const asn_TYPE_descriptor_t *td, const asn_oer_constraints_t *constraints, const void *sptr, asn_app_consume_bytes_f *cb, void *app_key) { const ASN__PRIMITIVE_TYPE_t *st = (const ASN__PRIMITIVE_TYPE_t *)sptr; asn_enc_rval_t er = {0, 0, 0}; ssize_t ret; (void)constraints; if(!st) ASN__ENCODE_FAILED; ASN_DEBUG("Encoding %s (%" ASN_PRI_SIZE " bytes)", td ? td->name : "", st->size); /* * X.696 (08/2015) #27.2 */ ret = oer_serialize_length(st->size, cb, app_key); if(ret < 0) { ASN__ENCODE_FAILED; } er.encoded += ret; er.encoded += st->size; if(cb(st->buf, st->size, app_key) < 0) { ASN__ENCODE_FAILED; } else { ASN__ENCODED_OK(er); } } static int oer__count_bytes(const void *buffer, size_t size, void *bytes_ptr) { size_t *bytes = bytes_ptr; (void)buffer; *bytes += size; return 0; } ssize_t oer_open_type_put(const asn_TYPE_descriptor_t *td, const asn_oer_constraints_t *constraints, const void *sptr, asn_app_consume_bytes_f *cb, void *app_key) { size_t serialized_byte_count = 0; asn_enc_rval_t er = {0,0,0}; ssize_t len_len; er = td->op->oer_encoder(td, constraints, sptr, oer__count_bytes, &serialized_byte_count); if(er.encoded < 0) return -1; assert(serialized_byte_count == (size_t)er.encoded); len_len = oer_serialize_length(serialized_byte_count, cb, app_key); if(len_len == -1) return -1; er = td->op->oer_encoder(td, constraints, sptr, cb, app_key); if(er.encoded < 0) return -1; assert(serialized_byte_count == (size_t)er.encoded); return len_len + er.encoded; }