summaryrefslogtreecommitdiff
path: root/buffer.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2011-06-01 14:19:13 -0400
committerNick Mathewson <nickm@torproject.org>2011-06-01 14:19:13 -0400
commit7b9d13957ff3c2e85e2964b467bcf08d118495a8 (patch)
tree1fe492ae1a161885bdf5316360886c5a21a5cb9f /buffer.c
parent25fe382981ef419186b3e09178d4aea7ee5e8753 (diff)
downloadlibevent-7b9d13957ff3c2e85e2964b467bcf08d118495a8.tar.gz
Try to squeeze a little more speed out of EVBUFFER_EOL_CRLF
Diffstat (limited to 'buffer.c')
-rw-r--r--buffer.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/buffer.c b/buffer.c
index 16cb2c90..d6ecb81a 100644
--- a/buffer.c
+++ b/buffer.c
@@ -140,6 +140,8 @@ static int evbuffer_ptr_memcmp(const struct evbuffer *buf,
const struct evbuffer_ptr *pos, const char *mem, size_t len);
static struct evbuffer_chain *evbuffer_expand_singlechain(struct evbuffer *buf,
size_t datlen);
+static int evbuffer_ptr_subtract(struct evbuffer *buf, struct evbuffer_ptr *pos,
+ size_t howfar);
static struct evbuffer_chain *
evbuffer_chain_new(size_t size)
@@ -1373,14 +1375,18 @@ evbuffer_search_eol(struct evbuffer *buffer,
break;
}
case EVBUFFER_EOL_CRLF:
- // Is a LF
+ /* Look for a LF ... */
if (evbuffer_strchr(&it, '\n') < 0)
goto done;
extra_drain = 1;
- // Optionally preceeded by a CR
+ /* ... optionally preceeded by a CR. */
if (it.pos < 1) break;
+ /* This potentially does an extra linear walk over the first
+ * few chains. Probably, that's not too expensive unless you
+ * have a really pathological setup. */
memcpy(&it2, &it, sizeof(it));
- if (evbuffer_ptr_set(buffer, &it2, it2.pos - 1, EVBUFFER_PTR_SET)<0) break;
+ if (evbuffer_ptr_subtract(buffer, &it2, 1)<0)
+ break;
if (evbuffer_getchr(&it2) == '\r') {
memcpy(&it, &it2, sizeof(it));
extra_drain = 2;
@@ -2271,6 +2277,29 @@ evbuffer_find(struct evbuffer *buffer, const unsigned char *what, size_t len)
return search;
}
+/* Subract <b>howfar</b> from the position of <b>pos</b> within
+ * <b>buf</b>. Returns 0 on success, -1 on failure.
+ *
+ * This isn't exposed yet, because of potential inefficiency issues.
+ * Maybe it should be. */
+static int
+evbuffer_ptr_subtract(struct evbuffer *buf, struct evbuffer_ptr *pos,
+ size_t howfar)
+{
+ if (howfar > (size_t)pos->pos)
+ return -1;
+ if (howfar <= pos->_internal.pos_in_chain) {
+ pos->_internal.pos_in_chain -= howfar;
+ pos->pos -= howfar;
+ return 0;
+ } else {
+ const size_t newpos = pos->pos - howfar;
+ /* Here's the inefficient part: it walks over the
+ * chains until we hit newpos. */
+ return evbuffer_ptr_set(buf, pos, newpos, EVBUFFER_PTR_SET);
+ }
+}
+
int
evbuffer_ptr_set(struct evbuffer *buf, struct evbuffer_ptr *pos,
size_t position, enum evbuffer_ptr_how how)