asn_encode_to_new_buffer()
diff --git a/skeletons/asn_application.c b/skeletons/asn_application.c
index ee74e32..b8852ea 100644
--- a/skeletons/asn_application.c
+++ b/skeletons/asn_application.c
@@ -42,6 +42,12 @@
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;
@@ -71,6 +77,43 @@
}
/*
+ * 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.
*/
static int
@@ -134,7 +177,8 @@
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 @@
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,
diff --git a/skeletons/asn_application.h b/skeletons/asn_application.h
index a125562..acc91ab 100644
--- a/skeletons/asn_application.h
+++ b/skeletons/asn_application.h
@@ -81,6 +81,28 @@
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