2 * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1998-2002 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or 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.47 2007/06/19 23:47:17 tbox 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_initnull(isc_buffer_t
*b
) {
45 * Initialize a new buffer which has no backing store. This can
46 * later be grown as needed and swapped in place.
49 ISC__BUFFER_INIT(b
, NULL
, 0);
53 isc_buffer_reinit(isc_buffer_t
*b
, void *base
, unsigned int length
) {
55 * Re-initialize the buffer enough to reconfigure the base of the
56 * buffer. We will swap in the new buffer, after copying any
57 * data we contain into the new buffer and adjusting all of our
60 * The buffer must not be smaller than the length of the original
63 REQUIRE(b
->length
<= length
);
64 REQUIRE(base
!= NULL
);
66 (void)memmove(base
, b
->base
, b
->length
);
72 isc__buffer_invalidate(isc_buffer_t
*b
) {
74 * Make 'b' an invalid buffer.
77 REQUIRE(ISC_BUFFER_VALID(b
));
78 REQUIRE(!ISC_LINK_LINKED(b
, link
));
79 REQUIRE(b
->mctx
== NULL
);
81 ISC__BUFFER_INVALIDATE(b
);
85 isc__buffer_region(isc_buffer_t
*b
, isc_region_t
*r
) {
87 * Make 'r' refer to the region of 'b'.
90 REQUIRE(ISC_BUFFER_VALID(b
));
93 ISC__BUFFER_REGION(b
, r
);
97 isc__buffer_usedregion(isc_buffer_t
*b
, isc_region_t
*r
) {
99 * Make 'r' refer to the used region of 'b'.
102 REQUIRE(ISC_BUFFER_VALID(b
));
105 ISC__BUFFER_USEDREGION(b
, r
);
109 isc__buffer_availableregion(isc_buffer_t
*b
, isc_region_t
*r
) {
111 * Make 'r' refer to the available region of 'b'.
114 REQUIRE(ISC_BUFFER_VALID(b
));
117 ISC__BUFFER_AVAILABLEREGION(b
, r
);
121 isc__buffer_add(isc_buffer_t
*b
, unsigned int n
) {
123 * Increase the 'used' region of 'b' by 'n' bytes.
126 REQUIRE(ISC_BUFFER_VALID(b
));
127 REQUIRE(b
->used
+ n
<= b
->length
);
129 ISC__BUFFER_ADD(b
, n
);
133 isc__buffer_subtract(isc_buffer_t
*b
, unsigned int n
) {
135 * Decrease the 'used' region of 'b' by 'n' bytes.
138 REQUIRE(ISC_BUFFER_VALID(b
));
139 REQUIRE(b
->used
>= n
);
141 ISC__BUFFER_SUBTRACT(b
, n
);
145 isc__buffer_clear(isc_buffer_t
*b
) {
147 * Make the used region empty.
150 REQUIRE(ISC_BUFFER_VALID(b
));
152 ISC__BUFFER_CLEAR(b
);
156 isc__buffer_consumedregion(isc_buffer_t
*b
, isc_region_t
*r
) {
158 * Make 'r' refer to the consumed region of 'b'.
161 REQUIRE(ISC_BUFFER_VALID(b
));
164 ISC__BUFFER_CONSUMEDREGION(b
, r
);
168 isc__buffer_remainingregion(isc_buffer_t
*b
, isc_region_t
*r
) {
170 * Make 'r' refer to the remaining region of 'b'.
173 REQUIRE(ISC_BUFFER_VALID(b
));
176 ISC__BUFFER_REMAININGREGION(b
, r
);
180 isc__buffer_activeregion(isc_buffer_t
*b
, isc_region_t
*r
) {
182 * Make 'r' refer to the active region of 'b'.
185 REQUIRE(ISC_BUFFER_VALID(b
));
188 ISC__BUFFER_ACTIVEREGION(b
, r
);
192 isc__buffer_setactive(isc_buffer_t
*b
, unsigned int n
) {
194 * Sets the end of the active region 'n' bytes after current.
197 REQUIRE(ISC_BUFFER_VALID(b
));
198 REQUIRE(b
->current
+ n
<= b
->used
);
200 ISC__BUFFER_SETACTIVE(b
, n
);
204 isc__buffer_first(isc_buffer_t
*b
) {
206 * Make the consumed region empty.
209 REQUIRE(ISC_BUFFER_VALID(b
));
211 ISC__BUFFER_FIRST(b
);
215 isc__buffer_forward(isc_buffer_t
*b
, unsigned int n
) {
217 * Increase the 'consumed' region of 'b' by 'n' bytes.
220 REQUIRE(ISC_BUFFER_VALID(b
));
221 REQUIRE(b
->current
+ n
<= b
->used
);
223 ISC__BUFFER_FORWARD(b
, n
);
227 isc__buffer_back(isc_buffer_t
*b
, unsigned int n
) {
229 * Decrease the 'consumed' region of 'b' by 'n' bytes.
232 REQUIRE(ISC_BUFFER_VALID(b
));
233 REQUIRE(n
<= b
->current
);
235 ISC__BUFFER_BACK(b
, n
);
239 isc_buffer_compact(isc_buffer_t
*b
) {
244 * Compact the used region by moving the remaining region so it occurs
245 * at the start of the buffer. The used region is shrunk by the size
246 * of the consumed region, and the consumed region is then made empty.
249 REQUIRE(ISC_BUFFER_VALID(b
));
251 src
= isc_buffer_current(b
);
252 length
= isc_buffer_remaininglength(b
);
253 (void)memmove(b
->base
, src
, (size_t)length
);
255 if (b
->active
> b
->current
)
256 b
->active
-= b
->current
;
264 isc_buffer_getuint8(isc_buffer_t
*b
) {
269 * Read an unsigned 8-bit integer from 'b' and return it.
272 REQUIRE(ISC_BUFFER_VALID(b
));
273 REQUIRE(b
->used
- b
->current
>= 1);
275 cp
= isc_buffer_current(b
);
277 result
= ((isc_uint8_t
)(cp
[0]));
283 isc__buffer_putuint8(isc_buffer_t
*b
, isc_uint8_t val
) {
284 REQUIRE(ISC_BUFFER_VALID(b
));
285 REQUIRE(b
->used
+ 1 <= b
->length
);
287 ISC__BUFFER_PUTUINT8(b
, val
);
291 isc_buffer_getuint16(isc_buffer_t
*b
) {
296 * Read an unsigned 16-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
>= 2);
303 cp
= isc_buffer_current(b
);
305 result
= ((unsigned int)(cp
[0])) << 8;
306 result
|= ((unsigned int)(cp
[1]));
312 isc__buffer_putuint16(isc_buffer_t
*b
, isc_uint16_t val
) {
313 REQUIRE(ISC_BUFFER_VALID(b
));
314 REQUIRE(b
->used
+ 2 <= b
->length
);
316 ISC__BUFFER_PUTUINT16(b
, val
);
320 isc_buffer_getuint32(isc_buffer_t
*b
) {
325 * Read an unsigned 32-bit integer in network byte order from 'b',
326 * convert it to host byte order, and return it.
329 REQUIRE(ISC_BUFFER_VALID(b
));
330 REQUIRE(b
->used
- b
->current
>= 4);
332 cp
= isc_buffer_current(b
);
334 result
= ((unsigned int)(cp
[0])) << 24;
335 result
|= ((unsigned int)(cp
[1])) << 16;
336 result
|= ((unsigned int)(cp
[2])) << 8;
337 result
|= ((unsigned int)(cp
[3]));
343 isc__buffer_putuint32(isc_buffer_t
*b
, isc_uint32_t val
) {
344 REQUIRE(ISC_BUFFER_VALID(b
));
345 REQUIRE(b
->used
+ 4 <= b
->length
);
347 ISC__BUFFER_PUTUINT32(b
, val
);
351 isc_buffer_getuint48(isc_buffer_t
*b
) {
356 * Read an unsigned 48-bit integer in network byte order from 'b',
357 * convert it to host byte order, and return it.
360 REQUIRE(ISC_BUFFER_VALID(b
));
361 REQUIRE(b
->used
- b
->current
>= 6);
363 cp
= isc_buffer_current(b
);
365 result
= ((isc_int64_t
)(cp
[0])) << 40;
366 result
|= ((isc_int64_t
)(cp
[1])) << 32;
367 result
|= ((isc_int64_t
)(cp
[2])) << 24;
368 result
|= ((isc_int64_t
)(cp
[3])) << 16;
369 result
|= ((isc_int64_t
)(cp
[4])) << 8;
370 result
|= ((isc_int64_t
)(cp
[5]));
376 isc__buffer_putuint48(isc_buffer_t
*b
, isc_uint64_t val
) {
380 REQUIRE(ISC_BUFFER_VALID(b
));
381 REQUIRE(b
->used
+ 6 <= b
->length
);
383 valhi
= (isc_uint16_t
)(val
>> 32);
384 vallo
= (isc_uint32_t
)(val
& 0xFFFFFFFF);
385 ISC__BUFFER_PUTUINT16(b
, valhi
);
386 ISC__BUFFER_PUTUINT32(b
, vallo
);
390 isc__buffer_putmem(isc_buffer_t
*b
, const unsigned char *base
,
393 REQUIRE(ISC_BUFFER_VALID(b
));
394 REQUIRE(b
->used
+ length
<= b
->length
);
396 ISC__BUFFER_PUTMEM(b
, base
, length
);
400 isc__buffer_putstr(isc_buffer_t
*b
, const char *source
) {
404 REQUIRE(ISC_BUFFER_VALID(b
));
405 REQUIRE(source
!= NULL
);
408 * Do not use ISC__BUFFER_PUTSTR(), so strlen is only done once.
412 REQUIRE(l
<= isc_buffer_availablelength(b
));
414 cp
= isc_buffer_used(b
);
415 memcpy(cp
, source
, l
);
420 isc_buffer_copyregion(isc_buffer_t
*b
, const isc_region_t
*r
) {
422 unsigned int available
;
424 REQUIRE(ISC_BUFFER_VALID(b
));
430 base
= isc_buffer_used(b
);
431 available
= isc_buffer_availablelength(b
);
432 if (r
->length
> available
)
433 return (ISC_R_NOSPACE
);
434 memcpy(base
, r
->base
, r
->length
);
435 b
->used
+= r
->length
;
437 return (ISC_R_SUCCESS
);
441 isc_buffer_allocate(isc_mem_t
*mctx
, isc_buffer_t
**dynbuffer
,
446 REQUIRE(dynbuffer
!= NULL
);
447 REQUIRE(*dynbuffer
== NULL
);
449 dbuf
= isc_mem_get(mctx
, length
+ sizeof(isc_buffer_t
));
451 return (ISC_R_NOMEMORY
);
453 isc_buffer_init(dbuf
, ((unsigned char *)dbuf
) + sizeof(isc_buffer_t
),
459 return (ISC_R_SUCCESS
);
463 isc_buffer_free(isc_buffer_t
**dynbuffer
) {
464 unsigned int real_length
;
468 REQUIRE(dynbuffer
!= NULL
);
469 REQUIRE(ISC_BUFFER_VALID(*dynbuffer
));
470 REQUIRE((*dynbuffer
)->mctx
!= NULL
);
473 *dynbuffer
= NULL
; /* destroy external reference */
475 real_length
= dbuf
->length
+ sizeof(isc_buffer_t
);
478 isc_buffer_invalidate(dbuf
);
480 isc_mem_put(mctx
, dbuf
, real_length
);