mirror of
https://github.com/libevent/libevent.git
synced 2025-01-31 09:12:55 +08:00
Add an evbuffer_search_range() to search a bounded range of a buffer
This can be handy when you have one search to find the end of a header section, and then you want to find a substring within the header section without looking at the body. svn:r1410
This commit is contained in:
parent
0c09fe5ada
commit
8a99083f01
22
buffer.c
22
buffer.c
@ -1967,9 +1967,15 @@ evbuffer_ptr_memcmp(const struct evbuffer *buf, const struct evbuffer_ptr *pos,
|
||||
|
||||
struct evbuffer_ptr
|
||||
evbuffer_search(struct evbuffer *buffer, const char *what, size_t len, const struct evbuffer_ptr *start)
|
||||
{
|
||||
return evbuffer_search_range(buffer, what, len, start, NULL);
|
||||
}
|
||||
|
||||
struct evbuffer_ptr
|
||||
evbuffer_search_range(struct evbuffer *buffer, const char *what, size_t len, const struct evbuffer_ptr *start, const struct evbuffer_ptr *end)
|
||||
{
|
||||
struct evbuffer_ptr pos;
|
||||
struct evbuffer_chain *chain;
|
||||
struct evbuffer_chain *chain, *last_chain = NULL;
|
||||
const unsigned char *p;
|
||||
char first;
|
||||
|
||||
@ -1984,6 +1990,9 @@ evbuffer_search(struct evbuffer *buffer, const char *what, size_t len, const str
|
||||
pos._internal.pos_in_chain = 0;
|
||||
}
|
||||
|
||||
if (end)
|
||||
last_chain = end->_internal.chain;
|
||||
|
||||
if (!len)
|
||||
goto done;
|
||||
|
||||
@ -1998,8 +2007,12 @@ evbuffer_search(struct evbuffer *buffer, const char *what, size_t len, const str
|
||||
if (p) {
|
||||
pos.pos += p - start_at;
|
||||
pos._internal.pos_in_chain += p - start_at;
|
||||
if (!evbuffer_ptr_memcmp(buffer, &pos, what, len))
|
||||
goto done;
|
||||
if (!evbuffer_ptr_memcmp(buffer, &pos, what, len)) {
|
||||
if (end && pos.pos + len > end->pos)
|
||||
goto not_found;
|
||||
else
|
||||
goto done;
|
||||
}
|
||||
++pos.pos;
|
||||
++pos._internal.pos_in_chain;
|
||||
if (pos._internal.pos_in_chain == chain->off) {
|
||||
@ -2007,12 +2020,15 @@ evbuffer_search(struct evbuffer *buffer, const char *what, size_t len, const str
|
||||
pos._internal.pos_in_chain = 0;
|
||||
}
|
||||
} else {
|
||||
if (chain == last_chain)
|
||||
goto not_found;
|
||||
pos.pos += chain->off - pos._internal.pos_in_chain;
|
||||
chain = pos._internal.chain = chain->next;
|
||||
pos._internal.pos_in_chain = 0;
|
||||
}
|
||||
}
|
||||
|
||||
not_found:
|
||||
pos.pos = -1;
|
||||
pos._internal.chain = NULL;
|
||||
done:
|
||||
|
@ -456,6 +456,22 @@ int evbuffer_read(struct evbuffer *buffer, evutil_socket_t fd, int howmuch);
|
||||
*/
|
||||
struct evbuffer_ptr evbuffer_search(struct evbuffer *buffer, const char *what, size_t len, const struct evbuffer_ptr *start);
|
||||
|
||||
/**
|
||||
Search for a string within part of an evbuffer.
|
||||
|
||||
@param buffer the evbuffer to be searched
|
||||
@param what the string to be searched for
|
||||
@param len the length of the search string
|
||||
@param start NULL or a pointer to a valid struct evbuffer_ptr that
|
||||
indicates where we should start searching.
|
||||
@param end NULL or a pointer to a valid struct evbuffer_ptr that
|
||||
indicates where we should stop searching.
|
||||
@return a struct evbuffer_ptr whose 'pos' field has the offset of the
|
||||
first occurrence of the string in the buffer after 'start'. The 'pos'
|
||||
field of the result is -1 if the string was not found.
|
||||
*/
|
||||
struct evbuffer_ptr evbuffer_search_range(struct evbuffer *buffer, const char *what, size_t len, const struct evbuffer_ptr *start, const struct evbuffer_ptr *end);
|
||||
|
||||
enum evbuffer_ptr_how {
|
||||
/** Sets the pointer to the position; can be called on with an
|
||||
uninitialized evbuffer_ptr. */
|
||||
|
@ -715,7 +715,7 @@ test_evbuffer_search(void *ptr)
|
||||
{
|
||||
struct evbuffer *buf = evbuffer_new();
|
||||
struct evbuffer *tmp = evbuffer_new();
|
||||
struct evbuffer_ptr pos;
|
||||
struct evbuffer_ptr pos, end;
|
||||
|
||||
/* set up our chains */
|
||||
evbuffer_add_printf(tmp, "hello"); /* 5 chars */
|
||||
@ -748,6 +748,18 @@ test_evbuffer_search(void *ptr)
|
||||
pos = evbuffer_search(buf, "tat", 3, &pos);
|
||||
tt_int_op(pos.pos, ==, 10);
|
||||
|
||||
/* test bounded search. */
|
||||
/* Set "end" to the first t in "attack". */
|
||||
evbuffer_ptr_set(buf, &end, 12, EVBUFFER_PTR_SET);
|
||||
pos = evbuffer_search_range(buf, "foo", 3, NULL, &end);
|
||||
tt_int_op(pos.pos, ==, 5);
|
||||
pos = evbuffer_search_range(buf, "foocata", 7, NULL, &end);
|
||||
tt_int_op(pos.pos, ==, 5);
|
||||
pos = evbuffer_search_range(buf, "foocatat", 8, NULL, &end);
|
||||
tt_int_op(pos.pos, ==, -1);
|
||||
pos = evbuffer_search_range(buf, "ack", 3, NULL, &end);
|
||||
tt_int_op(pos.pos, ==, -1);
|
||||
|
||||
end:
|
||||
if (buf)
|
||||
evbuffer_free(buf);
|
||||
|
Loading…
x
Reference in New Issue
Block a user