# HG changeset patch # User Mike Becker # Date 1349858780 -7200 # Node ID 6814aea8462ddbd1b68f1246adcad466e165f89a # Parent fb07a0ab9a17f47d57ec78d85e584885e0b90a89 added extract function diff -r fb07a0ab9a17 -r 6814aea8462d test/buffer_tests.c --- a/test/buffer_tests.c Wed Oct 10 10:04:01 2012 +0200 +++ b/test/buffer_tests.c Wed Oct 10 10:46:20 2012 +0200 @@ -62,7 +62,8 @@ ucx_buffer_putc(b, 48); ucx_buffer_putc(b, 48); ucx_buffer_putc(b, 48); UCX_TEST_ASSERT(ucx_buffer_tell(b) == 16, "pos wrong after last 3 puts"); UCX_TEST_ASSERT(ucx_buffer_eof(b), "eof not set"); - UCX_TEST_ASSERT(ucx_buffer_putc(b, 48) == EOF, "put shall return EOF on memof"); + UCX_TEST_ASSERT(ucx_buffer_putc(b, 48) == EOF, + "put shall return EOF when buffer is full"); UCX_TEST_ASSERT(memcmp(buffer, "000 000", 16) == 0, "buffer contains incorrect content"); @@ -184,3 +185,28 @@ ucx_buffer_free(b); free(buffer); } + +UCX_TEST_IMPLEMENT(test_ucx_buffer_extract) { + char *buffer = malloc(16); + strcpy(buffer, "this is a test!"); + + UcxBuffer *src = ucx_buffer_new(buffer, 16, UCX_BUFFER_AUTOFREE), + *dst = ucx_buffer_extract(src, 5, 5, UCX_BUFFER_DEFAULT); + + UCX_TEST_BEGIN + UCX_TEST_ASSERT(ucx_buffer_testflags(dst, UCX_BUFFER_AUTOFREE), + "autofree flag shall be enforced"); + UCX_TEST_ASSERT(ucx_buffer_size(dst) == 5, "wrong size for new buffer"); + char rb[5]; + ucx_buffer_read(rb, 1, 5, dst); + UCX_TEST_ASSERT(memcmp(rb, "is a ", 5) == 0, + "new buffer has incorrect content"); + + UCX_TEST_ASSERT(ucx_buffer_extract(dst, 3, 3, UCX_BUFFER_DEFAULT) == NULL, + "extract shall fail on invalid bounds"); + + UCX_TEST_END + + ucx_buffer_free(dst); + ucx_buffer_free(src); +} diff -r fb07a0ab9a17 -r 6814aea8462d test/buffer_tests.h --- a/test/buffer_tests.h Wed Oct 10 10:04:01 2012 +0200 +++ b/test/buffer_tests.h Wed Oct 10 10:46:20 2012 +0200 @@ -19,6 +19,7 @@ UCX_TEST_DECLARE(test_ucx_buffer_getc); UCX_TEST_DECLARE(test_ucx_buffer_write); UCX_TEST_DECLARE(test_ucx_buffer_read); +UCX_TEST_DECLARE(test_ucx_buffer_extract); #ifdef __cplusplus } diff -r fb07a0ab9a17 -r 6814aea8462d test/main.c --- a/test/main.c Wed Oct 10 10:04:01 2012 +0200 +++ b/test/main.c Wed Oct 10 10:46:20 2012 +0200 @@ -169,6 +169,7 @@ ucx_test_register(suite, test_ucx_buffer_getc); ucx_test_register(suite, test_ucx_buffer_write); ucx_test_register(suite, test_ucx_buffer_read); + ucx_test_register(suite, test_ucx_buffer_extract); ucx_test_run(suite, stdout); fflush(stdout); diff -r fb07a0ab9a17 -r 6814aea8462d ucx/buffer.c --- a/ucx/buffer.c Wed Oct 10 10:04:01 2012 +0200 +++ b/ucx/buffer.c Wed Oct 10 10:46:20 2012 +0200 @@ -5,8 +5,8 @@ struct UcxBuffer { void *space; - off_t pos; - size_t length; + size_t pos; + size_t size; int flags; }; @@ -25,7 +25,7 @@ } else { buffer->space = space; } - buffer->length = length; + buffer->size = length; buffer->pos = 0; } @@ -34,12 +34,36 @@ } void ucx_buffer_free(UcxBuffer *buffer) { - if ((buffer->flags & UCX_BUFFER_AUTOFREE) > 0) { + if (ucx_buffer_testflags(buffer, UCX_BUFFER_AUTOFREE)) { free(buffer->space); } free(buffer); } +UcxBuffer *ucx_buffer_extract( + UcxBuffer *src, size_t start, size_t length, int flags) { + if (length == 0) { + length = src->size - start; + } + if (start+length > src->size) { + return NULL; + } + + UcxBuffer *dst = (UcxBuffer*) malloc(sizeof(UcxBuffer)); + if (dst) { + dst->space = malloc(length); + if (!dst->space) { + free(dst); + return NULL; + } + dst->size = length; + dst->flags = flags | UCX_BUFFER_AUTOFREE; + dst->pos = 0; + memcpy(dst->space, (char*)src->space+start, length); + } + return dst; +} + int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence) { off_t npos; switch (whence) { @@ -56,7 +80,7 @@ npos += offset; - if (npos < 0 || npos > buffer->length) { + if (npos < 0 || npos > buffer->size) { return -1; } else { buffer->pos = npos; @@ -66,17 +90,25 @@ } int ucx_buffer_eof(UcxBuffer *buffer) { - return buffer->pos >= buffer->length; + return buffer->pos >= buffer->size; } size_t ucx_buffer_tell(UcxBuffer *buffer) { return buffer->pos; } +size_t ucx_buffer_size(UcxBuffer *buffer) { + return buffer->size; +} + +int ucx_buffer_testflags(UcxBuffer *buffer, int flags) { + return (buffer->flags & flags) == flags; +} + size_t ucx_bufio(void* d, size_t s, size_t n, UcxBuffer *b, _Bool read) { size_t len; - if (b->pos + s*n > b->length) { - len = b->length - b->pos; + if (b->pos + s*n > b->size) { + len = b->size - b->pos; if (s > 1) len -= len%s; } else { len = s*n; diff -r fb07a0ab9a17 -r 6814aea8462d ucx/buffer.h --- a/ucx/buffer.h Wed Oct 10 10:04:01 2012 +0200 +++ b/ucx/buffer.h Wed Oct 10 10:46:20 2012 +0200 @@ -1,6 +1,7 @@ #ifndef BUFFER_H #define BUFFER_H +#include #include #ifdef __cplusplus @@ -18,6 +19,16 @@ void ucx_buffer_free(UcxBuffer* buffer); /* + * the autofree flag is enforced for the new buffer + * if length is zero, the whole remaining buffer shall be extracted + * the position of the new buffer is set to zero + */ +UcxBuffer *ucx_buffer_extract(UcxBuffer *src, + size_t start, size_t length, int flags); +#define ucx_buffer_clone(src,flags) \ + ucx_buffer_extract(src, 0, 0, flags) + +/* * Moves the position of the buffer to a new position relative to whence. * * SEEK_SET marks the start of the buffer @@ -31,6 +42,9 @@ */ int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence); size_t ucx_buffer_tell(UcxBuffer *buffer); +size_t ucx_buffer_size(UcxBuffer *buffer); +/* returns non-zero, if at least the specified flags are set */ +int ucx_buffer_testflags(UcxBuffer *buffer, int flags); /* * returns non-zero, iff the current buffer position has exceeded the last