Add BIND 9.2.4rc7.
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / isc / buffer.c
blob929c41c6cd49fc6f360d90eb8e5d5faeb017eb69
1 /*
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 $ */
20 #include <config.h>
22 #include <isc/buffer.h>
23 #include <isc/mem.h>
24 #include <isc/region.h>
25 #include <isc/string.h>
26 #include <isc/util.h>
28 void
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.
35 REQUIRE(b != NULL);
37 ISC__BUFFER_INIT(b, base, length);
40 void
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);
53 void
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));
60 REQUIRE(r != NULL);
62 ISC__BUFFER_REGION(b, r);
65 void
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));
72 REQUIRE(r != NULL);
74 ISC__BUFFER_USEDREGION(b, r);
77 void
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));
84 REQUIRE(r != NULL);
86 ISC__BUFFER_AVAILABLEREGION(b, r);
89 void
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);
101 void
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);
113 void
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);
124 void
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));
131 REQUIRE(r != NULL);
133 ISC__BUFFER_CONSUMEDREGION(b, r);
136 void
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));
143 REQUIRE(r != NULL);
145 ISC__BUFFER_REMAININGREGION(b, r);
148 void
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));
155 REQUIRE(r != NULL);
157 ISC__BUFFER_ACTIVEREGION(b, r);
160 void
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);
172 void
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);
183 void
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);
195 void
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);
207 void
208 isc_buffer_compact(isc_buffer_t *b) {
209 unsigned int length;
210 void *src;
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;
226 else
227 b->active = 0;
228 b->current = 0;
229 b->used = length;
232 isc_uint8_t
233 isc_buffer_getuint8(isc_buffer_t *b) {
234 unsigned char *cp;
235 isc_uint8_t result;
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);
245 b->current += 1;
246 result = ((isc_uint8_t)(cp[0]));
248 return (result);
251 void
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);
259 isc_uint16_t
260 isc_buffer_getuint16(isc_buffer_t *b) {
261 unsigned char *cp;
262 isc_uint16_t result;
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);
273 b->current += 2;
274 result = ((unsigned int)(cp[0])) << 8;
275 result |= ((unsigned int)(cp[1]));
277 return (result);
280 void
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);
288 isc_uint32_t
289 isc_buffer_getuint32(isc_buffer_t *b) {
290 unsigned char *cp;
291 isc_uint32_t result;
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);
302 b->current += 4;
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]));
308 return (result);
311 void
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);
319 void
320 isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base,
321 unsigned int length)
323 REQUIRE(ISC_BUFFER_VALID(b));
324 REQUIRE(b->used + length <= b->length);
326 ISC__BUFFER_PUTMEM(b, base, length);
329 void
330 isc__buffer_putstr(isc_buffer_t *b, const char *source) {
331 unsigned int l;
332 unsigned char *cp;
334 REQUIRE(ISC_BUFFER_VALID(b));
335 REQUIRE(source != NULL);
338 * Do not use ISC__BUFFER_PUTSTR(), so strlen is only done once.
340 l = strlen(source);
342 REQUIRE(l <= isc_buffer_availablelength(b));
344 cp = isc_buffer_used(b);
345 memcpy(cp, source, l);
346 b->used += l;
349 isc_result_t
350 isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r) {
351 unsigned char *base;
352 unsigned int available;
354 REQUIRE(ISC_BUFFER_VALID(b));
355 REQUIRE(r != NULL);
358 * XXXDCL
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);
370 isc_result_t
371 isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
372 unsigned int length)
374 isc_buffer_t *dbuf;
376 REQUIRE(dynbuffer != NULL);
377 REQUIRE(*dynbuffer == NULL);
379 dbuf = isc_mem_get(mctx, length + sizeof(isc_buffer_t));
380 if (dbuf == NULL)
381 return (ISC_R_NOMEMORY);
383 isc_buffer_init(dbuf, ((unsigned char *)dbuf) + sizeof(isc_buffer_t),
384 length);
385 dbuf->mctx = mctx;
387 *dynbuffer = dbuf;
389 return (ISC_R_SUCCESS);
392 void
393 isc_buffer_free(isc_buffer_t **dynbuffer) {
394 unsigned int real_length;
395 isc_buffer_t *dbuf;
396 isc_mem_t *mctx;
398 REQUIRE(dynbuffer != NULL);
399 REQUIRE(ISC_BUFFER_VALID(*dynbuffer));
400 REQUIRE((*dynbuffer)->mctx != NULL);
402 dbuf = *dynbuffer;
403 *dynbuffer = NULL; /* destroy external reference */
405 real_length = dbuf->length + sizeof(isc_buffer_t);
406 mctx = dbuf->mctx;
407 dbuf->mctx = NULL;
408 isc_buffer_invalidate(dbuf);
410 isc_mem_put(mctx, dbuf, real_length);