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:
Nick Mathewson 2009-08-07 17:16:52 +00:00
parent 0c09fe5ada
commit 8a99083f01
3 changed files with 48 additions and 4 deletions

View File

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

View File

@ -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. */

View File

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