asn_encode_to_new_buffer()

This commit is contained in:
Lev Walkin 2017-11-06 01:58:49 -08:00
parent cd8f1e0377
commit 1fc5edb22d
2 changed files with 101 additions and 1 deletions

View File

@ -42,6 +42,12 @@ struct overrun_encoder_key {
size_t computed_size;
};
struct dynamic_encoder_key {
void *buffer;
size_t buffer_size;
size_t computed_size;
};
struct callback_failure_catch_key {
asn_app_consume_bytes_f *callback;
void *callback_key;
@ -70,6 +76,43 @@ overrun_encoder_cb(const void *data, size_t size, void *keyp) {
return 0;
}
/*
* Encoder which dynamically allocates output, and continues
* to count even if allocation failed.
*/
static int
dynamic_encoder_cb(const void *data, size_t size, void *keyp) {
struct dynamic_encoder_key *key = keyp;
if(key->buffer) {
if(key->computed_size + size >= key->buffer_size) {
void *p;
size_t new_size = key->buffer_size;
do {
new_size *= 2;
} while(new_size <= key->computed_size + size);
p = REALLOC(key->buffer, new_size);
if(p) {
key->buffer = p;
key->buffer_size = new_size;
} else {
FREEMEM(key->buffer);
key->buffer = 0;
key->buffer_size = 0;
key->computed_size += size;
return 0;
}
}
memcpy((char *)key->buffer + key->computed_size, data, size);
}
key->computed_size += size;
return 0;
}
/*
* Encoder which help convert the application level encoder failure into EIO.
*/
@ -134,7 +177,8 @@ asn_encode_to_buffer(const asn_codec_ctx_t *opt_codec_ctx,
overrun_encoder_cb, &buf_key);
if(er.encoded >= 0 && (size_t)er.encoded != buf_key.computed_size) {
ASN_DEBUG("asn_encode() returned %" ASN_PRI_SSIZE " yet produced %" ASN_PRI_SIZE " bytes",
ASN_DEBUG("asn_encode() returned %" ASN_PRI_SSIZE
" yet produced %" ASN_PRI_SIZE " bytes",
er.encoded, buf_key.computed_size);
assert(er.encoded < 0 || (size_t)er.encoded == buf_key.computed_size);
}
@ -142,6 +186,40 @@ asn_encode_to_buffer(const asn_codec_ctx_t *opt_codec_ctx,
return er;
}
asn_encode_to_new_buffer_result_t
asn_encode_to_new_buffer(const asn_codec_ctx_t *opt_codec_ctx,
enum asn_transfer_syntax syntax,
const asn_TYPE_descriptor_t *td, const void *sptr) {
struct dynamic_encoder_key buf_key;
asn_encode_to_new_buffer_result_t res;
buf_key.buffer_size = 16;
buf_key.buffer = MALLOC(buf_key.buffer_size);
buf_key.computed_size = 0;
res.result = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,
dynamic_encoder_cb, &buf_key);
if(res.result.encoded >= 0
&& (size_t)res.result.encoded != buf_key.computed_size) {
ASN_DEBUG("asn_encode() returned %" ASN_PRI_SSIZE
" yet produced %" ASN_PRI_SIZE " bytes",
er.encoded, buf_key.computed_size);
assert(res.result.encoded < 0
|| (size_t)res.result.encoded == buf_key.computed_size);
}
res.buffer = buf_key.buffer;
/* 0-terminate just in case. */
if(res.buffer) {
assert(buf_key.computed_size < buf_key.buffer_size);
((char *)res.buffer)[buf_key.computed_size] = '\0';
}
return res;
}
static asn_enc_rval_t
asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
enum asn_transfer_syntax syntax,

View File

@ -81,6 +81,28 @@ asn_enc_rval_t asn_encode_to_buffer(
const struct asn_TYPE_descriptor_s *type_to_encode,
const void *structure_to_encode, void *buffer, size_t buffer_size);
/*
* A variant of asn_encode_to_buffer() with automatically allocated buffer.
* RETURN VALUES:
* On success, returns a newly allocated (.buffer) containing the whole message.
* The message size is returned in (.result.encoded).
* On failure:
* (.buffer) is NULL,
* (.result.encoded) as in asn_encode_to_buffer(),
* The errno codes as in asn_encode_to_buffer(), plus the following:
* ENOMEM: Memory allocation failed due to system or internal limits.
* The user is responsible for freeing the (.buffer).
*/
typedef struct asn_encode_to_new_buffer_result_s {
void *buffer; /* NULL if failed to encode. */
asn_enc_rval_t result;
} asn_encode_to_new_buffer_result_t;
asn_encode_to_new_buffer_result_t asn_encode_to_new_buffer(
const asn_codec_ctx_t *opt_codec_parameters, /* See asn_codecs.h */
enum asn_transfer_syntax,
const struct asn_TYPE_descriptor_s *type_to_encode,
const void *structure_to_encode);
/*
* Generic type of an application-defined callback to return various