mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-09 12:28:19 -04:00
Merge remote-tracking branch 'github/21_end_of_buffer'
Conflicts: include/event2/buffer.h
This commit is contained in:
commit
7d08a28c1c
49
buffer.c
49
buffer.c
@ -132,6 +132,13 @@
|
||||
#define CHAIN_PINNED(ch) (((ch)->flags & EVBUFFER_MEM_PINNED_ANY) != 0)
|
||||
#define CHAIN_PINNED_R(ch) (((ch)->flags & EVBUFFER_MEM_PINNED_R) != 0)
|
||||
|
||||
/* evbuffer_ptr support */
|
||||
#define PTR_NOT_FOUND(ptr) do { \
|
||||
(ptr)->pos = -1; \
|
||||
(ptr)->_internal.chain = NULL; \
|
||||
(ptr)->_internal.pos_in_chain = 0; \
|
||||
} while (0)
|
||||
|
||||
static void evbuffer_chain_align(struct evbuffer_chain *chain);
|
||||
static int evbuffer_chain_should_realign(struct evbuffer_chain *chain,
|
||||
size_t datalen);
|
||||
@ -1302,7 +1309,7 @@ evbuffer_strspn(
|
||||
size_t i = ptr->_internal.pos_in_chain;
|
||||
|
||||
if (!chain)
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
while (1) {
|
||||
char *buffer = (char *)chain->buffer + chain->misalign;
|
||||
@ -1333,13 +1340,16 @@ evbuffer_strspn(
|
||||
}
|
||||
|
||||
|
||||
static inline char
|
||||
static inline int
|
||||
evbuffer_getchr(struct evbuffer_ptr *it)
|
||||
{
|
||||
struct evbuffer_chain *chain = it->_internal.chain;
|
||||
size_t off = it->_internal.pos_in_chain;
|
||||
|
||||
return chain->buffer[chain->misalign + off];
|
||||
if (chain == NULL)
|
||||
return -1;
|
||||
|
||||
return (unsigned char)chain->buffer[chain->misalign + off];
|
||||
}
|
||||
|
||||
struct evbuffer_ptr
|
||||
@ -1351,6 +1361,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) {
|
||||
PTR_NOT_FOUND(&it);
|
||||
if (eol_len_out)
|
||||
*eol_len_out = extra_drain;
|
||||
return it;
|
||||
}
|
||||
|
||||
EVBUFFER_LOCK(buffer);
|
||||
|
||||
if (start) {
|
||||
@ -1411,9 +1429,8 @@ evbuffer_search_eol(struct evbuffer *buffer,
|
||||
done:
|
||||
EVBUFFER_UNLOCK(buffer);
|
||||
|
||||
if (!ok) {
|
||||
it.pos = -1;
|
||||
}
|
||||
if (!ok)
|
||||
PTR_NOT_FOUND(&it);
|
||||
if (eol_len_out)
|
||||
*eol_len_out = extra_drain;
|
||||
|
||||
@ -2294,7 +2311,7 @@ evbuffer_ptr_subtract(struct evbuffer *buf, struct evbuffer_ptr *pos,
|
||||
{
|
||||
if (howfar > (size_t)pos->pos)
|
||||
return -1;
|
||||
if (howfar <= pos->_internal.pos_in_chain) {
|
||||
if (pos->_internal.chain && howfar <= pos->_internal.pos_in_chain) {
|
||||
pos->_internal.pos_in_chain -= howfar;
|
||||
pos->pos -= howfar;
|
||||
return 0;
|
||||
@ -2312,6 +2329,7 @@ evbuffer_ptr_set(struct evbuffer *buf, struct evbuffer_ptr *pos,
|
||||
{
|
||||
size_t left = position;
|
||||
struct evbuffer_chain *chain = NULL;
|
||||
int result = 0;
|
||||
|
||||
EVBUFFER_LOCK(buf);
|
||||
|
||||
@ -2338,14 +2356,18 @@ evbuffer_ptr_set(struct evbuffer *buf, struct evbuffer_ptr *pos,
|
||||
if (chain) {
|
||||
pos->_internal.chain = chain;
|
||||
pos->_internal.pos_in_chain = position + left;
|
||||
} else {
|
||||
} else if (left == 0) {
|
||||
/* The first byte in the (nonexistent) chain after the last chain */
|
||||
pos->_internal.chain = NULL;
|
||||
pos->pos = -1;
|
||||
pos->_internal.pos_in_chain = 0;
|
||||
} else {
|
||||
PTR_NOT_FOUND(pos);
|
||||
result = -1;
|
||||
}
|
||||
|
||||
EVBUFFER_UNLOCK(buf);
|
||||
|
||||
return chain != NULL ? 0 : -1;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2450,8 +2472,7 @@ evbuffer_search_range(struct evbuffer *buffer, const char *what, size_t len, con
|
||||
}
|
||||
|
||||
not_found:
|
||||
pos.pos = -1;
|
||||
pos._internal.chain = NULL;
|
||||
PTR_NOT_FOUND(&pos);
|
||||
done:
|
||||
EVBUFFER_UNLOCK(buffer);
|
||||
return pos;
|
||||
@ -2466,6 +2487,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) {
|
||||
|
@ -105,11 +105,22 @@ struct evbuffer
|
||||
that modifies or re-packs the buffer contents may invalidate all
|
||||
evbuffer_ptrs for that buffer. Do not modify these values except with
|
||||
evbuffer_ptr_set.
|
||||
|
||||
Used when repeatedly searching through a buffer. Calls to any function
|
||||
that modifies or re-packs the buffer contents may invalidate all
|
||||
evbuffer_ptrs for that buffer. Do not modify these values except with
|
||||
evbuffer_ptr_set.
|
||||
|
||||
An evbuffer_ptr can represent any position from the start of a buffer up
|
||||
to a position immediately after the end of a buffer.
|
||||
|
||||
@see evbuffer_ptr_set()
|
||||
*/
|
||||
struct evbuffer_ptr {
|
||||
ev_ssize_t pos;
|
||||
|
||||
/* Do not alter the values of fields. */
|
||||
/* Do not alter or rely on the values of fields: they are for internal
|
||||
* use */
|
||||
struct {
|
||||
void *chain;
|
||||
size_t pos_in_chain;
|
||||
@ -421,17 +432,9 @@ int evbuffer_add_reference(struct evbuffer *outbuf,
|
||||
|
||||
@param outbuf the output buffer
|
||||
@param fd the file descriptor
|
||||
<<<<<<< HEAD
|
||||
@param off the offset from which to read data
|
||||
@param offset the offset from which to read data
|
||||
@param length how much data to read, or -1 to read as much as possible.
|
||||
(-1 requires that 'fd' support fstat.)
|
||||
||||||| merged common ancestors
|
||||
@param off the offset from which to read data
|
||||
@param length how much data to read
|
||||
=======
|
||||
@param offset the offset from which to read data
|
||||
@param length how much data to read
|
||||
>>>>>>> origin/patches-2.0
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
*/
|
||||
|
||||
@ -657,9 +660,18 @@ enum evbuffer_ptr_how {
|
||||
/**
|
||||
Sets the search pointer in the buffer to position.
|
||||
|
||||
If evbuffer_ptr is not initialized. This function can only be called
|
||||
There are two ways to use this function: you can call
|
||||
evbuffer_ptr_set(buf, &pos, N, EVBUFFER_PTR_SET)
|
||||
to move 'pos' to a position 'N' bytes after the start of the buffer, or
|
||||
evbuffer_ptr_set(buf, &pos, N, EVBUFFER_PTR_SET)
|
||||
to move 'pos' forward by 'N' bytes.
|
||||
|
||||
If evbuffer_ptr is not initialized, this function can only be called
|
||||
with EVBUFFER_PTR_SET.
|
||||
|
||||
An evbuffer_ptr can represent any position from the start of the buffer to
|
||||
a position immediately after the end of the buffer.
|
||||
|
||||
@param buffer the evbuffer to be search
|
||||
@param ptr a pointer to a struct evbuffer_ptr
|
||||
@param position the position at which to start the next search
|
||||
|
@ -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;
|
||||
@ -1222,6 +1237,8 @@ test_evbuffer_ptr_set(void *ptr)
|
||||
tt_assert(pos.pos == 10000);
|
||||
tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == 0);
|
||||
tt_assert(pos.pos == 11000);
|
||||
tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == 0);
|
||||
tt_assert(pos.pos == 12000);
|
||||
tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == -1);
|
||||
tt_assert(pos.pos == -1);
|
||||
|
||||
@ -1237,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);
|
||||
@ -1280,6 +1309,20 @@ test_evbuffer_search(void *ptr)
|
||||
pos = evbuffer_search_range(buf, "ack", 3, NULL, &end);
|
||||
tt_int_op(pos.pos, ==, -1);
|
||||
|
||||
/* 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)
|
||||
@ -1630,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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user