summaryrefslogtreecommitdiff
path: root/src/utils/buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils/buffer.c')
-rw-r--r--src/utils/buffer.c86
1 files changed, 70 insertions, 16 deletions
diff --git a/src/utils/buffer.c b/src/utils/buffer.c
index 716e67c..5e0f58c 100644
--- a/src/utils/buffer.c
+++ b/src/utils/buffer.c
@@ -30,12 +30,13 @@ parserutils_error parserutils_buffer_create(parserutils_buffer **buffer)
if (b == NULL)
return PARSERUTILS_NOMEM;
- b->data = malloc(DEFAULT_SIZE);
- if (b->data == NULL) {
+ b->alloc = malloc(DEFAULT_SIZE);
+ if (b->alloc == NULL) {
free(b);
return PARSERUTILS_NOMEM;
}
+ b->data = b->alloc;
b->length = 0;
b->allocated = DEFAULT_SIZE;
@@ -55,13 +56,59 @@ parserutils_error parserutils_buffer_destroy(parserutils_buffer *buffer)
if (buffer == NULL)
return PARSERUTILS_BADPARM;
- free(buffer->data);
+ free(buffer->alloc);
free(buffer);
return PARSERUTILS_OK;
}
/**
+ * Get current data offset within buffer's allocation.
+ *
+ * \param[in] buffer The buffer object.
+ * \return data offset in bytes.
+ */
+static inline size_t get_offset(parserutils_buffer *buffer)
+{
+ return buffer->data - buffer->alloc;
+}
+
+/**
+ * Try moving the data to the start of the allocation.
+ *
+ * \param[in] buffer The buffer object.
+ */
+static inline void try_rebase(parserutils_buffer *buffer)
+{
+ if (get_offset(buffer) >= buffer->length) {
+ memcpy(buffer->alloc, buffer->data, buffer->length);
+ buffer->data = buffer->alloc;
+ }
+}
+
+/**
+ * Ensure that the buffer has enough space at the end to add len bytes.
+ *
+ * \param[in] buffer The buffer object.
+ * \param[in] len Number of bytes to ensure there is space for.
+ * \return PARSERUTILS_OK on success, appropriate error otherwise.
+ */
+static inline parserutils_error ensure_space(
+ parserutils_buffer *buffer,
+ size_t len)
+{
+ try_rebase(buffer);
+
+ while (len >= buffer->allocated - buffer->length - get_offset(buffer)) {
+ parserutils_error error = parserutils_buffer_grow(buffer);
+ if (error != PARSERUTILS_OK)
+ return error;
+ }
+
+ return PARSERUTILS_OK;
+}
+
+/**
* Append data to a memory buffer
*
* \param buffer The buffer to append to
@@ -72,11 +119,9 @@ parserutils_error parserutils_buffer_destroy(parserutils_buffer *buffer)
parserutils_error parserutils_buffer_append(parserutils_buffer *buffer,
const uint8_t *data, size_t len)
{
- while (len >= buffer->allocated - buffer->length) {
- parserutils_error error = parserutils_buffer_grow(buffer);
- if (error != PARSERUTILS_OK)
- return error;
- }
+ parserutils_error error = ensure_space(buffer, len);
+ if (error != PARSERUTILS_OK)
+ return error;
memcpy(buffer->data + buffer->length, data, len);
@@ -97,17 +142,17 @@ parserutils_error parserutils_buffer_append(parserutils_buffer *buffer,
parserutils_error parserutils_buffer_insert(parserutils_buffer *buffer,
size_t offset, const uint8_t *data, size_t len)
{
+ parserutils_error error;
+
if (offset > buffer->length)
return PARSERUTILS_BADPARM;
if (offset == buffer->length)
return parserutils_buffer_append(buffer, data, len);
- while (len >= buffer->allocated - buffer->length) {
- parserutils_error error = parserutils_buffer_grow(buffer);
- if (error != PARSERUTILS_OK)
- return error;
- }
+ error = ensure_space(buffer, len);
+ if (error != PARSERUTILS_OK)
+ return error;
memmove(buffer->data + offset + len,
buffer->data + offset, buffer->length - offset);
@@ -133,6 +178,13 @@ parserutils_error parserutils_buffer_discard(parserutils_buffer *buffer,
if (offset >= buffer->length || offset + len > buffer->length)
return PARSERUTILS_BADPARM;
+ if (offset == 0) {
+ buffer->data += len;
+ buffer->length -= len;
+ try_rebase(buffer);
+ return PARSERUTILS_OK;
+ }
+
memmove(buffer->data + offset, buffer->data + offset + len,
buffer->length - (len + offset));
@@ -149,11 +201,13 @@ parserutils_error parserutils_buffer_discard(parserutils_buffer *buffer,
*/
parserutils_error parserutils_buffer_grow(parserutils_buffer *buffer)
{
- uint8_t *temp = realloc(buffer->data, buffer->allocated * 2);
+ size_t offset = get_offset(buffer);
+ uint8_t *temp = realloc(buffer->alloc, buffer->allocated * 2);
if (temp == NULL)
return PARSERUTILS_NOMEM;
- buffer->data = temp;
+ buffer->alloc = temp;
+ buffer->data = buffer->alloc + offset;
buffer->allocated *= 2;
return PARSERUTILS_OK;
@@ -180,7 +234,7 @@ parserutils_error parserutils_buffer_randomise(parserutils_buffer *buffer)
/* Leak the buffer's current data, so we don't reuse it */
/* buffer->alloc(buffer->data, 0, buffer->pw); */
- buffer->data = temp;
+ buffer->alloc = buffer->data = temp;
#endif