* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
* \brief A buffer is a region of memory, together with a set of related subregions.
* Buffers are used for parsing and I/O operations.
* The 'used region' and the 'available' region are disjoint, and their
* union is the buffer's region. The used region extends from the beginning
* of the buffer region to the last used byte. The available region
* extends from one byte greater than the last used byte to the end of the
* buffer's region. The size of the used region can be changed using various
* buffer commands. Initially, the used region is empty.
* The used region is further subdivided into two disjoint regions: the
* 'consumed region' and the 'remaining region'. The union of these two
* regions is the used region. The consumed region extends from the beginning
* of the used region to the byte before the 'current' offset (if any). The
* 'remaining' region the current pointer to the end of the used
* region. The size of the consumed region can be changed using various
* buffer commands. Initially, the consumed region is empty.
* The 'active region' is an (optional) subregion of the remaining region.
* It extends from the current offset to an offset in the remaining region
* that is selected with isc_buffer_setactive(). Initially, the active region
* is empty. If the current offset advances beyond the chosen offset, the
* active region will also be empty.
* /------------entire length---------------\
* /----- used region -----\/-- available --\
* +----------------------------------------+
* | consumed | remaining | |
* +----------------------------------------+
* b == current pointer. Can be anywhere between a and d.
* c == active pointer. Meaningful between b and d.
* a-e == entire length of buffer.
* a-b == consumed region.
* b-d == remaining region.
* b-c == optional active region.
* The following invariants are maintained by all routines:
* base is a valid pointer to length bytes of memory
* (although active < current implies empty active region)
* Buffers have no synchronization. Clients must ensure exclusive
* Memory: 1 pointer + 6 unsigned integers per buffer.
#include <isc/assertions.h>
#include <isc/formatcheck.h>
* To make many functions be inline macros (via \#define) define this.
* If it is undefined, a function will be used.
/* #define ISC_BUFFER_USEINLINE */
#define ISC_BUFFER_MAGIC 0x42756621U /* Buf!. */
#define ISC_BUFFER_VALID(b) ISC_MAGIC_VALID(b, ISC_BUFFER_MAGIC)
* Size granularity for dynamically resizable buffers; when reserving
* space in a buffer, we round the allocated buffer length up to the
* nearest * multiple of this value.
#define ISC_BUFFER_INCR 2048
* The following macros MUST be used only on valid buffers. It is the
* caller's responsibility to ensure this by using the ISC_BUFFER_VALID
* check above, or by calling another isc_buffer_*() function (rather than
* Fundamental buffer elements. (A through E in the introductory comment.)
#define isc_buffer_base(b) ((void *)(b)->base) /*a*/
#define isc_buffer_current(b) \
((void *)((unsigned char *)(b)->base + (b)->current)) /*b*/
#define isc_buffer_active(b) \
((void *)((unsigned char *)(b)->base + (b)->active)) /*c*/
#define isc_buffer_used(b) \
((void *)((unsigned char *)(b)->base + (b)->used)) /*d*/
#define isc_buffer_length(b) ((b)->length) /*e*/
* Derived lengths. (Described in the introductory comment.)
#define isc_buffer_usedlength(b) ((b)->used) /* d-a */
#define isc_buffer_consumedlength(b) ((b)->current) /* b-a */
#define isc_buffer_remaininglength(b) ((b)->used - (b)->current) /* d-b */
#define isc_buffer_activelength(b) ((b)->active - (b)->current) /* c-b */
#define isc_buffer_availablelength(b) ((b)->length - (b)->used) /* e-d */
* Note that the buffer structure is public. This is principally so buffer
* operations can be implemented using macros. Applications are strongly
* discouraged from directly manipulating the structure.
/*! The following integers are byte offsets from 'base'. */
ISC_LINK(isc_buffer_t) link;
/*! private internal elements */
/* automatically realloc buffer at put* */
isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
* \brief Allocate a dynamic linkable buffer which has "length" bytes in the
*\li "dynbuffer" is non-NULL, and "*dynbuffer" is NULL.
*\li ISC_R_SUCCESS - success
*\li ISC_R_NOMEMORY - no memory available
*\li Changing the buffer's length field is not permitted.
isc_buffer_reallocate(isc_buffer_t **dynbuffer, unsigned int length);
* \brief Reallocate the buffer to be "length" bytes long. The buffer
* pointer may move when you call this function.
*\li "dynbuffer" is not NULL.
*\li "*dynbuffer" is a valid dynamic buffer.
*\li 'length' > current length of buffer.
*\li ISC_R_SUCCESS - success
*\li ISC_R_NOMEMORY - no memory available
*\li "*dynbuffer" will be valid on return and will contain all the
* original data. However, the buffer pointer may be moved during
isc_buffer_reserve(isc_buffer_t **dynbuffer, unsigned int size);
* \brief Make "size" bytes of space available in the buffer. The buffer
* pointer may move when you call this function.
*\li "dynbuffer" is not NULL.
*\li "*dynbuffer" is a valid dynamic buffer.
*\li ISC_R_SUCCESS - success
*\li ISC_R_NOMEMORY - no memory available
*\li "*dynbuffer" will be valid on return and will contain all the
* original data. However, the buffer pointer may be moved during
isc_buffer_free(isc_buffer_t **dynbuffer);
* \brief Release resources allocated for a dynamic buffer.
*\li "dynbuffer" is not NULL.
*\li "*dynbuffer" is a valid dynamic buffer.
*\li "*dynbuffer" will be NULL on return, and all memory associated with
* the dynamic buffer is returned to the memory context used in
isc__buffer_init(isc_buffer_t *b, void *base, unsigned int length);
* \brief Make 'b' refer to the 'length'-byte region starting at base.
*\li 'base' is a pointer to a sequence of 'length' bytes.
isc__buffer_initnull(isc_buffer_t *b);
*\brief Initialize a buffer 'b' with a null data and zero length/
isc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length);
* \brief Make 'b' refer to the 'length'-byte region starting at base.
* Any existing data will be copied.
*\li 'length' > 0 AND length >= previous length
*\li 'base' is a pointer to a sequence of 'length' bytes.
isc__buffer_invalidate(isc_buffer_t *b);
* \brief Make 'b' an invalid buffer.
*\li 'b' is a valid buffer.
*\li If assertion checking is enabled, future attempts to use 'b' without
* calling isc_buffer_init() on it will cause an assertion failure.
isc_buffer_setautorealloc(isc_buffer_t *b, bool enable);
* \brief Enable or disable autoreallocation on 'b'.
*\li 'b' is a valid dynamic buffer (b->mctx != NULL).
isc__buffer_region(isc_buffer_t *b, isc_region_t *r);
* \brief Make 'r' refer to the region of 'b'.
*\li 'b' is a valid buffer.
*\li 'r' points to a region structure.
isc__buffer_usedregion(const isc_buffer_t *b, isc_region_t *r);
* \brief Make 'r' refer to the used region of 'b'.
*\li 'b' is a valid buffer.
*\li 'r' points to a region structure.
isc__buffer_availableregion(isc_buffer_t *b, isc_region_t *r);
* \brief Make 'r' refer to the available region of 'b'.
*\li 'b' is a valid buffer.
*\li 'r' points to a region structure.
isc__buffer_add(isc_buffer_t *b, unsigned int n);
* \brief Increase the 'used' region of 'b' by 'n' bytes.
*\li 'b' is a valid buffer
isc__buffer_subtract(isc_buffer_t *b, unsigned int n);
* \brief Decrease the 'used' region of 'b' by 'n' bytes.
*\li 'b' is a valid buffer
isc__buffer_clear(isc_buffer_t *b);
* \brief Make the used region empty.
*\li 'b' is a valid buffer
isc__buffer_consumedregion(isc_buffer_t *b, isc_region_t *r);
* \brief Make 'r' refer to the consumed region of 'b'.
*\li 'b' is a valid buffer.
*\li 'r' points to a region structure.
isc__buffer_remainingregion(isc_buffer_t *b, isc_region_t *r);
* \brief Make 'r' refer to the remaining region of 'b'.
*\li 'b' is a valid buffer.
*\li 'r' points to a region structure.
isc__buffer_activeregion(isc_buffer_t *b, isc_region_t *r);
* \brief Make 'r' refer to the active region of 'b'.
*\li 'b' is a valid buffer.
*\li 'r' points to a region structure.
isc__buffer_setactive(isc_buffer_t *b, unsigned int n);
* \brief Sets the end of the active region 'n' bytes after current.
*\li 'b' is a valid buffer.
isc__buffer_first(isc_buffer_t *b);
* \brief Make the consumed region empty.
*\li 'b' is a valid buffer
isc__buffer_forward(isc_buffer_t *b, unsigned int n);
* \brief Increase the 'consumed' region of 'b' by 'n' bytes.
*\li 'b' is a valid buffer
isc__buffer_back(isc_buffer_t *b, unsigned int n);
* \brief Decrease the 'consumed' region of 'b' by 'n' bytes.
*\li 'b' is a valid buffer
isc_buffer_compact(isc_buffer_t *b);