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;
pos._internal.pos_in_chain = 0;
}
+ if (end)
+ last_chain = end->_internal.chain;
+
if (!len)
goto done;
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) {
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:
*/
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. */
{
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 */
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);