From 324daf82504ef6a409a1d955a804a5f05d572aa4 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Fri, 4 Sep 2015 15:34:10 +0200 Subject: add libmds_message_duplicate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- src/libmdsclient/inbound.c | 42 ++++++++++++++++++++++++++++++++++++++++-- src/libmdsclient/inbound.h | 22 ++++++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/libmdsclient/inbound.c b/src/libmdsclient/inbound.c index 739cbcb..7b8a0fc 100644 --- a/src/libmdsclient/inbound.c +++ b/src/libmdsclient/inbound.c @@ -52,6 +52,7 @@ int libmds_message_initialise(libmds_message_t* restrict this) this->buffer_ptr = 0; this->stage = 0; this->buffer = malloc(this->buffer_size * sizeof(char)); + this->flattened = 0; return this->buffer == NULL ? -1 : 0; } @@ -64,8 +65,45 @@ int libmds_message_initialise(libmds_message_t* restrict this) */ void libmds_message_destroy(libmds_message_t* restrict this) { - free(this->headers), this->headers = NULL; - free(this->buffer), this->buffer = NULL; + if (this->flattened == 0) + { + free(this->headers), this->headers = NULL; + free(this->buffer), this->buffer = NULL; + } +} + + +/** + * Release all resources in a message, should + * be done even if initialisation fails + * + * @param this The message + * @return The duplicate, you do not need to call `libmds_message_destroy` + * on it before you call `free` on it. However, you cannot use + * this is an `libmds_message_t` array (libmds_message_t*), only + * in an `libmds_message_t*` array (libmds_message_t**). + */ +libmds_message_t* libmds_message_duplicate(libmds_message_t* restrict this) +{ + size_t flattened_size, i, n = this->header_count; + libmds_message_t* rc; + + flattened_size = sizeof(libmds_message_t) + this->buffer_off * sizeof(char) + n * sizeof(void*); + if (rc = malloc(flattened_size), rc == NULL) + return NULL; + + *rc = *this; + rc->flattened = flattened_size; + rc->buffer_size = this->buffer_off; + + rc->buffer = ((char*)rc) + sizeof(libmds_message_t) / sizeof(char); + rc->headers = (char**)(void*)(rc->buffer + this->buffer_off); + rc->payload = rc->buffer + (size_t)(this->payload - this->buffer); + for (i = 0; i < n; i++) + rc->headers[i] = rc->buffer + (size_t)(this->headers[i] - this->buffer); + + memcpy(rc->buffer, this->buffer, this->buffer_off * sizeof(char)); + return rc; } diff --git a/src/libmdsclient/inbound.h b/src/libmdsclient/inbound.h index f0e3d20..87b96f4 100644 --- a/src/libmdsclient/inbound.h +++ b/src/libmdsclient/inbound.h @@ -75,6 +75,15 @@ typedef struct libmds_message */ size_t buffer_off; + /** + * Zero unless the structure is flattend, otherwise + * the size of the object (semiinternal data) + * + * Flattened means that all pointers are subpointers + * of the object itself + */ + size_t flattened; + /** * 0 while reading headers, 1 while reading payload, and 2 when done (internal data) */ @@ -107,6 +116,19 @@ int libmds_message_initialise(libmds_message_t* restrict this); __attribute__((nonnull)) void libmds_message_destroy(libmds_message_t* restrict this); +/** + * Release all resources in a message, should + * be done even if initialisation fails + * + * @param this The message + * @return The duplicate, you do not need to call `libmds_message_destroy` + * on it before you call `free` on it. However, you cannot use + * this is an `libmds_message_t` array (libmds_message_t*), only + * in an `libmds_message_t*` array (libmds_message_t**). + */ +__attribute__((nonnull, malloc, warn_unused_result)) +libmds_message_t* libmds_message_duplicate(libmds_message_t* restrict this); + /** * Read the next message from a file descriptor * -- cgit v1.2.3-70-g09d2