1: /*
2: * Copyright (C) 2004-2008 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.1.1.1 2012/05/29 12:08:38 misho 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: void
320: isc__buffer_putuint24(isc_buffer_t *b, isc_uint32_t val) {
321: REQUIRE(ISC_BUFFER_VALID(b));
322: REQUIRE(b->used + 3 <= b->length);
323:
324: ISC__BUFFER_PUTUINT24(b, val);
325: }
326:
327: isc_uint32_t
328: isc_buffer_getuint32(isc_buffer_t *b) {
329: unsigned char *cp;
330: isc_uint32_t result;
331:
332: /*
333: * Read an unsigned 32-bit integer in network byte order from 'b',
334: * convert it to host byte order, and return it.
335: */
336:
337: REQUIRE(ISC_BUFFER_VALID(b));
338: REQUIRE(b->used - b->current >= 4);
339:
340: cp = isc_buffer_current(b);
341: b->current += 4;
342: result = ((unsigned int)(cp[0])) << 24;
343: result |= ((unsigned int)(cp[1])) << 16;
344: result |= ((unsigned int)(cp[2])) << 8;
345: result |= ((unsigned int)(cp[3]));
346:
347: return (result);
348: }
349:
350: void
351: isc__buffer_putuint32(isc_buffer_t *b, isc_uint32_t val) {
352: REQUIRE(ISC_BUFFER_VALID(b));
353: REQUIRE(b->used + 4 <= b->length);
354:
355: ISC__BUFFER_PUTUINT32(b, val);
356: }
357:
358: isc_uint64_t
359: isc_buffer_getuint48(isc_buffer_t *b) {
360: unsigned char *cp;
361: isc_uint64_t result;
362:
363: /*
364: * Read an unsigned 48-bit integer in network byte order from 'b',
365: * convert it to host byte order, and return it.
366: */
367:
368: REQUIRE(ISC_BUFFER_VALID(b));
369: REQUIRE(b->used - b->current >= 6);
370:
371: cp = isc_buffer_current(b);
372: b->current += 6;
373: result = ((isc_int64_t)(cp[0])) << 40;
374: result |= ((isc_int64_t)(cp[1])) << 32;
375: result |= ((isc_int64_t)(cp[2])) << 24;
376: result |= ((isc_int64_t)(cp[3])) << 16;
377: result |= ((isc_int64_t)(cp[4])) << 8;
378: result |= ((isc_int64_t)(cp[5]));
379:
380: return (result);
381: }
382:
383: void
384: isc__buffer_putuint48(isc_buffer_t *b, isc_uint64_t val) {
385: isc_uint16_t valhi;
386: isc_uint32_t vallo;
387:
388: REQUIRE(ISC_BUFFER_VALID(b));
389: REQUIRE(b->used + 6 <= b->length);
390:
391: valhi = (isc_uint16_t)(val >> 32);
392: vallo = (isc_uint32_t)(val & 0xFFFFFFFF);
393: ISC__BUFFER_PUTUINT16(b, valhi);
394: ISC__BUFFER_PUTUINT32(b, vallo);
395: }
396:
397: void
398: isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base,
399: unsigned int length)
400: {
401: REQUIRE(ISC_BUFFER_VALID(b));
402: REQUIRE(b->used + length <= b->length);
403:
404: ISC__BUFFER_PUTMEM(b, base, length);
405: }
406:
407: void
408: isc__buffer_putstr(isc_buffer_t *b, const char *source) {
409: unsigned int l;
410: unsigned char *cp;
411:
412: REQUIRE(ISC_BUFFER_VALID(b));
413: REQUIRE(source != NULL);
414:
415: /*
416: * Do not use ISC__BUFFER_PUTSTR(), so strlen is only done once.
417: */
418: l = strlen(source);
419:
420: REQUIRE(l <= isc_buffer_availablelength(b));
421:
422: cp = isc_buffer_used(b);
423: memcpy(cp, source, l);
424: b->used += l;
425: }
426:
427: isc_result_t
428: isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r) {
429: unsigned char *base;
430: unsigned int available;
431:
432: REQUIRE(ISC_BUFFER_VALID(b));
433: REQUIRE(r != NULL);
434:
435: /*
436: * XXXDCL
437: */
438: base = isc_buffer_used(b);
439: available = isc_buffer_availablelength(b);
440: if (r->length > available)
441: return (ISC_R_NOSPACE);
442: memcpy(base, r->base, r->length);
443: b->used += r->length;
444:
445: return (ISC_R_SUCCESS);
446: }
447:
448: isc_result_t
449: isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
450: unsigned int length)
451: {
452: isc_buffer_t *dbuf;
453:
454: REQUIRE(dynbuffer != NULL);
455: REQUIRE(*dynbuffer == NULL);
456:
457: dbuf = isc_mem_get(mctx, length + sizeof(isc_buffer_t));
458: if (dbuf == NULL)
459: return (ISC_R_NOMEMORY);
460:
461: isc_buffer_init(dbuf, ((unsigned char *)dbuf) + sizeof(isc_buffer_t),
462: length);
463: dbuf->mctx = mctx;
464:
465: *dynbuffer = dbuf;
466:
467: return (ISC_R_SUCCESS);
468: }
469:
470: void
471: isc_buffer_free(isc_buffer_t **dynbuffer) {
472: unsigned int real_length;
473: isc_buffer_t *dbuf;
474: isc_mem_t *mctx;
475:
476: REQUIRE(dynbuffer != NULL);
477: REQUIRE(ISC_BUFFER_VALID(*dynbuffer));
478: REQUIRE((*dynbuffer)->mctx != NULL);
479:
480: dbuf = *dynbuffer;
481: *dynbuffer = NULL; /* destroy external reference */
482:
483: real_length = dbuf->length + sizeof(isc_buffer_t);
484: mctx = dbuf->mctx;
485: dbuf->mctx = NULL;
486: isc_buffer_invalidate(dbuf);
487:
488: isc_mem_put(mctx, dbuf, real_length);
489: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>