Added evbuffer_add_iovec and unit tests.

This commit is contained in:
Mark Ellzey 2011-10-25 09:13:15 -04:00 committed by Nick Mathewson
parent 95af043314
commit aaec5aca01
3 changed files with 90 additions and 0 deletions

View File

@ -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)

View File

@ -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

View File

@ -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, \