Commit 441a57f9 authored by Michael Graff's avatar Michael Graff

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.
parent 292c7d39
......@@ -22,9 +22,14 @@
#include <isc/assertions.h>
#include <isc/buffer.h>
#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);
}
......@@ -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 <isc/lang.h>
#include <isc/list.h>
#include <isc/mem.h>
#include <isc/region.h>
#include <isc/int.h>
......@@ -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,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment