mirror of
https://github.com/libevent/libevent.git
synced 2025-01-09 00:56:20 +08:00
Merge branch 'evbuffer_add_reference_with_offset' - #1513
* evbuffer_add_reference_with_offset: Add a comment for evbuffer_ref_cleanup_cb tests: simplify test_evbuffer_add_reference_with_offset Add function evbuffer_add_reference_with_offset()
This commit is contained in:
commit
c15ba75d18
11
buffer.c
11
buffer.c
@ -2941,6 +2941,14 @@ int
|
||||
evbuffer_add_reference(struct evbuffer *outbuf,
|
||||
const void *data, size_t datlen,
|
||||
evbuffer_ref_cleanup_cb cleanupfn, void *extra)
|
||||
{
|
||||
return evbuffer_add_reference_with_offset(outbuf, data, /* offset= */ 0, datlen, cleanupfn, extra);
|
||||
}
|
||||
|
||||
int
|
||||
evbuffer_add_reference_with_offset(struct evbuffer *outbuf, const void *data,
|
||||
size_t offset, size_t datlen, evbuffer_ref_cleanup_cb cleanupfn,
|
||||
void *extra)
|
||||
{
|
||||
struct evbuffer_chain *chain;
|
||||
struct evbuffer_chain_reference *info;
|
||||
@ -2951,7 +2959,8 @@ evbuffer_add_reference(struct evbuffer *outbuf,
|
||||
return (-1);
|
||||
chain->flags |= EVBUFFER_REFERENCE | EVBUFFER_IMMUTABLE;
|
||||
chain->buffer = (unsigned char *)data;
|
||||
chain->buffer_len = datlen;
|
||||
chain->misalign = offset;
|
||||
chain->buffer_len = offset + datlen;
|
||||
chain->off = datlen;
|
||||
|
||||
info = EVBUFFER_CHAIN_EXTRA(struct evbuffer_chain_reference, chain);
|
||||
|
@ -496,7 +496,11 @@ int evbuffer_add_buffer_reference(struct evbuffer *outbuf,
|
||||
A cleanup function for a piece of memory added to an evbuffer by
|
||||
reference.
|
||||
|
||||
@param data buffer
|
||||
@param datalen - total buffer len (including @offset if any, @see evbuffer_add_reference_with_offset())
|
||||
|
||||
@see evbuffer_add_reference()
|
||||
@see evbuffer_add_reference_with_offset()
|
||||
*/
|
||||
typedef void (*evbuffer_ref_cleanup_cb)(const void *data,
|
||||
size_t datalen, void *extra);
|
||||
@ -521,6 +525,28 @@ int evbuffer_add_reference(struct evbuffer *outbuf,
|
||||
const void *data, size_t datlen,
|
||||
evbuffer_ref_cleanup_cb cleanupfn, void *cleanupfn_arg);
|
||||
|
||||
|
||||
/**
|
||||
Reference memory into an evbuffer without copying.
|
||||
|
||||
The memory needs to remain valid until all the added data has been
|
||||
read. This function keeps just a reference to the memory without
|
||||
actually incurring the overhead of a copy.
|
||||
|
||||
@param outbuf the output buffer
|
||||
@param data the memory to reference
|
||||
@param offset offset inside @data
|
||||
@param datlen how memory to reference (excluding @offset)
|
||||
@param cleanupfn callback to be invoked when the memory is no longer
|
||||
referenced by this evbuffer.
|
||||
@param cleanupfn_arg optional argument to the cleanup callback
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evbuffer_add_reference_with_offset(struct evbuffer *outbuf, const void *data,
|
||||
size_t offset, size_t datlen, evbuffer_ref_cleanup_cb cleanupfn,
|
||||
void *cleanupfn_arg);
|
||||
|
||||
/**
|
||||
Copy data from a file into the evbuffer for writing to a socket.
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "tinytest_macros.h"
|
||||
#include "util-internal.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -2123,6 +2124,81 @@ end:
|
||||
evbuffer_free(buf2);
|
||||
}
|
||||
|
||||
static void
|
||||
ref_done_cb_with_offset(const void *data, size_t len, void *arg)
|
||||
{
|
||||
size_t expected_len = (size_t)arg;
|
||||
if (len != expected_len)
|
||||
TT_FAIL(("%zu != %zu, data: '%s'", len, expected_len, (const char *)data));
|
||||
}
|
||||
static void
|
||||
test_evbuffer_add_reference_with_offset(void* ptr)
|
||||
{
|
||||
const char* prefix = "|prefix| ";
|
||||
const char* content1 = "|prefix| If you have found the answer to such a problem";
|
||||
const char *content2 = "|prefix| you ought to write it up for publication";
|
||||
|
||||
struct evbuffer *buf1 = NULL, *buf2 = NULL;
|
||||
/* -- Knuth's "Notes on the Exercises" from TAOCP */
|
||||
char tmp[16];
|
||||
|
||||
size_t prefix_len = strlen(prefix);
|
||||
size_t len1 = strlen(content1) - prefix_len;
|
||||
size_t len2 = strlen(content2) - prefix_len;
|
||||
|
||||
buf1 = evbuffer_new();
|
||||
tt_assert(buf1);
|
||||
|
||||
evbuffer_add_reference_with_offset(buf1, (const void *)content1, prefix_len,
|
||||
len1, ref_done_cb_with_offset, (void *)(len1 + prefix_len));
|
||||
evbuffer_add(buf1, ", ", 2);
|
||||
evbuffer_add_reference_with_offset(buf1, (const void *)content2, prefix_len,
|
||||
len2, ref_done_cb_with_offset, (void *)(len2 + prefix_len));
|
||||
tt_int_op(evbuffer_get_length(buf1), ==, len1 + len2 + 2 /* ", " */);
|
||||
|
||||
/* Make sure we can drain a little from a reference. */
|
||||
tt_int_op(evbuffer_remove(buf1, tmp, 6), ==, 6);
|
||||
tt_mem_op(tmp, ==, "If you", 6);
|
||||
tt_int_op(evbuffer_remove(buf1, tmp, 5), ==, 5);
|
||||
tt_mem_op(tmp, ==, " have", 5);
|
||||
|
||||
/* Make sure that prepending does not meddle with immutable data */
|
||||
tt_int_op(evbuffer_prepend(buf1, "I have ", 7), ==, 0);
|
||||
tt_mem_op(content1, ==, prefix, prefix_len);
|
||||
evbuffer_validate(buf1);
|
||||
|
||||
/* Make sure that when the chunk is over, the callback is invoked. */
|
||||
evbuffer_drain(buf1, 7); /* Remove prepended stuff. */
|
||||
evbuffer_drain(buf1, len1 - 11 - 1); /* remove all but one byte of chunk1 */
|
||||
evbuffer_remove(buf1, tmp, 1);
|
||||
tt_int_op(tmp[0], ==, 'm');
|
||||
evbuffer_validate(buf1);
|
||||
|
||||
/* Drain some of the remaining chunk, then add it to another buffer */
|
||||
evbuffer_drain(buf1, 6); /* Remove the ", you ". */
|
||||
buf2 = evbuffer_new();
|
||||
tt_assert(buf2);
|
||||
evbuffer_add(buf2, "I ", 2);
|
||||
|
||||
evbuffer_add_buffer(buf2, buf1);
|
||||
evbuffer_remove(buf2, tmp, 16);
|
||||
tt_mem_op("I ought to write", ==, tmp, 16);
|
||||
evbuffer_drain(buf2, evbuffer_get_length(buf2));
|
||||
evbuffer_validate(buf2);
|
||||
|
||||
/* Now add more stuff to buf1 and make sure that it gets removed on free. */
|
||||
evbuffer_add(buf1, "You shake and shake the ", 24);
|
||||
evbuffer_add_reference(
|
||||
buf1, "ketchup bottle", 14, ref_done_cb, (void *)3333);
|
||||
evbuffer_add(buf1, ". Nothing comes and then a lot'll.", 35);
|
||||
|
||||
end:
|
||||
if (buf1)
|
||||
evbuffer_free(buf1);
|
||||
if (buf2)
|
||||
evbuffer_free(buf2);
|
||||
}
|
||||
|
||||
static void
|
||||
test_evbuffer_multicast(void *ptr)
|
||||
{
|
||||
@ -2834,6 +2910,7 @@ struct testcase_t evbuffer_testcases[] = {
|
||||
{ "search", test_evbuffer_search, 0, NULL, NULL },
|
||||
{ "callbacks", test_evbuffer_callbacks, 0, NULL, NULL },
|
||||
{ "add_reference", test_evbuffer_add_reference, 0, NULL, NULL },
|
||||
{ "add_reference_with_offset", test_evbuffer_add_reference_with_offset, 0, NULL, NULL},
|
||||
{ "multicast", test_evbuffer_multicast, 0, NULL, NULL },
|
||||
{ "multicast_drain", test_evbuffer_multicast_drain, 0, NULL, NULL },
|
||||
{ "prepend", test_evbuffer_prepend, TT_FORK, NULL, NULL },
|
||||
|
Loading…
x
Reference in New Issue
Block a user