BIND: update vendor tree to 9.5.2-P2
[dragonfly.git] / contrib / bind / lib / isc / buffer.c
CommitLineData
bbbf71a3
JL
1/*
2 * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1998-2002 Internet Software Consortium.
4 *
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.
8 *
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.
16 */
17
18/* $Id: buffer.c,v 1.47 2007/06/19 23:47:17 tbox Exp $ */
19
20/*! \file */
21
22#include <config.h>
23
24#include <isc/buffer.h>
25#include <isc/mem.h>
26#include <isc/region.h>
27#include <isc/string.h>
28#include <isc/util.h>
29
30void
31isc__buffer_init(isc_buffer_t *b, const void *base, unsigned int length) {
32 /*
33 * Make 'b' refer to the 'length'-byte region starting at 'base'.
34 * XXXDCL see the comment in buffer.h about base being const.
35 */
36
37 REQUIRE(b != NULL);
38
39 ISC__BUFFER_INIT(b, base, length);
40}
41
42void
43isc__buffer_initnull(isc_buffer_t *b) {
44 /*
45 * Initialize a new buffer which has no backing store. This can
46 * later be grown as needed and swapped in place.
47 */
48
49 ISC__BUFFER_INIT(b, NULL, 0);
50}
51
52void
53isc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length) {
54 /*
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
58 * internal pointers.
59 *
60 * The buffer must not be smaller than the length of the original
61 * buffer.
62 */
63 REQUIRE(b->length <= length);
64 REQUIRE(base != NULL);
65
66 (void)memmove(base, b->base, b->length);
67 b->base = base;
68 b->length = length;
69}
70
71void
72isc__buffer_invalidate(isc_buffer_t *b) {
73 /*
74 * Make 'b' an invalid buffer.
75 */
76
77 REQUIRE(ISC_BUFFER_VALID(b));
78 REQUIRE(!ISC_LINK_LINKED(b, link));
79 REQUIRE(b->mctx == NULL);
80
81 ISC__BUFFER_INVALIDATE(b);
82}
83
84void
85isc__buffer_region(isc_buffer_t *b, isc_region_t *r) {
86 /*
87 * Make 'r' refer to the region of 'b'.
88 */
89
90 REQUIRE(ISC_BUFFER_VALID(b));
91 REQUIRE(r != NULL);
92
93 ISC__BUFFER_REGION(b, r);
94}
95
96void
97isc__buffer_usedregion(isc_buffer_t *b, isc_region_t *r) {
98 /*
99 * Make 'r' refer to the used region of 'b'.
100 */
101
102 REQUIRE(ISC_BUFFER_VALID(b));
103 REQUIRE(r != NULL);
104
105 ISC__BUFFER_USEDREGION(b, r);
106}
107
108void
109isc__buffer_availableregion(isc_buffer_t *b, isc_region_t *r) {
110 /*
111 * Make 'r' refer to the available region of 'b'.
112 */
113
114 REQUIRE(ISC_BUFFER_VALID(b));
115 REQUIRE(r != NULL);
116
117 ISC__BUFFER_AVAILABLEREGION(b, r);
118}
119
120void
121isc__buffer_add(isc_buffer_t *b, unsigned int n) {
122 /*
123 * Increase the 'used' region of 'b' by 'n' bytes.
124 */
125
126 REQUIRE(ISC_BUFFER_VALID(b));
127 REQUIRE(b->used + n <= b->length);
128
129 ISC__BUFFER_ADD(b, n);
130}
131
132void
133isc__buffer_subtract(isc_buffer_t *b, unsigned int n) {
134 /*
135 * Decrease the 'used' region of 'b' by 'n' bytes.
136 */
137
138 REQUIRE(ISC_BUFFER_VALID(b));
139 REQUIRE(b->used >= n);
140
141 ISC__BUFFER_SUBTRACT(b, n);
142}
143
144void
145isc__buffer_clear(isc_buffer_t *b) {
146 /*
147 * Make the used region empty.
148 */
149
150 REQUIRE(ISC_BUFFER_VALID(b));
151
152 ISC__BUFFER_CLEAR(b);
153}
154
155void
156isc__buffer_consumedregion(isc_buffer_t *b, isc_region_t *r) {
157 /*
158 * Make 'r' refer to the consumed region of 'b'.
159 */
160
161 REQUIRE(ISC_BUFFER_VALID(b));
162 REQUIRE(r != NULL);
163
164 ISC__BUFFER_CONSUMEDREGION(b, r);
165}
166
167void
168isc__buffer_remainingregion(isc_buffer_t *b, isc_region_t *r) {
169 /*
170 * Make 'r' refer to the remaining region of 'b'.
171 */
172
173 REQUIRE(ISC_BUFFER_VALID(b));
174 REQUIRE(r != NULL);
175
176 ISC__BUFFER_REMAININGREGION(b, r);
177}
178
179void
180isc__buffer_activeregion(isc_buffer_t *b, isc_region_t *r) {
181 /*
182 * Make 'r' refer to the active region of 'b'.
183 */
184
185 REQUIRE(ISC_BUFFER_VALID(b));
186 REQUIRE(r != NULL);
187
188 ISC__BUFFER_ACTIVEREGION(b, r);
189}
190
191void
192isc__buffer_setactive(isc_buffer_t *b, unsigned int n) {
193 /*
194 * Sets the end of the active region 'n' bytes after current.
195 */
196
197 REQUIRE(ISC_BUFFER_VALID(b));
198 REQUIRE(b->current + n <= b->used);
199
200 ISC__BUFFER_SETACTIVE(b, n);
201}
202
203void
204isc__buffer_first(isc_buffer_t *b) {
205 /*
206 * Make the consumed region empty.
207 */
208
209 REQUIRE(ISC_BUFFER_VALID(b));
210
211 ISC__BUFFER_FIRST(b);
212}
213
214void
215isc__buffer_forward(isc_buffer_t *b, unsigned int n) {
216 /*
217 * Increase the 'consumed' region of 'b' by 'n' bytes.
218 */
219
220 REQUIRE(ISC_BUFFER_VALID(b));
221 REQUIRE(b->current + n <= b->used);
222
223 ISC__BUFFER_FORWARD(b, n);
224}
225
226void
227isc__buffer_back(isc_buffer_t *b, unsigned int n) {
228 /*
229 * Decrease the 'consumed' region of 'b' by 'n' bytes.
230 */
231
232 REQUIRE(ISC_BUFFER_VALID(b));
233 REQUIRE(n <= b->current);
234
235 ISC__BUFFER_BACK(b, n);
236}
237
238void
239isc_buffer_compact(isc_buffer_t *b) {
240 unsigned int length;
241 void *src;
242
243 /*
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.
247 */
248
249 REQUIRE(ISC_BUFFER_VALID(b));
250
251 src = isc_buffer_current(b);
252 length = isc_buffer_remaininglength(b);
253 (void)memmove(b->base, src, (size_t)length);
254
255 if (b->active > b->current)
256 b->active -= b->current;
257 else
258 b->active = 0;
259 b->current = 0;
260 b->used = length;
261}
262
263isc_uint8_t
264isc_buffer_getuint8(isc_buffer_t *b) {
265 unsigned char *cp;
266 isc_uint8_t result;
267
268 /*
269 * Read an unsigned 8-bit integer from 'b' and return it.
270 */
271
272 REQUIRE(ISC_BUFFER_VALID(b));
273 REQUIRE(b->used - b->current >= 1);
274
275 cp = isc_buffer_current(b);
276 b->current += 1;
277 result = ((isc_uint8_t)(cp[0]));
278
279 return (result);
280}
281
282void
283isc__buffer_putuint8(isc_buffer_t *b, isc_uint8_t val) {
284 REQUIRE(ISC_BUFFER_VALID(b));
285 REQUIRE(b->used + 1 <= b->length);
286
287 ISC__BUFFER_PUTUINT8(b, val);
288}
289
290isc_uint16_t
291isc_buffer_getuint16(isc_buffer_t *b) {
292 unsigned char *cp;
293 isc_uint16_t result;
294
295 /*
296 * Read an unsigned 16-bit integer in network byte order from 'b',
297 * convert it to host byte order, and return it.
298 */
299
300 REQUIRE(ISC_BUFFER_VALID(b));
301 REQUIRE(b->used - b->current >= 2);
302
303 cp = isc_buffer_current(b);
304 b->current += 2;
305 result = ((unsigned int)(cp[0])) << 8;
306 result |= ((unsigned int)(cp[1]));
307
308 return (result);
309}
310
311void
312isc__buffer_putuint16(isc_buffer_t *b, isc_uint16_t val) {
313 REQUIRE(ISC_BUFFER_VALID(b));
314 REQUIRE(b->used + 2 <= b->length);
315
316 ISC__BUFFER_PUTUINT16(b, val);
317}
318
319isc_uint32_t
320isc_buffer_getuint32(isc_buffer_t *b) {
321 unsigned char *cp;
322 isc_uint32_t result;
323
324 /*
325 * Read an unsigned 32-bit integer in network byte order from 'b',
326 * convert it to host byte order, and return it.
327 */
328
329 REQUIRE(ISC_BUFFER_VALID(b));
330 REQUIRE(b->used - b->current >= 4);
331
332 cp = isc_buffer_current(b);
333 b->current += 4;
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]));
338
339 return (result);
340}
341
342void
343isc__buffer_putuint32(isc_buffer_t *b, isc_uint32_t val) {
344 REQUIRE(ISC_BUFFER_VALID(b));
345 REQUIRE(b->used + 4 <= b->length);
346
347 ISC__BUFFER_PUTUINT32(b, val);
348}
349
350isc_uint64_t
351isc_buffer_getuint48(isc_buffer_t *b) {
352 unsigned char *cp;
353 isc_uint64_t result;
354
355 /*
356 * Read an unsigned 48-bit integer in network byte order from 'b',
357 * convert it to host byte order, and return it.
358 */
359
360 REQUIRE(ISC_BUFFER_VALID(b));
361 REQUIRE(b->used - b->current >= 6);
362
363 cp = isc_buffer_current(b);
364 b->current += 6;
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]));
371
372 return (result);
373}
374
375void
376isc__buffer_putuint48(isc_buffer_t *b, isc_uint64_t val) {
377 isc_uint16_t valhi;
378 isc_uint32_t vallo;
379
380 REQUIRE(ISC_BUFFER_VALID(b));
381 REQUIRE(b->used + 6 <= b->length);
382
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);
387}
388
389void
390isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base,
391 unsigned int length)
392{
393 REQUIRE(ISC_BUFFER_VALID(b));
394 REQUIRE(b->used + length <= b->length);
395
396 ISC__BUFFER_PUTMEM(b, base, length);
397}
398
399void
400isc__buffer_putstr(isc_buffer_t *b, const char *source) {
401 unsigned int l;
402 unsigned char *cp;
403
404 REQUIRE(ISC_BUFFER_VALID(b));
405 REQUIRE(source != NULL);
406
407 /*
408 * Do not use ISC__BUFFER_PUTSTR(), so strlen is only done once.
409 */
410 l = strlen(source);
411
412 REQUIRE(l <= isc_buffer_availablelength(b));
413
414 cp = isc_buffer_used(b);
415 memcpy(cp, source, l);
416 b->used += l;
417}
418
419isc_result_t
420isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r) {
421 unsigned char *base;
422 unsigned int available;
423
424 REQUIRE(ISC_BUFFER_VALID(b));
425 REQUIRE(r != NULL);
426
427 /*
428 * XXXDCL
429 */
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;
436
437 return (ISC_R_SUCCESS);
438}
439
440isc_result_t
441isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
442 unsigned int length)
443{
444 isc_buffer_t *dbuf;
445
446 REQUIRE(dynbuffer != NULL);
447 REQUIRE(*dynbuffer == NULL);
448
449 dbuf = isc_mem_get(mctx, length + sizeof(isc_buffer_t));
450 if (dbuf == NULL)
451 return (ISC_R_NOMEMORY);
452
453 isc_buffer_init(dbuf, ((unsigned char *)dbuf) + sizeof(isc_buffer_t),
454 length);
455 dbuf->mctx = mctx;
456
457 *dynbuffer = dbuf;
458
459 return (ISC_R_SUCCESS);
460}
461
462void
463isc_buffer_free(isc_buffer_t **dynbuffer) {
464 unsigned int real_length;
465 isc_buffer_t *dbuf;
466 isc_mem_t *mctx;
467
468 REQUIRE(dynbuffer != NULL);
469 REQUIRE(ISC_BUFFER_VALID(*dynbuffer));
470 REQUIRE((*dynbuffer)->mctx != NULL);
471
472 dbuf = *dynbuffer;
473 *dynbuffer = NULL; /* destroy external reference */
474
475 real_length = dbuf->length + sizeof(isc_buffer_t);
476 mctx = dbuf->mctx;
477 dbuf->mctx = NULL;
478 isc_buffer_invalidate(dbuf);
479
480 isc_mem_put(mctx, dbuf, real_length);
481}