2 * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1998-2002 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: buffer.c,v 1.40.18.2 2005/04/29 00:16:44 marka Exp $ */
24 #include <isc/buffer.h>
26 #include <isc/region.h>
27 #include <isc/string.h>
31 isc__buffer_init(isc_buffer_t *b, const void *base, unsigned int length) {
33 * Make 'b' refer to the 'length'-byte region starting at 'base'.
34 * XXXDCL see the comment in buffer.h about base being const.
39 ISC__BUFFER_INIT(b, base, length);
43 isc__buffer_invalidate(isc_buffer_t *b) {
45 * Make 'b' an invalid buffer.
48 REQUIRE(ISC_BUFFER_VALID(b));
49 REQUIRE(!ISC_LINK_LINKED(b, link));
50 REQUIRE(b->mctx == NULL);
52 ISC__BUFFER_INVALIDATE(b);
56 isc__buffer_region(isc_buffer_t *b, isc_region_t *r) {
58 * Make 'r' refer to the region of 'b'.
61 REQUIRE(ISC_BUFFER_VALID(b));
64 ISC__BUFFER_REGION(b, r);
68 isc__buffer_usedregion(isc_buffer_t *b, isc_region_t *r) {
70 * Make 'r' refer to the used region of 'b'.
73 REQUIRE(ISC_BUFFER_VALID(b));
76 ISC__BUFFER_USEDREGION(b, r);
80 isc__buffer_availableregion(isc_buffer_t *b, isc_region_t *r) {
82 * Make 'r' refer to the available region of 'b'.
85 REQUIRE(ISC_BUFFER_VALID(b));
88 ISC__BUFFER_AVAILABLEREGION(b, r);
92 isc__buffer_add(isc_buffer_t *b, unsigned int n) {
94 * Increase the 'used' region of 'b' by 'n' bytes.
97 REQUIRE(ISC_BUFFER_VALID(b));
98 REQUIRE(b->used + n <= b->length);
100 ISC__BUFFER_ADD(b, n);
104 isc__buffer_subtract(isc_buffer_t *b, unsigned int n) {
106 * Decrease the 'used' region of 'b' by 'n' bytes.
109 REQUIRE(ISC_BUFFER_VALID(b));
110 REQUIRE(b->used >= n);
112 ISC__BUFFER_SUBTRACT(b, n);
116 isc__buffer_clear(isc_buffer_t *b) {
118 * Make the used region empty.
121 REQUIRE(ISC_BUFFER_VALID(b));
123 ISC__BUFFER_CLEAR(b);
127 isc__buffer_consumedregion(isc_buffer_t *b, isc_region_t *r) {
129 * Make 'r' refer to the consumed region of 'b'.
132 REQUIRE(ISC_BUFFER_VALID(b));
135 ISC__BUFFER_CONSUMEDREGION(b, r);
139 isc__buffer_remainingregion(isc_buffer_t *b, isc_region_t *r) {
141 * Make 'r' refer to the remaining region of 'b'.
144 REQUIRE(ISC_BUFFER_VALID(b));
147 ISC__BUFFER_REMAININGREGION(b, r);
151 isc__buffer_activeregion(isc_buffer_t *b, isc_region_t *r) {
153 * Make 'r' refer to the active region of 'b'.
156 REQUIRE(ISC_BUFFER_VALID(b));
159 ISC__BUFFER_ACTIVEREGION(b, r);
163 isc__buffer_setactive(isc_buffer_t *b, unsigned int n) {
165 * Sets the end of the active region 'n' bytes after current.
168 REQUIRE(ISC_BUFFER_VALID(b));
169 REQUIRE(b->current + n <= b->used);
171 ISC__BUFFER_SETACTIVE(b, n);
175 isc__buffer_first(isc_buffer_t *b) {
177 * Make the consumed region empty.
180 REQUIRE(ISC_BUFFER_VALID(b));
182 ISC__BUFFER_FIRST(b);
186 isc__buffer_forward(isc_buffer_t *b, unsigned int n) {
188 * Increase the 'consumed' region of 'b' by 'n' bytes.
191 REQUIRE(ISC_BUFFER_VALID(b));
192 REQUIRE(b->current + n <= b->used);
194 ISC__BUFFER_FORWARD(b, n);
198 isc__buffer_back(isc_buffer_t *b, unsigned int n) {
200 * Decrease the 'consumed' region of 'b' by 'n' bytes.
203 REQUIRE(ISC_BUFFER_VALID(b));
204 REQUIRE(n <= b->current);
206 ISC__BUFFER_BACK(b, n);
210 isc_buffer_compact(isc_buffer_t *b) {
215 * Compact the used region by moving the remaining region so it occurs
216 * at the start of the buffer. The used region is shrunk by the size
217 * of the consumed region, and the consumed region is then made empty.
220 REQUIRE(ISC_BUFFER_VALID(b));
222 src = isc_buffer_current(b);
223 length = isc_buffer_remaininglength(b);
224 (void)memmove(b->base, src, (size_t)length);
226 if (b->active > b->current)
227 b->active -= b->current;
235 isc_buffer_getuint8(isc_buffer_t *b) {
240 * Read an unsigned 8-bit integer from 'b' and return it.
243 REQUIRE(ISC_BUFFER_VALID(b));
244 REQUIRE(b->used - b->current >= 1);
246 cp = isc_buffer_current(b);
248 result = ((isc_uint8_t)(cp[0]));
254 isc__buffer_putuint8(isc_buffer_t *b, isc_uint8_t val) {
255 REQUIRE(ISC_BUFFER_VALID(b));
256 REQUIRE(b->used + 1 <= b->length);
258 ISC__BUFFER_PUTUINT8(b, val);
262 isc_buffer_getuint16(isc_buffer_t *b) {
267 * Read an unsigned 16-bit integer in network byte order from 'b',
268 * convert it to host byte order, and return it.
271 REQUIRE(ISC_BUFFER_VALID(b));
272 REQUIRE(b->used - b->current >= 2);
274 cp = isc_buffer_current(b);
276 result = ((unsigned int)(cp[0])) << 8;
277 result |= ((unsigned int)(cp[1]));
283 isc__buffer_putuint16(isc_buffer_t *b, isc_uint16_t val) {
284 REQUIRE(ISC_BUFFER_VALID(b));
285 REQUIRE(b->used + 2 <= b->length);
287 ISC__BUFFER_PUTUINT16(b, val);
291 isc_buffer_getuint32(isc_buffer_t *b) {
296 * Read an unsigned 32-bit integer in network byte order from 'b',
297 * convert it to host byte order, and return it.
300 REQUIRE(ISC_BUFFER_VALID(b));
301 REQUIRE(b->used - b->current >= 4);
303 cp = isc_buffer_current(b);
305 result = ((unsigned int)(cp[0])) << 24;
306 result |= ((unsigned int)(cp[1])) << 16;
307 result |= ((unsigned int)(cp[2])) << 8;
308 result |= ((unsigned int)(cp[3]));
314 isc__buffer_putuint32(isc_buffer_t *b, isc_uint32_t val) {
315 REQUIRE(ISC_BUFFER_VALID(b));
316 REQUIRE(b->used + 4 <= b->length);
318 ISC__BUFFER_PUTUINT32(b, val);
322 isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base,
325 REQUIRE(ISC_BUFFER_VALID(b));
326 REQUIRE(b->used + length <= b->length);
328 ISC__BUFFER_PUTMEM(b, base, length);
332 isc__buffer_putstr(isc_buffer_t *b, const char *source) {
336 REQUIRE(ISC_BUFFER_VALID(b));
337 REQUIRE(source != NULL);
340 * Do not use ISC__BUFFER_PUTSTR(), so strlen is only done once.
344 REQUIRE(l <= isc_buffer_availablelength(b));
346 cp = isc_buffer_used(b);
347 memcpy(cp, source, l);
352 isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r) {
354 unsigned int available;
356 REQUIRE(ISC_BUFFER_VALID(b));
362 base = isc_buffer_used(b);
363 available = isc_buffer_availablelength(b);
364 if (r->length > available)
365 return (ISC_R_NOSPACE);
366 memcpy(base, r->base, r->length);
367 b->used += r->length;
369 return (ISC_R_SUCCESS);
373 isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
378 REQUIRE(dynbuffer != NULL);
379 REQUIRE(*dynbuffer == NULL);
381 dbuf = isc_mem_get(mctx, length + sizeof(isc_buffer_t));
383 return (ISC_R_NOMEMORY);
385 isc_buffer_init(dbuf, ((unsigned char *)dbuf) + sizeof(isc_buffer_t),
391 return (ISC_R_SUCCESS);
395 isc_buffer_free(isc_buffer_t **dynbuffer) {
396 unsigned int real_length;
400 REQUIRE(dynbuffer != NULL);
401 REQUIRE(ISC_BUFFER_VALID(*dynbuffer));
402 REQUIRE((*dynbuffer)->mctx != NULL);
405 *dynbuffer = NULL; /* destroy external reference */
407 real_length = dbuf->length + sizeof(isc_buffer_t);
410 isc_buffer_invalidate(dbuf);
412 isc_mem_put(mctx, dbuf, real_length);