aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@operamail.com>2015-09-04 15:34:10 +0200
committerMattias Andrée <maandree@operamail.com>2015-09-04 15:34:10 +0200
commit324daf82504ef6a409a1d955a804a5f05d572aa4 (patch)
treecf085fa28e009ec802309a2cc03d47c7c231d298
parentoptimise libmds_message (diff)
downloadmds-324daf82504ef6a409a1d955a804a5f05d572aa4.tar.gz
mds-324daf82504ef6a409a1d955a804a5f05d572aa4.tar.bz2
mds-324daf82504ef6a409a1d955a804a5f05d572aa4.tar.xz
add libmds_message_duplicate
Signed-off-by: Mattias Andrée <maandree@operamail.com>
-rw-r--r--src/libmdsclient/inbound.c42
-rw-r--r--src/libmdsclient/inbound.h22
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
@@ -76,6 +76,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)
*/
int stage;
@@ -108,6 +117,19 @@ __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
*
* @param this Memory slot in which to store the new message