From 7aeb2fd4ca222ac84a8f86bf9739a4cfde6f6c4a Mon Sep 17 00:00:00 2001 From: Nir Soffer Date: Mon, 13 Jun 2011 16:35:28 -0400 Subject: [PATCH] Allow evbuffer_ptr to point to position 0 in an empty evbuffer --- buffer.c | 22 +++++++++++++++++--- test/regress_buffer.c | 48 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 65 insertions(+), 5 deletions(-) diff --git a/buffer.c b/buffer.c index c4297ed0..9d8820e0 100644 --- a/buffer.c +++ b/buffer.c @@ -1334,6 +1334,9 @@ evbuffer_getchr(struct evbuffer_ptr *it) struct evbuffer_chain *chain = it->_internal.chain; size_t off = it->_internal.pos_in_chain; + if (chain == NULL) + return -1; /* XXX Better invalid char value? */ + return chain->buffer[chain->misalign + off]; } @@ -1346,6 +1349,14 @@ evbuffer_search_eol(struct evbuffer *buffer, size_t extra_drain = 0; int ok = 0; + /* Avoid locking in trivial edge cases */ + if (start && start->_internal.chain == NULL) { + it.pos = -1; + if (eol_len_out) + *eol_len_out = extra_drain; + return it; + } + EVBUFFER_LOCK(buffer); if (start) { @@ -2334,9 +2345,10 @@ evbuffer_ptr_set(struct evbuffer *buf, struct evbuffer_ptr *pos, if (chain) { pos->_internal.chain = chain; pos->_internal.pos_in_chain = position + left; - } else if (left == 0 && buf->last) { - pos->_internal.chain = buf->last; - pos->_internal.pos_in_chain = buf->last->off; + } else if (left == 0) { + /* The first byte in the (nonexistent) chain after the last chain */ + pos->_internal.chain = NULL; + pos->_internal.pos_in_chain = 0; } else { pos->_internal.chain = NULL; pos->pos = -1; @@ -2466,6 +2478,10 @@ evbuffer_peek(struct evbuffer *buffer, ev_ssize_t len, int idx = 0; ev_ssize_t len_so_far = 0; + /* Avoid locking in trivial edge cases */ + if (start_at && start_at->_internal.chain == NULL) + return 0; + EVBUFFER_LOCK(buffer); if (start_at) { diff --git a/test/regress_buffer.c b/test/regress_buffer.c index a9a4f6a3..03a27ead 100644 --- a/test/regress_buffer.c +++ b/test/regress_buffer.c @@ -1090,6 +1090,12 @@ test_evbuffer_search_eol(void *ptr) tt_int_op(ptr2.pos, ==, 11); tt_int_op(eol_len, ==, 1); + tt_assert(evbuffer_ptr_set(buf, &ptr1, evbuffer_get_length(buf), EVBUFFER_PTR_SET) == 0); + eol_len = -1; + ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF); + tt_int_op(ptr2.pos, ==, -1); + tt_int_op(eol_len, ==, 0); + end: evbuffer_free(buf); } @@ -1190,6 +1196,15 @@ test_evbuffer_ptr_set(void *ptr) struct evbuffer_ptr pos; struct evbuffer_iovec v[1]; + tt_int_op(evbuffer_get_length(buf), ==, 0); + + tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0); + tt_assert(pos.pos == 0); + tt_assert(evbuffer_ptr_set(buf, &pos, 1, EVBUFFER_PTR_ADD) == -1); + tt_assert(pos.pos == -1); + tt_assert(evbuffer_ptr_set(buf, &pos, 1, EVBUFFER_PTR_SET) == -1); + tt_assert(pos.pos == -1); + /* create some chains */ evbuffer_reserve_space(buf, 5000, v, 1); v[0].iov_len = 5000; @@ -1239,6 +1254,18 @@ test_evbuffer_search(void *ptr) struct evbuffer *tmp = evbuffer_new(); struct evbuffer_ptr pos, end; + pos = evbuffer_search(buf, "x", 1, NULL); + tt_int_op(pos.pos, ==, -1); + tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0); + pos = evbuffer_search(buf, "x", 1, &pos); + tt_int_op(pos.pos, ==, -1); + tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0); + pos = evbuffer_search_range(buf, "x", 1, &pos, &pos); + tt_int_op(pos.pos, ==, -1); + tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0); + pos = evbuffer_search_range(buf, "x", 1, &pos, NULL); + tt_int_op(pos.pos, ==, -1); + /* set up our chains */ evbuffer_add_printf(tmp, "hello"); /* 5 chars */ evbuffer_add_buffer(buf, tmp); @@ -1282,10 +1309,20 @@ test_evbuffer_search(void *ptr) pos = evbuffer_search_range(buf, "ack", 3, NULL, &end); tt_int_op(pos.pos, ==, -1); - /* Set "end" to the last byte in the buffer. */ - evbuffer_ptr_set(buf, &end, 17, EVBUFFER_PTR_SET); + /* Set "end" after the last byte in the buffer. */ + tt_assert(evbuffer_ptr_set(buf, &end, 17, EVBUFFER_PTR_SET) == 0); + pos = evbuffer_search_range(buf, "attack", 6, NULL, &end); tt_int_op(pos.pos, ==, 11); + tt_assert(evbuffer_ptr_set(buf, &pos, 11, EVBUFFER_PTR_SET) == 0); + pos = evbuffer_search_range(buf, "attack", 6, &pos, &end); + tt_int_op(pos.pos, ==, 11); + tt_assert(evbuffer_ptr_set(buf, &pos, 17, EVBUFFER_PTR_SET) == 0); + pos = evbuffer_search_range(buf, "attack", 6, &pos, &end); + tt_int_op(pos.pos, ==, -1); + tt_assert(evbuffer_ptr_set(buf, &pos, 17, EVBUFFER_PTR_SET) == 0); + pos = evbuffer_search_range(buf, "attack", 6, &pos, NULL); + tt_int_op(pos.pos, ==, -1); end: if (buf) @@ -1636,6 +1673,13 @@ test_evbuffer_peek(void *info) tt_iov_eq(&v[0], "Contents of chunk [2]\n"); tt_iov_eq(&v[1], "Contents of chunk [3]\n"); /*more than we asked for*/ + /* peek at the end of the buffer */ + memset(v, 0, sizeof(v)); + tt_assert(evbuffer_ptr_set(buf, &ptr, evbuffer_get_length(buf), EVBUFFER_PTR_SET) == 0); + i = evbuffer_peek(buf, 44, &ptr, v, 20); + tt_int_op(i, ==, 0); + tt_assert(v[0].iov_base == NULL); + end: if (buf) evbuffer_free(buf); -- 2.40.0