diff options
Diffstat (limited to 'contrib/ntp/lib/isc/buffer.c')
-rw-r--r-- | contrib/ntp/lib/isc/buffer.c | 489 |
1 files changed, 489 insertions, 0 deletions
diff --git a/contrib/ntp/lib/isc/buffer.c b/contrib/ntp/lib/isc/buffer.c new file mode 100644 index 0000000..1b59e65 --- /dev/null +++ b/contrib/ntp/lib/isc/buffer.c @@ -0,0 +1,489 @@ +/* + * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1998-2002 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: buffer.c,v 1.49 2008/09/25 04:02:39 tbox Exp $ */ + +/*! \file */ + +#include <config.h> + +#include <isc/buffer.h> +#include <isc/mem.h> +#include <isc/region.h> +#include <isc/string.h> +#include <isc/util.h> + +void +isc__buffer_init(isc_buffer_t *b, const void *base, unsigned int length) { + /* + * Make 'b' refer to the 'length'-byte region starting at 'base'. + * XXXDCL see the comment in buffer.h about base being const. + */ + + REQUIRE(b != NULL); + + ISC__BUFFER_INIT(b, base, length); +} + +void +isc__buffer_initnull(isc_buffer_t *b) { + /* + * Initialize a new buffer which has no backing store. This can + * later be grown as needed and swapped in place. + */ + + ISC__BUFFER_INIT(b, NULL, 0); +} + +void +isc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length) { + /* + * Re-initialize the buffer enough to reconfigure the base of the + * buffer. We will swap in the new buffer, after copying any + * data we contain into the new buffer and adjusting all of our + * internal pointers. + * + * The buffer must not be smaller than the length of the original + * buffer. + */ + REQUIRE(b->length <= length); + REQUIRE(base != NULL); + + (void)memmove(base, b->base, b->length); + b->base = base; + b->length = length; +} + +void +isc__buffer_invalidate(isc_buffer_t *b) { + /* + * Make 'b' an invalid buffer. + */ + + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(!ISC_LINK_LINKED(b, link)); + REQUIRE(b->mctx == NULL); + + ISC__BUFFER_INVALIDATE(b); +} + +void +isc__buffer_region(isc_buffer_t *b, isc_region_t *r) { + /* + * Make 'r' refer to the region of 'b'. + */ + + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(r != NULL); + + ISC__BUFFER_REGION(b, r); +} + +void +isc__buffer_usedregion(isc_buffer_t *b, isc_region_t *r) { + /* + * Make 'r' refer to the used region of 'b'. + */ + + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(r != NULL); + + ISC__BUFFER_USEDREGION(b, r); +} + +void +isc__buffer_availableregion(isc_buffer_t *b, isc_region_t *r) { + /* + * Make 'r' refer to the available region of 'b'. + */ + + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(r != NULL); + + ISC__BUFFER_AVAILABLEREGION(b, r); +} + +void +isc__buffer_add(isc_buffer_t *b, unsigned int n) { + /* + * Increase the 'used' region of 'b' by 'n' bytes. + */ + + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(b->used + n <= b->length); + + ISC__BUFFER_ADD(b, n); +} + +void +isc__buffer_subtract(isc_buffer_t *b, unsigned int n) { + /* + * Decrease the 'used' region of 'b' by 'n' bytes. + */ + + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(b->used >= n); + + ISC__BUFFER_SUBTRACT(b, n); +} + +void +isc__buffer_clear(isc_buffer_t *b) { + /* + * Make the used region empty. + */ + + REQUIRE(ISC_BUFFER_VALID(b)); + + ISC__BUFFER_CLEAR(b); +} + +void +isc__buffer_consumedregion(isc_buffer_t *b, isc_region_t *r) { + /* + * Make 'r' refer to the consumed region of 'b'. + */ + + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(r != NULL); + + ISC__BUFFER_CONSUMEDREGION(b, r); +} + +void +isc__buffer_remainingregion(isc_buffer_t *b, isc_region_t *r) { + /* + * Make 'r' refer to the remaining region of 'b'. + */ + + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(r != NULL); + + ISC__BUFFER_REMAININGREGION(b, r); +} + +void +isc__buffer_activeregion(isc_buffer_t *b, isc_region_t *r) { + /* + * Make 'r' refer to the active region of 'b'. + */ + + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(r != NULL); + + ISC__BUFFER_ACTIVEREGION(b, r); +} + +void +isc__buffer_setactive(isc_buffer_t *b, unsigned int n) { + /* + * Sets the end of the active region 'n' bytes after current. + */ + + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(b->current + n <= b->used); + + ISC__BUFFER_SETACTIVE(b, n); +} + +void +isc__buffer_first(isc_buffer_t *b) { + /* + * Make the consumed region empty. + */ + + REQUIRE(ISC_BUFFER_VALID(b)); + + ISC__BUFFER_FIRST(b); +} + +void +isc__buffer_forward(isc_buffer_t *b, unsigned int n) { + /* + * Increase the 'consumed' region of 'b' by 'n' bytes. + */ + + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(b->current + n <= b->used); + + ISC__BUFFER_FORWARD(b, n); +} + +void +isc__buffer_back(isc_buffer_t *b, unsigned int n) { + /* + * Decrease the 'consumed' region of 'b' by 'n' bytes. + */ + + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(n <= b->current); + + ISC__BUFFER_BACK(b, n); +} + +void +isc_buffer_compact(isc_buffer_t *b) { + unsigned int length; + void *src; + + /* + * Compact the used region by moving the remaining region so it occurs + * at the start of the buffer. The used region is shrunk by the size + * of the consumed region, and the consumed region is then made empty. + */ + + REQUIRE(ISC_BUFFER_VALID(b)); + + src = isc_buffer_current(b); + length = isc_buffer_remaininglength(b); + (void)memmove(b->base, src, (size_t)length); + + if (b->active > b->current) + b->active -= b->current; + else + b->active = 0; + b->current = 0; + b->used = length; +} + +isc_uint8_t +isc_buffer_getuint8(isc_buffer_t *b) { + unsigned char *cp; + isc_uint8_t result; + + /* + * Read an unsigned 8-bit integer from 'b' and return it. + */ + + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(b->used - b->current >= 1); + + cp = isc_buffer_current(b); + b->current += 1; + result = ((isc_uint8_t)(cp[0])); + + return (result); +} + +void +isc__buffer_putuint8(isc_buffer_t *b, isc_uint8_t val) { + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(b->used + 1 <= b->length); + + ISC__BUFFER_PUTUINT8(b, val); +} + +isc_uint16_t +isc_buffer_getuint16(isc_buffer_t *b) { + unsigned char *cp; + isc_uint16_t result; + + /* + * Read an unsigned 16-bit integer in network byte order from 'b', + * convert it to host byte order, and return it. + */ + + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(b->used - b->current >= 2); + + cp = isc_buffer_current(b); + b->current += 2; + result = ((unsigned int)(cp[0])) << 8; + result |= ((unsigned int)(cp[1])); + + return (result); +} + +void +isc__buffer_putuint16(isc_buffer_t *b, isc_uint16_t val) { + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(b->used + 2 <= b->length); + + ISC__BUFFER_PUTUINT16(b, val); +} + +void +isc__buffer_putuint24(isc_buffer_t *b, isc_uint32_t val) { + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(b->used + 3 <= b->length); + + ISC__BUFFER_PUTUINT24(b, val); +} + +isc_uint32_t +isc_buffer_getuint32(isc_buffer_t *b) { + unsigned char *cp; + isc_uint32_t result; + + /* + * Read an unsigned 32-bit integer in network byte order from 'b', + * convert it to host byte order, and return it. + */ + + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(b->used - b->current >= 4); + + cp = isc_buffer_current(b); + b->current += 4; + result = ((unsigned int)(cp[0])) << 24; + result |= ((unsigned int)(cp[1])) << 16; + result |= ((unsigned int)(cp[2])) << 8; + result |= ((unsigned int)(cp[3])); + + return (result); +} + +void +isc__buffer_putuint32(isc_buffer_t *b, isc_uint32_t val) { + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(b->used + 4 <= b->length); + + ISC__BUFFER_PUTUINT32(b, val); +} + +isc_uint64_t +isc_buffer_getuint48(isc_buffer_t *b) { + unsigned char *cp; + isc_uint64_t result; + + /* + * Read an unsigned 48-bit integer in network byte order from 'b', + * convert it to host byte order, and return it. + */ + + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(b->used - b->current >= 6); + + cp = isc_buffer_current(b); + b->current += 6; + result = ((isc_int64_t)(cp[0])) << 40; + result |= ((isc_int64_t)(cp[1])) << 32; + result |= ((isc_int64_t)(cp[2])) << 24; + result |= ((isc_int64_t)(cp[3])) << 16; + result |= ((isc_int64_t)(cp[4])) << 8; + result |= ((isc_int64_t)(cp[5])); + + return (result); +} + +void +isc__buffer_putuint48(isc_buffer_t *b, isc_uint64_t val) { + isc_uint16_t valhi; + isc_uint32_t vallo; + + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(b->used + 6 <= b->length); + + valhi = (isc_uint16_t)(val >> 32); + vallo = (isc_uint32_t)(val & 0xFFFFFFFF); + ISC__BUFFER_PUTUINT16(b, valhi); + ISC__BUFFER_PUTUINT32(b, vallo); +} + +void +isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base, + unsigned int length) +{ + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(b->used + length <= b->length); + + ISC__BUFFER_PUTMEM(b, base, length); +} + +void +isc__buffer_putstr(isc_buffer_t *b, const char *source) { + unsigned int l; + unsigned char *cp; + + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(source != NULL); + + /* + * Do not use ISC__BUFFER_PUTSTR(), so strlen is only done once. + */ + l = strlen(source); + + REQUIRE(l <= isc_buffer_availablelength(b)); + + cp = isc_buffer_used(b); + memcpy(cp, source, l); + b->used += l; +} + +isc_result_t +isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r) { + unsigned char *base; + unsigned int available; + + REQUIRE(ISC_BUFFER_VALID(b)); + REQUIRE(r != NULL); + + /* + * XXXDCL + */ + base = isc_buffer_used(b); + available = isc_buffer_availablelength(b); + if (r->length > available) + return (ISC_R_NOSPACE); + memcpy(base, r->base, r->length); + b->used += r->length; + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer, + unsigned int length) +{ + isc_buffer_t *dbuf; + + REQUIRE(dynbuffer != NULL); + REQUIRE(*dynbuffer == NULL); + + dbuf = isc_mem_get(mctx, length + sizeof(isc_buffer_t)); + if (dbuf == NULL) + return (ISC_R_NOMEMORY); + + isc_buffer_init(dbuf, ((unsigned char *)dbuf) + sizeof(isc_buffer_t), + length); + dbuf->mctx = mctx; + + *dynbuffer = dbuf; + + return (ISC_R_SUCCESS); +} + +void +isc_buffer_free(isc_buffer_t **dynbuffer) { + unsigned int real_length; + isc_buffer_t *dbuf; + isc_mem_t *mctx; + + REQUIRE(dynbuffer != NULL); + REQUIRE(ISC_BUFFER_VALID(*dynbuffer)); + REQUIRE((*dynbuffer)->mctx != NULL); + + dbuf = *dynbuffer; + *dynbuffer = NULL; /* destroy external reference */ + + real_length = dbuf->length + sizeof(isc_buffer_t); + mctx = dbuf->mctx; + dbuf->mctx = NULL; + isc_buffer_invalidate(dbuf); + + isc_mem_put(mctx, dbuf, real_length); +} |