]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - contrib/bind9/lib/isc/buffer.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / contrib / bind9 / lib / isc / buffer.c
1 /*
2  * Copyright (C) 2004, 2005  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1998-2002  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.40.18.2 2005/04/29 00:16:44 marka 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_invalidate(isc_buffer_t *b) {
44         /*
45          * Make 'b' an invalid buffer.
46          */
47
48         REQUIRE(ISC_BUFFER_VALID(b));
49         REQUIRE(!ISC_LINK_LINKED(b, link));
50         REQUIRE(b->mctx == NULL);
51
52         ISC__BUFFER_INVALIDATE(b);
53 }
54
55 void
56 isc__buffer_region(isc_buffer_t *b, isc_region_t *r) {
57         /*
58          * Make 'r' refer to the region of 'b'.
59          */
60
61         REQUIRE(ISC_BUFFER_VALID(b));
62         REQUIRE(r != NULL);
63
64         ISC__BUFFER_REGION(b, r);
65 }
66
67 void
68 isc__buffer_usedregion(isc_buffer_t *b, isc_region_t *r) {
69         /*
70          * Make 'r' refer to the used region of 'b'.
71          */
72
73         REQUIRE(ISC_BUFFER_VALID(b));
74         REQUIRE(r != NULL);
75
76         ISC__BUFFER_USEDREGION(b, r);
77 }
78
79 void
80 isc__buffer_availableregion(isc_buffer_t *b, isc_region_t *r) {
81         /*
82          * Make 'r' refer to the available region of 'b'.
83          */
84
85         REQUIRE(ISC_BUFFER_VALID(b));
86         REQUIRE(r != NULL);
87
88         ISC__BUFFER_AVAILABLEREGION(b, r);
89 }
90
91 void
92 isc__buffer_add(isc_buffer_t *b, unsigned int n) {
93         /*
94          * Increase the 'used' region of 'b' by 'n' bytes.
95          */
96
97         REQUIRE(ISC_BUFFER_VALID(b));
98         REQUIRE(b->used + n <= b->length);
99
100         ISC__BUFFER_ADD(b, n);
101 }
102
103 void
104 isc__buffer_subtract(isc_buffer_t *b, unsigned int n) {
105         /*
106          * Decrease the 'used' region of 'b' by 'n' bytes.
107          */
108
109         REQUIRE(ISC_BUFFER_VALID(b));
110         REQUIRE(b->used >= n);
111
112         ISC__BUFFER_SUBTRACT(b, n);
113 }
114
115 void
116 isc__buffer_clear(isc_buffer_t *b) {
117         /*
118          * Make the used region empty.
119          */
120
121         REQUIRE(ISC_BUFFER_VALID(b));
122
123         ISC__BUFFER_CLEAR(b);
124 }
125
126 void
127 isc__buffer_consumedregion(isc_buffer_t *b, isc_region_t *r) {
128         /*
129          * Make 'r' refer to the consumed region of 'b'.
130          */
131
132         REQUIRE(ISC_BUFFER_VALID(b));
133         REQUIRE(r != NULL);
134
135         ISC__BUFFER_CONSUMEDREGION(b, r);
136 }
137
138 void
139 isc__buffer_remainingregion(isc_buffer_t *b, isc_region_t *r) {
140         /*
141          * Make 'r' refer to the remaining region of 'b'.
142          */
143
144         REQUIRE(ISC_BUFFER_VALID(b));
145         REQUIRE(r != NULL);
146
147         ISC__BUFFER_REMAININGREGION(b, r);
148 }
149
150 void
151 isc__buffer_activeregion(isc_buffer_t *b, isc_region_t *r) {
152         /*
153          * Make 'r' refer to the active region of 'b'.
154          */
155
156         REQUIRE(ISC_BUFFER_VALID(b));
157         REQUIRE(r != NULL);
158
159         ISC__BUFFER_ACTIVEREGION(b, r);
160 }
161
162 void
163 isc__buffer_setactive(isc_buffer_t *b, unsigned int n) {
164         /*
165          * Sets the end of the active region 'n' bytes after current.
166          */
167
168         REQUIRE(ISC_BUFFER_VALID(b));
169         REQUIRE(b->current + n <= b->used);
170
171         ISC__BUFFER_SETACTIVE(b, n);
172 }
173
174 void
175 isc__buffer_first(isc_buffer_t *b) {
176         /*
177          * Make the consumed region empty.
178          */
179
180         REQUIRE(ISC_BUFFER_VALID(b));
181
182         ISC__BUFFER_FIRST(b);
183 }
184
185 void
186 isc__buffer_forward(isc_buffer_t *b, unsigned int n) {
187         /*
188          * Increase the 'consumed' region of 'b' by 'n' bytes.
189          */
190
191         REQUIRE(ISC_BUFFER_VALID(b));
192         REQUIRE(b->current + n <= b->used);
193
194         ISC__BUFFER_FORWARD(b, n);
195 }
196
197 void
198 isc__buffer_back(isc_buffer_t *b, unsigned int n) {
199         /*
200          * Decrease the 'consumed' region of 'b' by 'n' bytes.
201          */
202
203         REQUIRE(ISC_BUFFER_VALID(b));
204         REQUIRE(n <= b->current);
205
206         ISC__BUFFER_BACK(b, n);
207 }
208
209 void
210 isc_buffer_compact(isc_buffer_t *b) {
211         unsigned int length;
212         void *src;
213
214         /*
215          * Compact the used region by moving the remaining region so it occurs
216          * at the start of the buffer.  The used region is shrunk by the size
217          * of the consumed region, and the consumed region is then made empty.
218          */
219
220         REQUIRE(ISC_BUFFER_VALID(b));
221
222         src = isc_buffer_current(b);
223         length = isc_buffer_remaininglength(b);
224         (void)memmove(b->base, src, (size_t)length);
225
226         if (b->active > b->current)
227                 b->active -= b->current;
228         else
229                 b->active = 0;
230         b->current = 0;
231         b->used = length;
232 }
233
234 isc_uint8_t
235 isc_buffer_getuint8(isc_buffer_t *b) {
236         unsigned char *cp;
237         isc_uint8_t result;
238
239         /*
240          * Read an unsigned 8-bit integer from 'b' and return it.
241          */
242
243         REQUIRE(ISC_BUFFER_VALID(b));
244         REQUIRE(b->used - b->current >= 1);
245
246         cp = isc_buffer_current(b);
247         b->current += 1;
248         result = ((isc_uint8_t)(cp[0]));
249
250         return (result);
251 }
252
253 void
254 isc__buffer_putuint8(isc_buffer_t *b, isc_uint8_t val) {
255         REQUIRE(ISC_BUFFER_VALID(b));
256         REQUIRE(b->used + 1 <= b->length);
257
258         ISC__BUFFER_PUTUINT8(b, val);
259 }
260
261 isc_uint16_t
262 isc_buffer_getuint16(isc_buffer_t *b) {
263         unsigned char *cp;
264         isc_uint16_t result;
265
266         /*
267          * Read an unsigned 16-bit integer in network byte order from 'b',
268          * convert it to host byte order, and return it.
269          */
270
271         REQUIRE(ISC_BUFFER_VALID(b));
272         REQUIRE(b->used - b->current >= 2);
273
274         cp = isc_buffer_current(b);
275         b->current += 2;
276         result = ((unsigned int)(cp[0])) << 8;
277         result |= ((unsigned int)(cp[1]));
278
279         return (result);
280 }
281
282 void
283 isc__buffer_putuint16(isc_buffer_t *b, isc_uint16_t val) {
284         REQUIRE(ISC_BUFFER_VALID(b));
285         REQUIRE(b->used + 2 <= b->length);
286
287         ISC__BUFFER_PUTUINT16(b, val);
288 }
289
290 isc_uint32_t
291 isc_buffer_getuint32(isc_buffer_t *b) {
292         unsigned char *cp;
293         isc_uint32_t result;
294
295         /*
296          * Read an unsigned 32-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 >= 4);
302
303         cp = isc_buffer_current(b);
304         b->current += 4;
305         result = ((unsigned int)(cp[0])) << 24;
306         result |= ((unsigned int)(cp[1])) << 16;
307         result |= ((unsigned int)(cp[2])) << 8;
308         result |= ((unsigned int)(cp[3]));
309
310         return (result);
311 }
312
313 void
314 isc__buffer_putuint32(isc_buffer_t *b, isc_uint32_t val) {
315         REQUIRE(ISC_BUFFER_VALID(b));
316         REQUIRE(b->used + 4 <= b->length);
317
318         ISC__BUFFER_PUTUINT32(b, val);
319 }
320
321 void
322 isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base,
323                    unsigned int length)
324 {
325         REQUIRE(ISC_BUFFER_VALID(b));
326         REQUIRE(b->used + length <= b->length);
327
328         ISC__BUFFER_PUTMEM(b, base, length);
329 }
330
331 void
332 isc__buffer_putstr(isc_buffer_t *b, const char *source) {
333         unsigned int l;
334         unsigned char *cp;
335
336         REQUIRE(ISC_BUFFER_VALID(b));
337         REQUIRE(source != NULL);
338
339         /*
340          * Do not use ISC__BUFFER_PUTSTR(), so strlen is only done once.
341          */
342         l = strlen(source);
343
344         REQUIRE(l <= isc_buffer_availablelength(b));
345
346         cp = isc_buffer_used(b);
347         memcpy(cp, source, l);
348         b->used += l;
349 }
350
351 isc_result_t
352 isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r) {
353         unsigned char *base;
354         unsigned int available;
355
356         REQUIRE(ISC_BUFFER_VALID(b));
357         REQUIRE(r != NULL);
358
359         /*
360          * XXXDCL
361          */
362         base = isc_buffer_used(b);
363         available = isc_buffer_availablelength(b);
364         if (r->length > available)
365                 return (ISC_R_NOSPACE);
366         memcpy(base, r->base, r->length);
367         b->used += r->length;
368
369         return (ISC_R_SUCCESS);
370 }
371
372 isc_result_t
373 isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
374                     unsigned int length)
375 {
376         isc_buffer_t *dbuf;
377
378         REQUIRE(dynbuffer != NULL);
379         REQUIRE(*dynbuffer == NULL);
380
381         dbuf = isc_mem_get(mctx, length + sizeof(isc_buffer_t));
382         if (dbuf == NULL)
383                 return (ISC_R_NOMEMORY);
384
385         isc_buffer_init(dbuf, ((unsigned char *)dbuf) + sizeof(isc_buffer_t),
386                         length);
387         dbuf->mctx = mctx;
388
389         *dynbuffer = dbuf;
390
391         return (ISC_R_SUCCESS);
392 }
393
394 void
395 isc_buffer_free(isc_buffer_t **dynbuffer) {
396         unsigned int real_length;
397         isc_buffer_t *dbuf;
398         isc_mem_t *mctx;
399
400         REQUIRE(dynbuffer != NULL);
401         REQUIRE(ISC_BUFFER_VALID(*dynbuffer));
402         REQUIRE((*dynbuffer)->mctx != NULL);
403
404         dbuf = *dynbuffer;
405         *dynbuffer = NULL;      /* destroy external reference */
406
407         real_length = dbuf->length + sizeof(isc_buffer_t);
408         mctx = dbuf->mctx;
409         dbuf->mctx = NULL;
410         isc_buffer_invalidate(dbuf);
411
412         isc_mem_put(mctx, dbuf, real_length);
413 }