From 441a57f959ae5e08b3008e067898d11d5ab71e0b Mon Sep 17 00:00:00 2001 From: Michael Graff Date: Mon, 19 Apr 1999 23:56:36 +0000 Subject: [PATCH] Add support for dyamic buffers. These are allocated using isc_dynbuffer_allocate() and freed with isc_dynbuffer_free(), and are a linkable buffer type with a built-in data area. --- lib/isc/buffer.c | 50 +++++++++++++++++++++++++- lib/isc/include/isc/buffer.h | 69 +++++++++++++++++++++++++++++++++++- 2 files changed, 117 insertions(+), 2 deletions(-) diff --git a/lib/isc/buffer.c b/lib/isc/buffer.c index f8ed735cdc..30921f36bc 100644 --- a/lib/isc/buffer.c +++ b/lib/isc/buffer.c @@ -22,9 +22,14 @@ #include #include +#define BUFFER_MAGIC 0x42756621U /* Buf!. */ +#define DYNBUFFER_MAGIC 0x64427566U /* dBuf. */ + #define VALID_BUFFER(b) ((b) != NULL && \ (b)->magic == BUFFER_MAGIC) -#define BUFFER_MAGIC 0x42756621U /* Buf!. */ + +#define VALID_DYNBUFFER(b) ((b) != NULL && \ + (b)->magic == DYNBUFFER_MAGIC) void isc_buffer_init(isc_buffer_t *b, void *base, unsigned int length, @@ -349,3 +354,46 @@ isc_buffer_putuint32(isc_buffer_t *b, isc_uint32_t val) cp[2] = (val & 0x0000ff00) >> 8; cp[3] = (val & 0x000000ff); } + +isc_result_t +isc_dynbuffer_allocate(isc_mem_t *mctx, isc_dynbuffer_t **dynbuffer, + unsigned int length, unsigned int type) +{ + isc_dynbuffer_t *dbuf; + + REQUIRE(dynbuffer != NULL); + REQUIRE(*dynbuffer == NULL); + + dbuf = isc_mem_get(mctx, length + sizeof(isc_dynbuffer_t)); + if (dbuf == NULL) + return (ISC_R_NOMEMORY); + + dbuf->magic = DYNBUFFER_MAGIC; + ISC_LINK_INIT(dbuf, link); + isc_buffer_init(&dbuf->buffer, + ((unsigned char *)dbuf) + sizeof(isc_dynbuffer_t), + length, type); + + *dynbuffer = dbuf; + + return (ISC_R_SUCCESS); +} + +void +isc_dynbuffer_free(isc_mem_t *mctx, isc_dynbuffer_t **dynbuffer) +{ + unsigned int real_length; + isc_dynbuffer_t *dbuf; + + REQUIRE(dynbuffer != NULL); + REQUIRE(VALID_DYNBUFFER(*dynbuffer)); + + dbuf = *dynbuffer; + *dynbuffer = NULL; /* destroy external reference */ + + real_length = dbuf->buffer.length + sizeof(isc_dynbuffer_t); + isc_buffer_invalidate(&dbuf->buffer); + dbuf->magic = 0; + + isc_mem_put(mctx, dbuf, real_length); +} diff --git a/lib/isc/include/isc/buffer.h b/lib/isc/include/isc/buffer.h index a3496ca5ba..6b745b7c42 100644 --- a/lib/isc/include/isc/buffer.h +++ b/lib/isc/include/isc/buffer.h @@ -49,6 +49,24 @@ * is empty. If the current offset advances beyond the chosen offset, the * active region will also be empty. * + * /----- used region -----\/-- available --\ + * +----------------------------------------+ + * | consumed | remaining | | + * +----------------------------------------+ + * a b c d e + * + * a == base of buffer. + * b == current pointer. Can be anywhere between a and d. + * c == active pointer. Meaningful between b and d. + * d == used pointer. + * e == length of buffer. + * + * a-e == entire (length) of buffer. + * a-d == used region. + * a-b == consumed region. + * b-d == remaining region. + * b-c == optional active region. + * * The following invariants are maintained by all routines: * * length > 0 @@ -60,6 +78,7 @@ * 0 <= current <= used * * 0 <= active <= used + * (although active < current implies empty active region) * * MP: * Buffers have no synchronization. Clients must ensure exclusive @@ -69,7 +88,7 @@ * No anticipated impact. * * Resources: - * Memory: 2 pointers + 2 unsigned integers per buffer. + * Memory: 1 pointer + 6 unsigned integers per buffer. * * Security: * No anticipated impact. @@ -83,6 +102,8 @@ ***/ #include +#include +#include #include #include @@ -115,11 +136,57 @@ typedef struct isc_buffer { unsigned int active; } isc_buffer_t; +/* + * A handy thing to have, linkable buffers with built-in storage. These + * are allocated and freed with the isc_dynbuffer_alloc() and _free() + * functions below. These function should _ALWAYS_ be used to create these + * dynbuffers. The link is initialized on allocation and is solely for the + * caller to use. + */ +typedef struct isc_dynbuffer isc_dynbuffer_t; +struct isc_dynbuffer { + unsigned int magic; + isc_buffer_t buffer; + ISC_LINK(isc_dynbuffer_t) link; +}; /* variable sized */ /*** *** Functions ***/ +isc_result_t +isc_dynbuffer_allocate(isc_mem_t *mctx, isc_dynbuffer_t **dynbuffer, + unsigned int length, unsigned int type); +/* + * Allocate a dynamic linkable buffer which has "length" bytes in the + * data region. + * + * Requires: + * "mctx" is valid. + * + * "dynbuffer" is non-NULL, and "*dynbuffer" is NULL. + * + * Returns: + * ISC_R_SUCCESS - success + * ISC_R_NOMEMORY - no memory available + */ + +void +isc_dynbuffer_free(isc_mem_t *mctx, isc_dynbuffer_t **dynbuffer); +/* + * Release resources allocated for a dynamic buffer. + * + * Requires: + * "dynbuffer" is not NULL. + * + * "*dynbuffer" is a valid dynamic buffer. + * + * "mctx" is valid. + * + * Ensures: + * "*dynbuffer" will be NULL on return, and all memory associated with + * the dynamic buffer is returned to memory context "mctx". + */ void isc_buffer_init(isc_buffer_t *b, void *base, unsigned int length,