From aaec5aca01062a847378cd476df21babec31ad26 Mon Sep 17 00:00:00 2001 From: Mark Ellzey Date: Tue, 25 Oct 2011 09:13:15 -0400 Subject: [PATCH] Added evbuffer_add_iovec and unit tests. --- buffer.c | 31 +++++++++++++++++++++++++++++ include/event2/buffer.h | 15 ++++++++++++++ test/regress_buffer.c | 44 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+) diff --git a/buffer.c b/buffer.c index 61dd0f3e..e4096553 100644 --- a/buffer.c +++ b/buffer.c @@ -589,6 +589,37 @@ evbuffer_get_contiguous_space(const struct evbuffer *buf) return result; } +size_t +evbuffer_add_iovec(struct evbuffer * buf, struct evbuffer_iovec * vec, int n_vec) { + int n; + size_t res; + size_t to_alloc; + + EVBUFFER_LOCK(buf); + + res = to_alloc = 0; + + for (n = 0; n < n_vec; n++) { + to_alloc += vec[n].iov_len; + } + + if (evbuffer_expand(buf, to_alloc) < 0) { + goto done; + } + + for (n = 0; n < n_vec; n++) { + if (evbuffer_add(buf, vec[n].iov_base, vec[n].iov_len) < 0) { + goto done; + } + + res += vec[n].iov_len; + } + +done: + EVBUFFER_UNLOCK(buf); + return res; +} + int evbuffer_reserve_space(struct evbuffer *buf, ev_ssize_t size, struct evbuffer_iovec *vec, int n_vecs) diff --git a/include/event2/buffer.h b/include/event2/buffer.h index a81e3e55..8738884c 100644 --- a/include/event2/buffer.h +++ b/include/event2/buffer.h @@ -950,6 +950,21 @@ struct event_base; */ int evbuffer_defer_callbacks(struct evbuffer *buffer, struct event_base *base); +/** + Append data from 1 or more iovec's to an evbuffer + + Calculates the number of bytes needed for an iovec structure and guarantees + all data will fit into a single chain. Can be used in lieu of functionality + which calls evbuffer_add() constantly before being used to increase + performance. + + @param buffer the destination buffer + @param vec the source iovec + @param n_vec the number of iovec structures. + @return the number of bytes successfully written to the output buffer. +*/ +size_t evbuffer_add_iovec(struct evbuffer * buffer, struct evbuffer_iovec * vec, int n_vec); + #ifdef __cplusplus } #endif diff --git a/test/regress_buffer.c b/test/regress_buffer.c index eb35c33c..7fdfffdc 100644 --- a/test/regress_buffer.c +++ b/test/regress_buffer.c @@ -1827,6 +1827,49 @@ end: evbuffer_free(tmp_buf); } +static void +test_evbuffer_add_iovec(void * ptr) +{ + struct evbuffer * buf = NULL; + struct evbuffer_iovec vec[4]; + const char * data[] = { + "Guilt resembles a sword with two edges.", + "On the one hand, it cuts for Justice, imposing practical morality upon those who fear it.", + "Conscience does not always adhere to rational judgment.", + "Guilt is always a self-imposed burden, but it is not always rightly imposed." + }; + size_t expected_length = 0; + size_t returned_length = 0; + int i; + + buf = evbuffer_new(); + + for (i = 0; i < 4; i++) { + vec[i].iov_len = strlen(data[i]); + vec[i].iov_base = data[i]; + expected_length += vec[i].iov_len; + } + + returned_length = evbuffer_add_iovec(buf, vec, 4); + + tt_int_op(returned_length, ==, evbuffer_get_length(buf)); + tt_int_op(evbuffer_get_length(buf), ==, expected_length); + + for (i = 0; i < 4; i++) { + char charbuf[1024]; + + memset(charbuf, 0, 1024); + evbuffer_remove(buf, charbuf, strlen(data[i])); + tt_assert(strcmp(charbuf, data[i]) == 0); + } + + tt_assert(evbuffer_get_length(buf) == 0); +end: + if (buf) { + evbuffer_free(buf); + } +} + static void * setup_passthrough(const struct testcase_t *testcase) { @@ -1865,6 +1908,7 @@ struct testcase_t evbuffer_testcases[] = { { "peek", test_evbuffer_peek, 0, NULL, NULL }, { "freeze_start", test_evbuffer_freeze, 0, &nil_setup, (void*)"start" }, { "freeze_end", test_evbuffer_freeze, 0, &nil_setup, (void*)"end" }, + { "add_iovec", test_evbuffer_add_iovec, 0, NULL, NULL}, #define ADDFILE_TEST(name, parameters) \ { name, test_evbuffer_add_file, TT_FORK|TT_NEED_BASE, \ -- 2.40.0