Import bind 9.5.2 vendor sources.
[dragonfly.git] / contrib / bind-9.5.2 / lib / isc / buffer.c
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
30 void
31 isc__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
42 void
43 isc__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
52 void
53 isc_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
71 void
72 isc__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
84 void
85 isc__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
96 void
97 isc__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
108 void
109 isc__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
120 void
121 isc__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
132 void
133 isc__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
144 void
145 isc__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
155 void
156 isc__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
167 void
168 isc__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
179 void
180 isc__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
191 void
192 isc__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
203 void
204 isc__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
214 void
215 isc__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
226 void
227 isc__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
238 void
239 isc_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
263 isc_uint8_t
264 isc_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
282 void
283 isc__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
290 isc_uint16_t
291 isc_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
311 void
312 isc__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
319 isc_uint32_t
320 isc_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
342 void
343 isc__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
350 isc_uint64_t
351 isc_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
375 void
376 isc__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
389 void
390 isc__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
399 void
400 isc__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
419 isc_result_t
420 isc_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
440 isc_result_t
441 isc_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
462 void
463 isc_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 }