2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1998-2001 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.36.2.1 2004/03/09 06:11:45 marka Exp $ */
22 #include <isc/buffer.h>
24 #include <isc/region.h>
25 #include <isc/string.h>
29 isc__buffer_init(isc_buffer_t
*b
, const void *base
, unsigned int length
) {
31 * Make 'b' refer to the 'length'-byte region starting at 'base'.
32 * XXXDCL see the comment in buffer.h about base being const.
37 ISC__BUFFER_INIT(b
, base
, length
);
41 isc__buffer_invalidate(isc_buffer_t
*b
) {
43 * Make 'b' an invalid buffer.
46 REQUIRE(ISC_BUFFER_VALID(b
));
47 REQUIRE(!ISC_LINK_LINKED(b
, link
));
48 REQUIRE(b
->mctx
== NULL
);
50 ISC__BUFFER_INVALIDATE(b
);
54 isc__buffer_region(isc_buffer_t
*b
, isc_region_t
*r
) {
56 * Make 'r' refer to the region of 'b'.
59 REQUIRE(ISC_BUFFER_VALID(b
));
62 ISC__BUFFER_REGION(b
, r
);
66 isc__buffer_usedregion(isc_buffer_t
*b
, isc_region_t
*r
) {
68 * Make 'r' refer to the used region of 'b'.
71 REQUIRE(ISC_BUFFER_VALID(b
));
74 ISC__BUFFER_USEDREGION(b
, r
);
78 isc__buffer_availableregion(isc_buffer_t
*b
, isc_region_t
*r
) {
80 * Make 'r' refer to the available region of 'b'.
83 REQUIRE(ISC_BUFFER_VALID(b
));
86 ISC__BUFFER_AVAILABLEREGION(b
, r
);
90 isc__buffer_add(isc_buffer_t
*b
, unsigned int n
) {
92 * Increase the 'used' region of 'b' by 'n' bytes.
95 REQUIRE(ISC_BUFFER_VALID(b
));
96 REQUIRE(b
->used
+ n
<= b
->length
);
98 ISC__BUFFER_ADD(b
, n
);
102 isc__buffer_subtract(isc_buffer_t
*b
, unsigned int n
) {
104 * Decrease the 'used' region of 'b' by 'n' bytes.
107 REQUIRE(ISC_BUFFER_VALID(b
));
108 REQUIRE(b
->used
>= n
);
110 ISC__BUFFER_SUBTRACT(b
, n
);
114 isc__buffer_clear(isc_buffer_t
*b
) {
116 * Make the used region empty.
119 REQUIRE(ISC_BUFFER_VALID(b
));
121 ISC__BUFFER_CLEAR(b
);
125 isc__buffer_consumedregion(isc_buffer_t
*b
, isc_region_t
*r
) {
127 * Make 'r' refer to the consumed region of 'b'.
130 REQUIRE(ISC_BUFFER_VALID(b
));
133 ISC__BUFFER_CONSUMEDREGION(b
, r
);
137 isc__buffer_remainingregion(isc_buffer_t
*b
, isc_region_t
*r
) {
139 * Make 'r' refer to the remaining region of 'b'.
142 REQUIRE(ISC_BUFFER_VALID(b
));
145 ISC__BUFFER_REMAININGREGION(b
, r
);
149 isc__buffer_activeregion(isc_buffer_t
*b
, isc_region_t
*r
) {
151 * Make 'r' refer to the active region of 'b'.
154 REQUIRE(ISC_BUFFER_VALID(b
));
157 ISC__BUFFER_ACTIVEREGION(b
, r
);
161 isc__buffer_setactive(isc_buffer_t
*b
, unsigned int n
) {
163 * Sets the end of the active region 'n' bytes after current.
166 REQUIRE(ISC_BUFFER_VALID(b
));
167 REQUIRE(b
->current
+ n
<= b
->used
);
169 ISC__BUFFER_SETACTIVE(b
, n
);
173 isc__buffer_first(isc_buffer_t
*b
) {
175 * Make the consumed region empty.
178 REQUIRE(ISC_BUFFER_VALID(b
));
180 ISC__BUFFER_FIRST(b
);
184 isc__buffer_forward(isc_buffer_t
*b
, unsigned int n
) {
186 * Increase the 'consumed' region of 'b' by 'n' bytes.
189 REQUIRE(ISC_BUFFER_VALID(b
));
190 REQUIRE(b
->current
+ n
<= b
->used
);
192 ISC__BUFFER_FORWARD(b
, n
);
196 isc__buffer_back(isc_buffer_t
*b
, unsigned int n
) {
198 * Decrease the 'consumed' region of 'b' by 'n' bytes.
201 REQUIRE(ISC_BUFFER_VALID(b
));
202 REQUIRE(n
<= b
->current
);
204 ISC__BUFFER_BACK(b
, n
);
208 isc_buffer_compact(isc_buffer_t
*b
) {
213 * Compact the used region by moving the remaining region so it occurs
214 * at the start of the buffer. The used region is shrunk by the size
215 * of the consumed region, and the consumed region is then made empty.
218 REQUIRE(ISC_BUFFER_VALID(b
));
220 src
= isc_buffer_current(b
);
221 length
= isc_buffer_remaininglength(b
);
222 (void)memmove(b
->base
, src
, (size_t)length
);
224 if (b
->active
> b
->current
)
225 b
->active
-= b
->current
;
233 isc_buffer_getuint8(isc_buffer_t
*b
) {
238 * Read an unsigned 8-bit integer from 'b' and return it.
241 REQUIRE(ISC_BUFFER_VALID(b
));
242 REQUIRE(b
->used
- b
->current
>= 1);
244 cp
= isc_buffer_current(b
);
246 result
= ((isc_uint8_t
)(cp
[0]));
252 isc__buffer_putuint8(isc_buffer_t
*b
, isc_uint8_t val
) {
253 REQUIRE(ISC_BUFFER_VALID(b
));
254 REQUIRE(b
->used
+ 1 <= b
->length
);
256 ISC__BUFFER_PUTUINT8(b
, val
);
260 isc_buffer_getuint16(isc_buffer_t
*b
) {
265 * Read an unsigned 16-bit integer in network byte order from 'b',
266 * convert it to host byte order, and return it.
269 REQUIRE(ISC_BUFFER_VALID(b
));
270 REQUIRE(b
->used
- b
->current
>= 2);
272 cp
= isc_buffer_current(b
);
274 result
= ((unsigned int)(cp
[0])) << 8;
275 result
|= ((unsigned int)(cp
[1]));
281 isc__buffer_putuint16(isc_buffer_t
*b
, isc_uint16_t val
) {
282 REQUIRE(ISC_BUFFER_VALID(b
));
283 REQUIRE(b
->used
+ 2 <= b
->length
);
285 ISC__BUFFER_PUTUINT16(b
, val
);
289 isc_buffer_getuint32(isc_buffer_t
*b
) {
294 * Read an unsigned 32-bit integer in network byte order from 'b',
295 * convert it to host byte order, and return it.
298 REQUIRE(ISC_BUFFER_VALID(b
));
299 REQUIRE(b
->used
- b
->current
>= 4);
301 cp
= isc_buffer_current(b
);
303 result
= ((unsigned int)(cp
[0])) << 24;
304 result
|= ((unsigned int)(cp
[1])) << 16;
305 result
|= ((unsigned int)(cp
[2])) << 8;
306 result
|= ((unsigned int)(cp
[3]));
312 isc__buffer_putuint32(isc_buffer_t
*b
, isc_uint32_t val
) {
313 REQUIRE(ISC_BUFFER_VALID(b
));
314 REQUIRE(b
->used
+ 4 <= b
->length
);
316 ISC__BUFFER_PUTUINT32(b
, val
);
320 isc__buffer_putmem(isc_buffer_t
*b
, const unsigned char *base
,
323 REQUIRE(ISC_BUFFER_VALID(b
));
324 REQUIRE(b
->used
+ length
<= b
->length
);
326 ISC__BUFFER_PUTMEM(b
, base
, length
);
330 isc__buffer_putstr(isc_buffer_t
*b
, const char *source
) {
334 REQUIRE(ISC_BUFFER_VALID(b
));
335 REQUIRE(source
!= NULL
);
338 * Do not use ISC__BUFFER_PUTSTR(), so strlen is only done once.
342 REQUIRE(l
<= isc_buffer_availablelength(b
));
344 cp
= isc_buffer_used(b
);
345 memcpy(cp
, source
, l
);
350 isc_buffer_copyregion(isc_buffer_t
*b
, const isc_region_t
*r
) {
352 unsigned int available
;
354 REQUIRE(ISC_BUFFER_VALID(b
));
360 base
= isc_buffer_used(b
);
361 available
= isc_buffer_availablelength(b
);
362 if (r
->length
> available
)
363 return (ISC_R_NOSPACE
);
364 memcpy(base
, r
->base
, r
->length
);
365 b
->used
+= r
->length
;
367 return (ISC_R_SUCCESS
);
371 isc_buffer_allocate(isc_mem_t
*mctx
, isc_buffer_t
**dynbuffer
,
376 REQUIRE(dynbuffer
!= NULL
);
377 REQUIRE(*dynbuffer
== NULL
);
379 dbuf
= isc_mem_get(mctx
, length
+ sizeof(isc_buffer_t
));
381 return (ISC_R_NOMEMORY
);
383 isc_buffer_init(dbuf
, ((unsigned char *)dbuf
) + sizeof(isc_buffer_t
),
389 return (ISC_R_SUCCESS
);
393 isc_buffer_free(isc_buffer_t
**dynbuffer
) {
394 unsigned int real_length
;
398 REQUIRE(dynbuffer
!= NULL
);
399 REQUIRE(ISC_BUFFER_VALID(*dynbuffer
));
400 REQUIRE((*dynbuffer
)->mctx
!= NULL
);
403 *dynbuffer
= NULL
; /* destroy external reference */
405 real_length
= dbuf
->length
+ sizeof(isc_buffer_t
);
408 isc_buffer_invalidate(dbuf
);
410 isc_mem_put(mctx
, dbuf
, real_length
);