Merge from vendor branch SENDMAIL:
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / isc / buffer.c
1 /*
2  * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1998-2001  Internet Software Consortium.
4  *
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.
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.36.2.1 2004/03/09 06:11:45 marka Exp $ */
19
20 #include <config.h>
21
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>
27
28 void
29 isc__buffer_init(isc_buffer_t *b, const void *base, unsigned int length) {
30         /*
31          * Make 'b' refer to the 'length'-byte region starting at 'base'.
32          * XXXDCL see the comment in buffer.h about base being const.
33          */
34
35         REQUIRE(b != NULL);
36
37         ISC__BUFFER_INIT(b, base, length);
38 }
39
40 void
41 isc__buffer_invalidate(isc_buffer_t *b) {
42         /*
43          * Make 'b' an invalid buffer.
44          */
45
46         REQUIRE(ISC_BUFFER_VALID(b));
47         REQUIRE(!ISC_LINK_LINKED(b, link));
48         REQUIRE(b->mctx == NULL);
49
50         ISC__BUFFER_INVALIDATE(b);
51 }
52
53 void
54 isc__buffer_region(isc_buffer_t *b, isc_region_t *r) {
55         /*
56          * Make 'r' refer to the region of 'b'.
57          */
58
59         REQUIRE(ISC_BUFFER_VALID(b));
60         REQUIRE(r != NULL);
61
62         ISC__BUFFER_REGION(b, r);
63 }
64
65 void
66 isc__buffer_usedregion(isc_buffer_t *b, isc_region_t *r) {
67         /*
68          * Make 'r' refer to the used region of 'b'.
69          */
70
71         REQUIRE(ISC_BUFFER_VALID(b));
72         REQUIRE(r != NULL);
73
74         ISC__BUFFER_USEDREGION(b, r);
75 }
76
77 void
78 isc__buffer_availableregion(isc_buffer_t *b, isc_region_t *r) {
79         /*
80          * Make 'r' refer to the available region of 'b'.
81          */
82
83         REQUIRE(ISC_BUFFER_VALID(b));
84         REQUIRE(r != NULL);
85
86         ISC__BUFFER_AVAILABLEREGION(b, r);
87 }
88
89 void
90 isc__buffer_add(isc_buffer_t *b, unsigned int n) {
91         /*
92          * Increase the 'used' region of 'b' by 'n' bytes.
93          */
94
95         REQUIRE(ISC_BUFFER_VALID(b));
96         REQUIRE(b->used + n <= b->length);
97
98         ISC__BUFFER_ADD(b, n);
99 }
100
101 void
102 isc__buffer_subtract(isc_buffer_t *b, unsigned int n) {
103         /*
104          * Decrease the 'used' region of 'b' by 'n' bytes.
105          */
106
107         REQUIRE(ISC_BUFFER_VALID(b));
108         REQUIRE(b->used >= n);
109
110         ISC__BUFFER_SUBTRACT(b, n);
111 }
112
113 void
114 isc__buffer_clear(isc_buffer_t *b) {
115         /*
116          * Make the used region empty.
117          */
118
119         REQUIRE(ISC_BUFFER_VALID(b));
120
121         ISC__BUFFER_CLEAR(b);
122 }
123
124 void
125 isc__buffer_consumedregion(isc_buffer_t *b, isc_region_t *r) {
126         /*
127          * Make 'r' refer to the consumed region of 'b'.
128          */
129
130         REQUIRE(ISC_BUFFER_VALID(b));
131         REQUIRE(r != NULL);
132
133         ISC__BUFFER_CONSUMEDREGION(b, r);
134 }
135
136 void
137 isc__buffer_remainingregion(isc_buffer_t *b, isc_region_t *r) {
138         /*
139          * Make 'r' refer to the remaining region of 'b'.
140          */
141
142         REQUIRE(ISC_BUFFER_VALID(b));
143         REQUIRE(r != NULL);
144
145         ISC__BUFFER_REMAININGREGION(b, r);
146 }
147
148 void
149 isc__buffer_activeregion(isc_buffer_t *b, isc_region_t *r) {
150         /*
151          * Make 'r' refer to the active region of 'b'.
152          */
153
154         REQUIRE(ISC_BUFFER_VALID(b));
155         REQUIRE(r != NULL);
156
157         ISC__BUFFER_ACTIVEREGION(b, r);
158 }
159
160 void
161 isc__buffer_setactive(isc_buffer_t *b, unsigned int n) {
162         /*
163          * Sets the end of the active region 'n' bytes after current.
164          */
165
166         REQUIRE(ISC_BUFFER_VALID(b));
167         REQUIRE(b->current + n <= b->used);
168
169         ISC__BUFFER_SETACTIVE(b, n);
170 }
171
172 void
173 isc__buffer_first(isc_buffer_t *b) {
174         /*
175          * Make the consumed region empty.
176          */
177
178         REQUIRE(ISC_BUFFER_VALID(b));
179
180         ISC__BUFFER_FIRST(b);
181 }
182
183 void
184 isc__buffer_forward(isc_buffer_t *b, unsigned int n) {
185         /*
186          * Increase the 'consumed' region of 'b' by 'n' bytes.
187          */
188
189         REQUIRE(ISC_BUFFER_VALID(b));
190         REQUIRE(b->current + n <= b->used);
191
192         ISC__BUFFER_FORWARD(b, n);
193 }
194
195 void
196 isc__buffer_back(isc_buffer_t *b, unsigned int n) {
197         /*
198          * Decrease the 'consumed' region of 'b' by 'n' bytes.
199          */
200
201         REQUIRE(ISC_BUFFER_VALID(b));
202         REQUIRE(n <= b->current);
203
204         ISC__BUFFER_BACK(b, n);
205 }
206
207 void
208 isc_buffer_compact(isc_buffer_t *b) {
209         unsigned int length;
210         void *src;
211
212         /*
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.
216          */
217
218         REQUIRE(ISC_BUFFER_VALID(b));
219
220         src = isc_buffer_current(b);
221         length = isc_buffer_remaininglength(b);
222         (void)memmove(b->base, src, (size_t)length);
223
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;
230 }
231
232 isc_uint8_t
233 isc_buffer_getuint8(isc_buffer_t *b) {
234         unsigned char *cp;
235         isc_uint8_t result;
236
237         /*
238          * Read an unsigned 8-bit integer from 'b' and return it.
239          */
240
241         REQUIRE(ISC_BUFFER_VALID(b));
242         REQUIRE(b->used - b->current >= 1);
243
244         cp = isc_buffer_current(b);
245         b->current += 1;
246         result = ((isc_uint8_t)(cp[0]));
247
248         return (result);
249 }
250
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);
255
256         ISC__BUFFER_PUTUINT8(b, val);
257 }
258
259 isc_uint16_t
260 isc_buffer_getuint16(isc_buffer_t *b) {
261         unsigned char *cp;
262         isc_uint16_t result;
263
264         /*
265          * Read an unsigned 16-bit integer in network byte order from 'b',
266          * convert it to host byte order, and return it.
267          */
268
269         REQUIRE(ISC_BUFFER_VALID(b));
270         REQUIRE(b->used - b->current >= 2);
271
272         cp = isc_buffer_current(b);
273         b->current += 2;
274         result = ((unsigned int)(cp[0])) << 8;
275         result |= ((unsigned int)(cp[1]));
276
277         return (result);
278 }
279
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);
284
285         ISC__BUFFER_PUTUINT16(b, val);
286 }
287
288 isc_uint32_t
289 isc_buffer_getuint32(isc_buffer_t *b) {
290         unsigned char *cp;
291         isc_uint32_t result;
292
293         /*
294          * Read an unsigned 32-bit integer in network byte order from 'b',
295          * convert it to host byte order, and return it.
296          */
297
298         REQUIRE(ISC_BUFFER_VALID(b));
299         REQUIRE(b->used - b->current >= 4);
300
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]));
307
308         return (result);
309 }
310
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);
315
316         ISC__BUFFER_PUTUINT32(b, val);
317 }
318
319 void
320 isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base,
321                    unsigned int length)
322 {
323         REQUIRE(ISC_BUFFER_VALID(b));
324         REQUIRE(b->used + length <= b->length);
325
326         ISC__BUFFER_PUTMEM(b, base, length);
327 }
328
329 void
330 isc__buffer_putstr(isc_buffer_t *b, const char *source) {
331         unsigned int l;
332         unsigned char *cp;
333
334         REQUIRE(ISC_BUFFER_VALID(b));
335         REQUIRE(source != NULL);
336
337         /*
338          * Do not use ISC__BUFFER_PUTSTR(), so strlen is only done once.
339          */
340         l = strlen(source);
341
342         REQUIRE(l <= isc_buffer_availablelength(b));
343
344         cp = isc_buffer_used(b);
345         memcpy(cp, source, l);
346         b->used += l;
347 }
348
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;
353
354         REQUIRE(ISC_BUFFER_VALID(b));
355         REQUIRE(r != NULL);
356
357         /*
358          * XXXDCL
359          */
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;
366
367         return (ISC_R_SUCCESS);
368 }
369
370 isc_result_t
371 isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
372                     unsigned int length)
373 {
374         isc_buffer_t *dbuf;
375
376         REQUIRE(dynbuffer != NULL);
377         REQUIRE(*dynbuffer == NULL);
378
379         dbuf = isc_mem_get(mctx, length + sizeof(isc_buffer_t));
380         if (dbuf == NULL)
381                 return (ISC_R_NOMEMORY);
382
383         isc_buffer_init(dbuf, ((unsigned char *)dbuf) + sizeof(isc_buffer_t),
384                         length);
385         dbuf->mctx = mctx;
386
387         *dynbuffer = dbuf;
388
389         return (ISC_R_SUCCESS);
390 }
391
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;
397
398         REQUIRE(dynbuffer != NULL);
399         REQUIRE(ISC_BUFFER_VALID(*dynbuffer));
400         REQUIRE((*dynbuffer)->mctx != NULL);
401
402         dbuf = *dynbuffer;
403         *dynbuffer = NULL;      /* destroy external reference */
404
405         real_length = dbuf->length + sizeof(isc_buffer_t);
406         mctx = dbuf->mctx;
407         dbuf->mctx = NULL;
408         isc_buffer_invalidate(dbuf);
409
410         isc_mem_put(mctx, dbuf, real_length);
411 }