From becc89b7788984924b3041d5a187b1c978bac458 Mon Sep 17 00:00:00 2001
From: Niels Provos <provos@gmail.com>
Date: Sat, 3 May 2008 02:37:18 +0000
Subject: [PATCH] introduce evbuffer_contiguous_space() and use it in the zlib
 filter test

svn:r756
---
 ChangeLog               |  3 ++-
 buffer.c                |  8 ++++++++
 include/event2/buffer.h | 13 +++++++++++++
 test/regress_zlib.c     | 14 ++++++++------
 4 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 1420a900..c31573ed 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -83,7 +83,8 @@ Changes in current version:
  o allow connections to be removed from an rpc pool
  o add new evtimer_assign, signal_assign, evtimer_new, and signal_new functions to manipulate timer and signal events, analagous to the now-recommended event_assign and event_new
  o switch internal uses of event_set over to use event_assign.
-        
+ o introduce evbuffer_contiguous_space() api that tells a user how much data is available in the first buffer chain
+	
 Changes in 1.4.0:
  o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr.
  o demote most http warnings to debug messages
diff --git a/buffer.c b/buffer.c
index e03c00af..20dfb160 100644
--- a/buffer.c
+++ b/buffer.c
@@ -123,6 +123,14 @@ evbuffer_length(struct evbuffer *buffer)
 	return (buffer->total_len);
 }
 
+size_t
+evbuffer_contiguous_space(struct evbuffer *buf)
+{
+	struct evbuffer_chain *chain = buf->first;
+
+	return (chain != NULL ? chain->off : 0);
+}
+
 #define ZERO_CHAIN(dst) do { \
 		(dst)->first = NULL;		\
 		(dst)->last = NULL;		\
diff --git a/include/event2/buffer.h b/include/event2/buffer.h
index 2b77b5d1..637cc2e0 100644
--- a/include/event2/buffer.h
+++ b/include/event2/buffer.h
@@ -93,6 +93,19 @@ void evbuffer_free(struct evbuffer *buf);
 */
 size_t evbuffer_length(struct evbuffer *buf);
 
+/**
+   Returns the contiguous number of available bytes in the first buffer chain.
+
+   This is useful when processing of all available data can be split up into
+   chunks.  Calls to evbuffer_pullup() that cause reallocation and copying
+   of data can thus be avoided.
+
+   @param buf pointer to the evbuffer
+   @return 0 if no data is available, otherwise the number of available bytes
+     in the first buffer chain.
+*/
+size_t evbuffer_contiguous_space(struct evbuffer *buf);
+
 /**
   Expands the available space in an event buffer.
 
diff --git a/test/regress_zlib.c b/test/regress_zlib.c
index 9455bc67..434054c4 100644
--- a/test/regress_zlib.c
+++ b/test/regress_zlib.c
@@ -111,7 +111,7 @@ zlib_input_filter(struct evbuffer *src, struct evbuffer *dst,
 
 	do {
 		/* let's do some decompression */
-		p->avail_in = EVBUFFER_LENGTH(src);
+		p->avail_in = evbuffer_contiguous_space(src);
 		p->next_in = evbuffer_pullup(src, p->avail_in);
 
 		p->next_out = (unsigned char *)tmp;
@@ -123,7 +123,7 @@ zlib_input_filter(struct evbuffer *src, struct evbuffer *dst,
 		assert(res == Z_OK || res == Z_STREAM_END);
 
 		/* let's figure out how much was compressed */
-		nread = EVBUFFER_LENGTH(src) - p->avail_in;
+		nread = evbuffer_contiguous_space(src) - p->avail_in;
 		nwrite = sizeof(tmp) - p->avail_out;
 
 		evbuffer_drain(src, nread);
@@ -147,7 +147,7 @@ zlib_output_filter(struct evbuffer *src, struct evbuffer *dst,
 
 	do {
 		/* let's do some compression */
-		p->avail_in = EVBUFFER_LENGTH(src);
+		p->avail_in = evbuffer_contiguous_space(src);
 		p->next_in = evbuffer_pullup(src, p->avail_in);
 
 		p->next_out = (unsigned char *)tmp;
@@ -158,7 +158,7 @@ zlib_output_filter(struct evbuffer *src, struct evbuffer *dst,
 		assert(res == Z_OK || res == Z_STREAM_END);
 
 		/* let's figure out how much was compressed */
-		nread = EVBUFFER_LENGTH(src) - p->avail_in;
+		nread = evbuffer_contiguous_space(src) - p->avail_in;
 		nwrite = sizeof(tmp) - p->avail_out;
 
 		evbuffer_drain(src, nread);
@@ -246,7 +246,9 @@ test_bufferevent_zlib(void)
 	for (i = 0; i < sizeof(buffer); i++)
 		buffer[i] = i;
 
-	bufferevent_write(bev1, buffer, sizeof(buffer));
+	/* break it up into multiple buffer chains */
+	bufferevent_write(bev1, buffer, 1800);
+	bufferevent_write(bev1, buffer + 1800, sizeof(buffer) - 1800);
 
 	/* we are done writing - we need to flush everything */
 	bufferevent_trigger_filter(bev1, NULL, BEV_OUTPUT, BEV_FLUSH);
@@ -256,7 +258,7 @@ test_bufferevent_zlib(void)
 	bufferevent_free(bev1);
 	bufferevent_free(bev2);
 
-	if (test_ok != 5) {
+	if (test_ok != 6) {
 		fprintf(stdout, "FAILED: %d\n", test_ok);
 		exit(1);
 	}
-- 
2.40.0