Mercurial > dovecot > core-2.2
changeset 23008:d7ad84cec527
lib: buffer - Add buffer_replace().
author | Stephan Bosch <stephan.bosch@dovecot.fi> |
---|---|
date | Thu, 14 Mar 2019 23:55:00 +0100 |
parents | 36e01285b5b8 |
children | 7f2568b494ac |
files | src/lib/buffer.c src/lib/buffer.h src/lib/test-buffer.c |
diffstat | 3 files changed, 98 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib/buffer.c Mon Mar 18 00:52:37 2019 +0100 +++ b/src/lib/buffer.c Thu Mar 14 23:55:00 2019 +0100 @@ -234,6 +234,40 @@ buffer_set_used_size(_buf, pos + end_size); } +void buffer_replace(buffer_t *_buf, size_t pos, size_t size, + const void *data, size_t data_size) +{ + struct real_buffer *buf = (struct real_buffer *)_buf; + size_t end_size; + + if (pos >= buf->used) { + buffer_write(_buf, pos, data, data_size); + return; + } + end_size = buf->used - pos; + + if (size < end_size) { + end_size -= size; + if (data_size == 0) { + /* delete from between */ + memmove(buf->w_buffer + pos, + buf->w_buffer + pos + size, end_size); + } else { + /* insert */ + buffer_copy(_buf, pos + data_size, _buf, pos + size, + (size_t)-1); + memcpy(buf->w_buffer + pos, data, data_size); + } + } else { + /* overwrite the end */ + end_size = 0; + buffer_write(_buf, pos, data, data_size); + } + + buffer_set_used_size(_buf, pos + data_size + end_size); +} + + void buffer_write_zero(buffer_t *_buf, size_t pos, size_t data_size) { struct real_buffer *buf = (struct real_buffer *)_buf;
--- a/src/lib/buffer.h Mon Mar 18 00:52:37 2019 +0100 +++ b/src/lib/buffer.h Thu Mar 14 23:55:00 2019 +0100 @@ -59,6 +59,11 @@ deleted block may cross the current buffer size boundary, which is ignored. */ void buffer_delete(buffer_t *buf, size_t pos, size_t size); +/* Replace the data in the buffer with the indicated size at position pos with + the provided data. This is a more optimized version of + buffer_delete(buf, pos, size); buffer_insert(buf, pos, data, data_size); */ +void buffer_replace(buffer_t *buf, size_t pos, size_t size, + const void *data, size_t data_size); /* Fill buffer with zero bytes. */ void buffer_write_zero(buffer_t *buf, size_t pos, size_t data_size);
--- a/src/lib/test-buffer.c Mon Mar 18 00:52:37 2019 +0100 +++ b/src/lib/test-buffer.c Thu Mar 14 23:55:00 2019 +0100 @@ -10,7 +10,7 @@ buffer_t *buf; unsigned char *p, testdata[BUF_TEST_SIZE], shadowbuf[BUF_TEST_SIZE]; unsigned int i, shadowbuf_size; - size_t pos, pos2, size; + size_t pos, pos2, size, size2; int test = -1; bool zero; @@ -29,7 +29,7 @@ i_assert(buf->used < BUF_TEST_SIZE); } - test = rand() % 6; + test = rand() % 7; zero = rand() % 10 == 0; switch (test) { case 0: @@ -95,6 +95,31 @@ } break; case 4: + pos = rand() % (BUF_TEST_SIZE - 1); + size = rand() % (BUF_TEST_SIZE - pos); + size2 = rand() % (BUF_TEST_SIZE - I_MAX(buf->used, pos)); + buffer_replace(buf, pos, size, testdata, size2); + if (pos < shadowbuf_size) { + if (pos + size > shadowbuf_size) + size = shadowbuf_size - pos; + memmove(shadowbuf + pos, + shadowbuf + pos + size, + BUF_TEST_SIZE - (pos + size)); + + shadowbuf_size -= size; + memset(shadowbuf + shadowbuf_size, 0, + BUF_TEST_SIZE - shadowbuf_size); + } + memmove(shadowbuf + pos + size2, + shadowbuf + pos, + BUF_TEST_SIZE - (pos + size2)); + memcpy(shadowbuf + pos, testdata, size2); + if (pos < shadowbuf_size) + shadowbuf_size += size2; + else + shadowbuf_size = pos + size2; + break; + case 5: if (shadowbuf_size <= 1) break; pos = rand() % (shadowbuf_size-1); /* dest */ @@ -106,7 +131,7 @@ if (pos > pos2 && pos + size > shadowbuf_size) shadowbuf_size = pos + size; break; - case 5: + case 6: pos = rand() % (BUF_TEST_SIZE-1); size = rand() % (BUF_TEST_SIZE - pos); p = buffer_get_space_unsafe(buf, pos, size); @@ -271,10 +296,41 @@ test_end(); } +static void test_buffer_replace(void) +{ + const char orig_input[] = "123456789"; + const char data[] = "abcdefghij"; + buffer_t *buf, *buf2; + unsigned int init_size, pos, size, data_size; + + test_begin("buffer_replace()"); + for (init_size = 0; init_size <= sizeof(orig_input)-1; init_size++) { + for (pos = 0; pos < sizeof(orig_input)+1; pos++) { + for (size = 0; size < sizeof(orig_input)+1; size++) { + for (data_size = 0; data_size <= sizeof(data)-1; data_size++) T_BEGIN { + buf = buffer_create_dynamic(pool_datastack_create(), 4); + buf2 = buffer_create_dynamic(pool_datastack_create(), 4); + buffer_append(buf, orig_input, init_size); + buffer_append(buf2, orig_input, init_size); + + buffer_replace(buf, pos, size, data, data_size); + buffer_delete(buf2, pos, size); + buffer_insert(buf2, pos, data, data_size); + test_assert(buf->used == buf2->used && + memcmp(buf->data, buf2->data, buf->used) == 0); + } T_END; + } + } + } + + test_end(); +} + void test_buffer(void) { test_buffer_random(); test_buffer_write(); test_buffer_set_used_size(); test_buffer_truncate_bits(); + test_buffer_replace(); }