Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / bsd / ntp / dist / lib / isc / buffer.c
blob996812fff74e4c9b7b19bac5d806f78f0251a825
1 /* $NetBSD$ */
3 /*
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 */
22 /*! \file */
24 #include <config.h>
26 #include <isc/buffer.h>
27 #include <isc/mem.h>
28 #include <isc/region.h>
29 #include <isc/string.h>
30 #include <isc/util.h>
32 void
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.
39 REQUIRE(b != NULL);
41 ISC__BUFFER_INIT(b, base, length);
44 void
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);
54 void
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
60 * internal pointers.
62 * The buffer must not be smaller than the length of the original
63 * buffer.
65 REQUIRE(b->length <= length);
66 REQUIRE(base != NULL);
68 (void)memmove(base, b->base, b->length);
69 b->base = base;
70 b->length = length;
73 void
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);
86 void
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));
93 REQUIRE(r != NULL);
95 ISC__BUFFER_REGION(b, r);
98 void
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));
105 REQUIRE(r != NULL);
107 ISC__BUFFER_USEDREGION(b, r);
110 void
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));
117 REQUIRE(r != NULL);
119 ISC__BUFFER_AVAILABLEREGION(b, r);
122 void
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);
134 void
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);
146 void
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);
157 void
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));
164 REQUIRE(r != NULL);
166 ISC__BUFFER_CONSUMEDREGION(b, r);
169 void
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));
176 REQUIRE(r != NULL);
178 ISC__BUFFER_REMAININGREGION(b, r);
181 void
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));
188 REQUIRE(r != NULL);
190 ISC__BUFFER_ACTIVEREGION(b, r);
193 void
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);
205 void
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);
216 void
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);
228 void
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);
240 void
241 isc_buffer_compact(isc_buffer_t *b) {
242 unsigned int length;
243 void *src;
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;
259 else
260 b->active = 0;
261 b->current = 0;
262 b->used = length;
265 isc_uint8_t
266 isc_buffer_getuint8(isc_buffer_t *b) {
267 unsigned char *cp;
268 isc_uint8_t result;
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);
278 b->current += 1;
279 result = ((isc_uint8_t)(cp[0]));
281 return (result);
284 void
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);
292 isc_uint16_t
293 isc_buffer_getuint16(isc_buffer_t *b) {
294 unsigned char *cp;
295 isc_uint16_t result;
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);
306 b->current += 2;
307 result = ((unsigned int)(cp[0])) << 8;
308 result |= ((unsigned int)(cp[1]));
310 return (result);
313 void
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);
321 void
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);
329 isc_uint32_t
330 isc_buffer_getuint32(isc_buffer_t *b) {
331 unsigned char *cp;
332 isc_uint32_t result;
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);
343 b->current += 4;
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]));
349 return (result);
352 void
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);
360 isc_uint64_t
361 isc_buffer_getuint48(isc_buffer_t *b) {
362 unsigned char *cp;
363 isc_uint64_t result;
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);
374 b->current += 6;
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]));
382 return (result);
385 void
386 isc__buffer_putuint48(isc_buffer_t *b, isc_uint64_t val) {
387 isc_uint16_t valhi;
388 isc_uint32_t vallo;
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);
399 void
400 isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base,
401 unsigned int length)
403 REQUIRE(ISC_BUFFER_VALID(b));
404 REQUIRE(b->used + length <= b->length);
406 ISC__BUFFER_PUTMEM(b, base, length);
409 void
410 isc__buffer_putstr(isc_buffer_t *b, const char *source) {
411 unsigned int l;
412 unsigned char *cp;
414 REQUIRE(ISC_BUFFER_VALID(b));
415 REQUIRE(source != NULL);
418 * Do not use ISC__BUFFER_PUTSTR(), so strlen is only done once.
420 l = strlen(source);
422 REQUIRE(l <= isc_buffer_availablelength(b));
424 cp = isc_buffer_used(b);
425 memcpy(cp, source, l);
426 b->used += l;
429 isc_result_t
430 isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r) {
431 unsigned char *base;
432 unsigned int available;
434 REQUIRE(ISC_BUFFER_VALID(b));
435 REQUIRE(r != NULL);
438 * XXXDCL
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);
450 isc_result_t
451 isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
452 unsigned int length)
454 isc_buffer_t *dbuf;
456 REQUIRE(dynbuffer != NULL);
457 REQUIRE(*dynbuffer == NULL);
459 dbuf = isc_mem_get(mctx, length + sizeof(isc_buffer_t));
460 if (dbuf == NULL)
461 return (ISC_R_NOMEMORY);
463 isc_buffer_init(dbuf, ((unsigned char *)dbuf) + sizeof(isc_buffer_t),
464 length);
465 dbuf->mctx = mctx;
467 *dynbuffer = dbuf;
469 return (ISC_R_SUCCESS);
472 void
473 isc_buffer_free(isc_buffer_t **dynbuffer) {
474 unsigned int real_length;
475 isc_buffer_t *dbuf;
476 isc_mem_t *mctx;
478 REQUIRE(dynbuffer != NULL);
479 REQUIRE(ISC_BUFFER_VALID(*dynbuffer));
480 REQUIRE((*dynbuffer)->mctx != NULL);
482 dbuf = *dynbuffer;
483 *dynbuffer = NULL; /* destroy external reference */
485 real_length = dbuf->length + sizeof(isc_buffer_t);
486 mctx = dbuf->mctx;
487 dbuf->mctx = NULL;
488 isc_buffer_invalidate(dbuf);
490 isc_mem_put(mctx, dbuf, real_length);