4 * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1998-2002 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: buffer.c,v 1.49 2008/09/25 04:02:39 tbox Exp */
26 #include <isc/buffer.h>
28 #include <isc/region.h>
29 #include <isc/string.h>
33 isc__buffer_init(isc_buffer_t
*b
, const void *base
, unsigned int length
) {
35 * Make 'b' refer to the 'length'-byte region starting at 'base'.
36 * XXXDCL see the comment in buffer.h about base being const.
41 ISC__BUFFER_INIT(b
, base
, length
);
45 isc__buffer_initnull(isc_buffer_t
*b
) {
47 * Initialize a new buffer which has no backing store. This can
48 * later be grown as needed and swapped in place.
51 ISC__BUFFER_INIT(b
, NULL
, 0);
55 isc_buffer_reinit(isc_buffer_t
*b
, void *base
, unsigned int length
) {
57 * Re-initialize the buffer enough to reconfigure the base of the
58 * buffer. We will swap in the new buffer, after copying any
59 * data we contain into the new buffer and adjusting all of our
62 * The buffer must not be smaller than the length of the original
65 REQUIRE(b
->length
<= length
);
66 REQUIRE(base
!= NULL
);
68 (void)memmove(base
, b
->base
, b
->length
);
74 isc__buffer_invalidate(isc_buffer_t
*b
) {
76 * Make 'b' an invalid buffer.
79 REQUIRE(ISC_BUFFER_VALID(b
));
80 REQUIRE(!ISC_LINK_LINKED(b
, link
));
81 REQUIRE(b
->mctx
== NULL
);
83 ISC__BUFFER_INVALIDATE(b
);
87 isc__buffer_region(isc_buffer_t
*b
, isc_region_t
*r
) {
89 * Make 'r' refer to the region of 'b'.
92 REQUIRE(ISC_BUFFER_VALID(b
));
95 ISC__BUFFER_REGION(b
, r
);
99 isc__buffer_usedregion(isc_buffer_t
*b
, isc_region_t
*r
) {
101 * Make 'r' refer to the used region of 'b'.
104 REQUIRE(ISC_BUFFER_VALID(b
));
107 ISC__BUFFER_USEDREGION(b
, r
);
111 isc__buffer_availableregion(isc_buffer_t
*b
, isc_region_t
*r
) {
113 * Make 'r' refer to the available region of 'b'.
116 REQUIRE(ISC_BUFFER_VALID(b
));
119 ISC__BUFFER_AVAILABLEREGION(b
, r
);
123 isc__buffer_add(isc_buffer_t
*b
, unsigned int n
) {
125 * Increase the 'used' region of 'b' by 'n' bytes.
128 REQUIRE(ISC_BUFFER_VALID(b
));
129 REQUIRE(b
->used
+ n
<= b
->length
);
131 ISC__BUFFER_ADD(b
, n
);
135 isc__buffer_subtract(isc_buffer_t
*b
, unsigned int n
) {
137 * Decrease the 'used' region of 'b' by 'n' bytes.
140 REQUIRE(ISC_BUFFER_VALID(b
));
141 REQUIRE(b
->used
>= n
);
143 ISC__BUFFER_SUBTRACT(b
, n
);
147 isc__buffer_clear(isc_buffer_t
*b
) {
149 * Make the used region empty.
152 REQUIRE(ISC_BUFFER_VALID(b
));
154 ISC__BUFFER_CLEAR(b
);
158 isc__buffer_consumedregion(isc_buffer_t
*b
, isc_region_t
*r
) {
160 * Make 'r' refer to the consumed region of 'b'.
163 REQUIRE(ISC_BUFFER_VALID(b
));
166 ISC__BUFFER_CONSUMEDREGION(b
, r
);
170 isc__buffer_remainingregion(isc_buffer_t
*b
, isc_region_t
*r
) {
172 * Make 'r' refer to the remaining region of 'b'.
175 REQUIRE(ISC_BUFFER_VALID(b
));
178 ISC__BUFFER_REMAININGREGION(b
, r
);
182 isc__buffer_activeregion(isc_buffer_t
*b
, isc_region_t
*r
) {
184 * Make 'r' refer to the active region of 'b'.
187 REQUIRE(ISC_BUFFER_VALID(b
));
190 ISC__BUFFER_ACTIVEREGION(b
, r
);
194 isc__buffer_setactive(isc_buffer_t
*b
, unsigned int n
) {
196 * Sets the end of the active region 'n' bytes after current.
199 REQUIRE(ISC_BUFFER_VALID(b
));
200 REQUIRE(b
->current
+ n
<= b
->used
);
202 ISC__BUFFER_SETACTIVE(b
, n
);
206 isc__buffer_first(isc_buffer_t
*b
) {
208 * Make the consumed region empty.
211 REQUIRE(ISC_BUFFER_VALID(b
));
213 ISC__BUFFER_FIRST(b
);
217 isc__buffer_forward(isc_buffer_t
*b
, unsigned int n
) {
219 * Increase the 'consumed' region of 'b' by 'n' bytes.
222 REQUIRE(ISC_BUFFER_VALID(b
));
223 REQUIRE(b
->current
+ n
<= b
->used
);
225 ISC__BUFFER_FORWARD(b
, n
);
229 isc__buffer_back(isc_buffer_t
*b
, unsigned int n
) {
231 * Decrease the 'consumed' region of 'b' by 'n' bytes.
234 REQUIRE(ISC_BUFFER_VALID(b
));
235 REQUIRE(n
<= b
->current
);
237 ISC__BUFFER_BACK(b
, n
);
241 isc_buffer_compact(isc_buffer_t
*b
) {
246 * Compact the used region by moving the remaining region so it occurs
247 * at the start of the buffer. The used region is shrunk by the size
248 * of the consumed region, and the consumed region is then made empty.
251 REQUIRE(ISC_BUFFER_VALID(b
));
253 src
= isc_buffer_current(b
);
254 length
= isc_buffer_remaininglength(b
);
255 (void)memmove(b
->base
, src
, (size_t)length
);
257 if (b
->active
> b
->current
)
258 b
->active
-= b
->current
;
266 isc_buffer_getuint8(isc_buffer_t
*b
) {
271 * Read an unsigned 8-bit integer from 'b' and return it.
274 REQUIRE(ISC_BUFFER_VALID(b
));
275 REQUIRE(b
->used
- b
->current
>= 1);
277 cp
= isc_buffer_current(b
);
279 result
= ((isc_uint8_t
)(cp
[0]));
285 isc__buffer_putuint8(isc_buffer_t
*b
, isc_uint8_t val
) {
286 REQUIRE(ISC_BUFFER_VALID(b
));
287 REQUIRE(b
->used
+ 1 <= b
->length
);
289 ISC__BUFFER_PUTUINT8(b
, val
);
293 isc_buffer_getuint16(isc_buffer_t
*b
) {
298 * Read an unsigned 16-bit integer in network byte order from 'b',
299 * convert it to host byte order, and return it.
302 REQUIRE(ISC_BUFFER_VALID(b
));
303 REQUIRE(b
->used
- b
->current
>= 2);
305 cp
= isc_buffer_current(b
);
307 result
= ((unsigned int)(cp
[0])) << 8;
308 result
|= ((unsigned int)(cp
[1]));
314 isc__buffer_putuint16(isc_buffer_t
*b
, isc_uint16_t val
) {
315 REQUIRE(ISC_BUFFER_VALID(b
));
316 REQUIRE(b
->used
+ 2 <= b
->length
);
318 ISC__BUFFER_PUTUINT16(b
, val
);
322 isc__buffer_putuint24(isc_buffer_t
*b
, isc_uint32_t val
) {
323 REQUIRE(ISC_BUFFER_VALID(b
));
324 REQUIRE(b
->used
+ 3 <= b
->length
);
326 ISC__BUFFER_PUTUINT24(b
, val
);
330 isc_buffer_getuint32(isc_buffer_t
*b
) {
335 * Read an unsigned 32-bit integer in network byte order from 'b',
336 * convert it to host byte order, and return it.
339 REQUIRE(ISC_BUFFER_VALID(b
));
340 REQUIRE(b
->used
- b
->current
>= 4);
342 cp
= isc_buffer_current(b
);
344 result
= ((unsigned int)(cp
[0])) << 24;
345 result
|= ((unsigned int)(cp
[1])) << 16;
346 result
|= ((unsigned int)(cp
[2])) << 8;
347 result
|= ((unsigned int)(cp
[3]));
353 isc__buffer_putuint32(isc_buffer_t
*b
, isc_uint32_t val
) {
354 REQUIRE(ISC_BUFFER_VALID(b
));
355 REQUIRE(b
->used
+ 4 <= b
->length
);
357 ISC__BUFFER_PUTUINT32(b
, val
);
361 isc_buffer_getuint48(isc_buffer_t
*b
) {
366 * Read an unsigned 48-bit integer in network byte order from 'b',
367 * convert it to host byte order, and return it.
370 REQUIRE(ISC_BUFFER_VALID(b
));
371 REQUIRE(b
->used
- b
->current
>= 6);
373 cp
= isc_buffer_current(b
);
375 result
= ((isc_int64_t
)(cp
[0])) << 40;
376 result
|= ((isc_int64_t
)(cp
[1])) << 32;
377 result
|= ((isc_int64_t
)(cp
[2])) << 24;
378 result
|= ((isc_int64_t
)(cp
[3])) << 16;
379 result
|= ((isc_int64_t
)(cp
[4])) << 8;
380 result
|= ((isc_int64_t
)(cp
[5]));
386 isc__buffer_putuint48(isc_buffer_t
*b
, isc_uint64_t val
) {
390 REQUIRE(ISC_BUFFER_VALID(b
));
391 REQUIRE(b
->used
+ 6 <= b
->length
);
393 valhi
= (isc_uint16_t
)(val
>> 32);
394 vallo
= (isc_uint32_t
)(val
& 0xFFFFFFFF);
395 ISC__BUFFER_PUTUINT16(b
, valhi
);
396 ISC__BUFFER_PUTUINT32(b
, vallo
);
400 isc__buffer_putmem(isc_buffer_t
*b
, const unsigned char *base
,
403 REQUIRE(ISC_BUFFER_VALID(b
));
404 REQUIRE(b
->used
+ length
<= b
->length
);
406 ISC__BUFFER_PUTMEM(b
, base
, length
);
410 isc__buffer_putstr(isc_buffer_t
*b
, const char *source
) {
414 REQUIRE(ISC_BUFFER_VALID(b
));
415 REQUIRE(source
!= NULL
);
418 * Do not use ISC__BUFFER_PUTSTR(), so strlen is only done once.
422 REQUIRE(l
<= isc_buffer_availablelength(b
));
424 cp
= isc_buffer_used(b
);
425 memcpy(cp
, source
, l
);
430 isc_buffer_copyregion(isc_buffer_t
*b
, const isc_region_t
*r
) {
432 unsigned int available
;
434 REQUIRE(ISC_BUFFER_VALID(b
));
440 base
= isc_buffer_used(b
);
441 available
= isc_buffer_availablelength(b
);
442 if (r
->length
> available
)
443 return (ISC_R_NOSPACE
);
444 memcpy(base
, r
->base
, r
->length
);
445 b
->used
+= r
->length
;
447 return (ISC_R_SUCCESS
);
451 isc_buffer_allocate(isc_mem_t
*mctx
, isc_buffer_t
**dynbuffer
,
456 REQUIRE(dynbuffer
!= NULL
);
457 REQUIRE(*dynbuffer
== NULL
);
459 dbuf
= isc_mem_get(mctx
, length
+ sizeof(isc_buffer_t
));
461 return (ISC_R_NOMEMORY
);
463 isc_buffer_init(dbuf
, ((unsigned char *)dbuf
) + sizeof(isc_buffer_t
),
469 return (ISC_R_SUCCESS
);
473 isc_buffer_free(isc_buffer_t
**dynbuffer
) {
474 unsigned int real_length
;
478 REQUIRE(dynbuffer
!= NULL
);
479 REQUIRE(ISC_BUFFER_VALID(*dynbuffer
));
480 REQUIRE((*dynbuffer
)->mctx
!= NULL
);
483 *dynbuffer
= NULL
; /* destroy external reference */
485 real_length
= dbuf
->length
+ sizeof(isc_buffer_t
);
488 isc_buffer_invalidate(dbuf
);
490 isc_mem_put(mctx
, dbuf
, real_length
);