xref: /minix/external/bsd/bind/dist/lib/isc/buffer.c (revision 00b67f09)
1 /*	$NetBSD: buffer.c,v 1.6 2014/12/10 04:37:59 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2004-2008, 2012, 2014  Internet Systems Consortium, Inc. ("ISC")
5  * Copyright (C) 1998-2002  Internet Software Consortium.
6  *
7  * Permission to use, copy, modify, and/or distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /* Id: buffer.c,v 1.49 2008/09/25 04:02:39 tbox Exp  */
21 
22 /*! \file */
23 
24 #include <config.h>
25 
26 #include <isc/buffer.h>
27 #include <isc/mem.h>
28 #include <isc/region.h>
29 #include <isc/string.h>
30 #include <isc/util.h>
31 
32 void
isc__buffer_init(isc_buffer_t * b,void * base,unsigned int length)33 isc__buffer_init(isc_buffer_t *b, void *base, unsigned int length) {
34 	/*
35 	 * Make 'b' refer to the 'length'-byte region starting at 'base'.
36 	 * XXXDCL see the comment in buffer.h about base being const.
37 	 */
38 
39 	REQUIRE(b != NULL);
40 
41 	ISC__BUFFER_INIT(b, base, length);
42 }
43 
44 void
isc__buffer_initnull(isc_buffer_t * b)45 isc__buffer_initnull(isc_buffer_t *b) {
46 	/*
47 	 * Initialize a new buffer which has no backing store.  This can
48 	 * later be grown as needed and swapped in place.
49 	 */
50 
51 	ISC__BUFFER_INIT(b, NULL, 0);
52 }
53 
54 void
isc_buffer_reinit(isc_buffer_t * b,void * base,unsigned int length)55 isc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length) {
56 	/*
57 	 * Re-initialize the buffer enough to reconfigure the base of the
58 	 * buffer.  We will swap in the new buffer, after copying any
59 	 * data we contain into the new buffer and adjusting all of our
60 	 * internal pointers.
61 	 *
62 	 * The buffer must not be smaller than the length of the original
63 	 * buffer.
64 	 */
65 	REQUIRE(b->length <= length);
66 	REQUIRE(base != NULL);
67 
68 	(void)memmove(base, b->base, b->length);
69 	b->base = base;
70 	b->length = length;
71 }
72 
73 void
isc__buffer_invalidate(isc_buffer_t * b)74 isc__buffer_invalidate(isc_buffer_t *b) {
75 	/*
76 	 * Make 'b' an invalid buffer.
77 	 */
78 
79 	REQUIRE(ISC_BUFFER_VALID(b));
80 	REQUIRE(!ISC_LINK_LINKED(b, link));
81 	REQUIRE(b->mctx == NULL);
82 
83 	ISC__BUFFER_INVALIDATE(b);
84 }
85 
86 void
isc__buffer_region(isc_buffer_t * b,isc_region_t * r)87 isc__buffer_region(isc_buffer_t *b, isc_region_t *r) {
88 	/*
89 	 * Make 'r' refer to the region of 'b'.
90 	 */
91 
92 	REQUIRE(ISC_BUFFER_VALID(b));
93 	REQUIRE(r != NULL);
94 
95 	ISC__BUFFER_REGION(b, r);
96 }
97 
98 void
isc__buffer_usedregion(isc_buffer_t * b,isc_region_t * r)99 isc__buffer_usedregion(isc_buffer_t *b, isc_region_t *r) {
100 	/*
101 	 * Make 'r' refer to the used region of 'b'.
102 	 */
103 
104 	REQUIRE(ISC_BUFFER_VALID(b));
105 	REQUIRE(r != NULL);
106 
107 	ISC__BUFFER_USEDREGION(b, r);
108 }
109 
110 void
isc__buffer_availableregion(isc_buffer_t * b,isc_region_t * r)111 isc__buffer_availableregion(isc_buffer_t *b, isc_region_t *r) {
112 	/*
113 	 * Make 'r' refer to the available region of 'b'.
114 	 */
115 
116 	REQUIRE(ISC_BUFFER_VALID(b));
117 	REQUIRE(r != NULL);
118 
119 	ISC__BUFFER_AVAILABLEREGION(b, r);
120 }
121 
122 void
isc__buffer_add(isc_buffer_t * b,unsigned int n)123 isc__buffer_add(isc_buffer_t *b, unsigned int n) {
124 	/*
125 	 * Increase the 'used' region of 'b' by 'n' bytes.
126 	 */
127 
128 	REQUIRE(ISC_BUFFER_VALID(b));
129 	REQUIRE(b->used + n <= b->length);
130 
131 	ISC__BUFFER_ADD(b, n);
132 }
133 
134 void
isc__buffer_subtract(isc_buffer_t * b,unsigned int n)135 isc__buffer_subtract(isc_buffer_t *b, unsigned int n) {
136 	/*
137 	 * Decrease the 'used' region of 'b' by 'n' bytes.
138 	 */
139 
140 	REQUIRE(ISC_BUFFER_VALID(b));
141 	REQUIRE(b->used >= n);
142 
143 	ISC__BUFFER_SUBTRACT(b, n);
144 }
145 
146 void
isc__buffer_clear(isc_buffer_t * b)147 isc__buffer_clear(isc_buffer_t *b) {
148 	/*
149 	 * Make the used region empty.
150 	 */
151 
152 	REQUIRE(ISC_BUFFER_VALID(b));
153 
154 	ISC__BUFFER_CLEAR(b);
155 }
156 
157 void
isc__buffer_consumedregion(isc_buffer_t * b,isc_region_t * r)158 isc__buffer_consumedregion(isc_buffer_t *b, isc_region_t *r) {
159 	/*
160 	 * Make 'r' refer to the consumed region of 'b'.
161 	 */
162 
163 	REQUIRE(ISC_BUFFER_VALID(b));
164 	REQUIRE(r != NULL);
165 
166 	ISC__BUFFER_CONSUMEDREGION(b, r);
167 }
168 
169 void
isc__buffer_remainingregion(isc_buffer_t * b,isc_region_t * r)170 isc__buffer_remainingregion(isc_buffer_t *b, isc_region_t *r) {
171 	/*
172 	 * Make 'r' refer to the remaining region of 'b'.
173 	 */
174 
175 	REQUIRE(ISC_BUFFER_VALID(b));
176 	REQUIRE(r != NULL);
177 
178 	ISC__BUFFER_REMAININGREGION(b, r);
179 }
180 
181 void
isc__buffer_activeregion(isc_buffer_t * b,isc_region_t * r)182 isc__buffer_activeregion(isc_buffer_t *b, isc_region_t *r) {
183 	/*
184 	 * Make 'r' refer to the active region of 'b'.
185 	 */
186 
187 	REQUIRE(ISC_BUFFER_VALID(b));
188 	REQUIRE(r != NULL);
189 
190 	ISC__BUFFER_ACTIVEREGION(b, r);
191 }
192 
193 void
isc__buffer_setactive(isc_buffer_t * b,unsigned int n)194 isc__buffer_setactive(isc_buffer_t *b, unsigned int n) {
195 	/*
196 	 * Sets the end of the active region 'n' bytes after current.
197 	 */
198 
199 	REQUIRE(ISC_BUFFER_VALID(b));
200 	REQUIRE(b->current + n <= b->used);
201 
202 	ISC__BUFFER_SETACTIVE(b, n);
203 }
204 
205 void
isc__buffer_first(isc_buffer_t * b)206 isc__buffer_first(isc_buffer_t *b) {
207 	/*
208 	 * Make the consumed region empty.
209 	 */
210 
211 	REQUIRE(ISC_BUFFER_VALID(b));
212 
213 	ISC__BUFFER_FIRST(b);
214 }
215 
216 void
isc__buffer_forward(isc_buffer_t * b,unsigned int n)217 isc__buffer_forward(isc_buffer_t *b, unsigned int n) {
218 	/*
219 	 * Increase the 'consumed' region of 'b' by 'n' bytes.
220 	 */
221 
222 	REQUIRE(ISC_BUFFER_VALID(b));
223 	REQUIRE(b->current + n <= b->used);
224 
225 	ISC__BUFFER_FORWARD(b, n);
226 }
227 
228 void
isc__buffer_back(isc_buffer_t * b,unsigned int n)229 isc__buffer_back(isc_buffer_t *b, unsigned int n) {
230 	/*
231 	 * Decrease the 'consumed' region of 'b' by 'n' bytes.
232 	 */
233 
234 	REQUIRE(ISC_BUFFER_VALID(b));
235 	REQUIRE(n <= b->current);
236 
237 	ISC__BUFFER_BACK(b, n);
238 }
239 
240 void
isc_buffer_compact(isc_buffer_t * b)241 isc_buffer_compact(isc_buffer_t *b) {
242 	unsigned int length;
243 	void *src;
244 
245 	/*
246 	 * Compact the used region by moving the remaining region so it occurs
247 	 * at the start of the buffer.  The used region is shrunk by the size
248 	 * of the consumed region, and the consumed region is then made empty.
249 	 */
250 
251 	REQUIRE(ISC_BUFFER_VALID(b));
252 
253 	src = isc_buffer_current(b);
254 	length = isc_buffer_remaininglength(b);
255 	(void)memmove(b->base, src, (size_t)length);
256 
257 	if (b->active > b->current)
258 		b->active -= b->current;
259 	else
260 		b->active = 0;
261 	b->current = 0;
262 	b->used = length;
263 }
264 
265 isc_uint8_t
isc_buffer_getuint8(isc_buffer_t * b)266 isc_buffer_getuint8(isc_buffer_t *b) {
267 	unsigned char *cp;
268 	isc_uint8_t result;
269 
270 	/*
271 	 * Read an unsigned 8-bit integer from 'b' and return it.
272 	 */
273 
274 	REQUIRE(ISC_BUFFER_VALID(b));
275 	REQUIRE(b->used - b->current >= 1);
276 
277 	cp = isc_buffer_current(b);
278 	b->current += 1;
279 	result = ((isc_uint8_t)(cp[0]));
280 
281 	return (result);
282 }
283 
284 void
isc__buffer_putuint8(isc_buffer_t * b,isc_uint8_t val)285 isc__buffer_putuint8(isc_buffer_t *b, isc_uint8_t val) {
286 	REQUIRE(ISC_BUFFER_VALID(b));
287 	REQUIRE(b->used + 1 <= b->length);
288 
289 	ISC__BUFFER_PUTUINT8(b, val);
290 }
291 
292 isc_uint16_t
isc_buffer_getuint16(isc_buffer_t * b)293 isc_buffer_getuint16(isc_buffer_t *b) {
294 	unsigned char *cp;
295 	isc_uint16_t result;
296 
297 	/*
298 	 * Read an unsigned 16-bit integer in network byte order from 'b',
299 	 * convert it to host byte order, and return it.
300 	 */
301 
302 	REQUIRE(ISC_BUFFER_VALID(b));
303 	REQUIRE(b->used - b->current >= 2);
304 
305 	cp = isc_buffer_current(b);
306 	b->current += 2;
307 	result = ((unsigned int)(cp[0])) << 8;
308 	result |= ((unsigned int)(cp[1]));
309 
310 	return (result);
311 }
312 
313 void
isc__buffer_putuint16(isc_buffer_t * b,isc_uint16_t val)314 isc__buffer_putuint16(isc_buffer_t *b, isc_uint16_t val) {
315 	REQUIRE(ISC_BUFFER_VALID(b));
316 	REQUIRE(b->used + 2 <= b->length);
317 
318 	ISC__BUFFER_PUTUINT16(b, val);
319 }
320 
321 void
isc__buffer_putuint24(isc_buffer_t * b,isc_uint32_t val)322 isc__buffer_putuint24(isc_buffer_t *b, isc_uint32_t val) {
323 	REQUIRE(ISC_BUFFER_VALID(b));
324 	REQUIRE(b->used + 3 <= b->length);
325 
326 	ISC__BUFFER_PUTUINT24(b, val);
327 }
328 
329 isc_uint32_t
isc_buffer_getuint32(isc_buffer_t * b)330 isc_buffer_getuint32(isc_buffer_t *b) {
331 	unsigned char *cp;
332 	isc_uint32_t result;
333 
334 	/*
335 	 * Read an unsigned 32-bit integer in network byte order from 'b',
336 	 * convert it to host byte order, and return it.
337 	 */
338 
339 	REQUIRE(ISC_BUFFER_VALID(b));
340 	REQUIRE(b->used - b->current >= 4);
341 
342 	cp = isc_buffer_current(b);
343 	b->current += 4;
344 	result = ((unsigned int)(cp[0])) << 24;
345 	result |= ((unsigned int)(cp[1])) << 16;
346 	result |= ((unsigned int)(cp[2])) << 8;
347 	result |= ((unsigned int)(cp[3]));
348 
349 	return (result);
350 }
351 
352 void
isc__buffer_putuint32(isc_buffer_t * b,isc_uint32_t val)353 isc__buffer_putuint32(isc_buffer_t *b, isc_uint32_t val) {
354 	REQUIRE(ISC_BUFFER_VALID(b));
355 	REQUIRE(b->used + 4 <= b->length);
356 
357 	ISC__BUFFER_PUTUINT32(b, val);
358 }
359 
360 isc_uint64_t
isc_buffer_getuint48(isc_buffer_t * b)361 isc_buffer_getuint48(isc_buffer_t *b) {
362 	unsigned char *cp;
363 	isc_uint64_t result;
364 
365 	/*
366 	 * Read an unsigned 48-bit integer in network byte order from 'b',
367 	 * convert it to host byte order, and return it.
368 	 */
369 
370 	REQUIRE(ISC_BUFFER_VALID(b));
371 	REQUIRE(b->used - b->current >= 6);
372 
373 	cp = isc_buffer_current(b);
374 	b->current += 6;
375 	result = ((isc_int64_t)(cp[0])) << 40;
376 	result |= ((isc_int64_t)(cp[1])) << 32;
377 	result |= ((isc_int64_t)(cp[2])) << 24;
378 	result |= ((isc_int64_t)(cp[3])) << 16;
379 	result |= ((isc_int64_t)(cp[4])) << 8;
380 	result |= ((isc_int64_t)(cp[5]));
381 
382 	return (result);
383 }
384 
385 void
isc__buffer_putuint48(isc_buffer_t * b,isc_uint64_t val)386 isc__buffer_putuint48(isc_buffer_t *b, isc_uint64_t val) {
387 	isc_uint16_t valhi;
388 	isc_uint32_t vallo;
389 
390 	REQUIRE(ISC_BUFFER_VALID(b));
391 	REQUIRE(b->used + 6 <= b->length);
392 
393 	valhi = (isc_uint16_t)(val >> 32);
394 	vallo = (isc_uint32_t)(val & 0xFFFFFFFF);
395 	ISC__BUFFER_PUTUINT16(b, valhi);
396 	ISC__BUFFER_PUTUINT32(b, vallo);
397 }
398 
399 void
isc__buffer_putmem(isc_buffer_t * b,const unsigned char * base,unsigned int length)400 isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base,
401 		   unsigned int length)
402 {
403 	REQUIRE(ISC_BUFFER_VALID(b));
404 	REQUIRE(b->used + length <= b->length);
405 
406 	ISC__BUFFER_PUTMEM(b, base, length);
407 }
408 
409 void
isc__buffer_putstr(isc_buffer_t * b,const char * source)410 isc__buffer_putstr(isc_buffer_t *b, const char *source) {
411 	unsigned int l;
412 	unsigned char *cp;
413 
414 	REQUIRE(ISC_BUFFER_VALID(b));
415 	REQUIRE(source != NULL);
416 
417 	/*
418 	 * Do not use ISC__BUFFER_PUTSTR(), so strlen is only done once.
419 	 */
420 	l = strlen(source);
421 
422 	REQUIRE(l <= isc_buffer_availablelength(b));
423 
424 	cp = isc_buffer_used(b);
425 	memmove(cp, source, l);
426 	b->used += l;
427 }
428 
429 isc_result_t
isc_buffer_copyregion(isc_buffer_t * b,const isc_region_t * r)430 isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r) {
431 	unsigned char *base;
432 	unsigned int available;
433 
434 	REQUIRE(ISC_BUFFER_VALID(b));
435 	REQUIRE(r != NULL);
436 
437 	/*
438 	 * XXXDCL
439 	 */
440 	base = isc_buffer_used(b);
441 	available = isc_buffer_availablelength(b);
442 	if (r->length > available)
443 		return (ISC_R_NOSPACE);
444 	memmove(base, r->base, r->length);
445 	b->used += r->length;
446 
447 	return (ISC_R_SUCCESS);
448 }
449 
450 isc_result_t
isc_buffer_allocate(isc_mem_t * mctx,isc_buffer_t ** dynbuffer,unsigned int length)451 isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
452 		    unsigned int length)
453 {
454 	isc_buffer_t *dbuf;
455 
456 	REQUIRE(dynbuffer != NULL);
457 	REQUIRE(*dynbuffer == NULL);
458 
459 	dbuf = isc_mem_get(mctx, length + sizeof(isc_buffer_t));
460 	if (dbuf == NULL)
461 		return (ISC_R_NOMEMORY);
462 
463 	isc_buffer_init(dbuf, ((unsigned char *)dbuf) + sizeof(isc_buffer_t),
464 			length);
465 	dbuf->mctx = mctx;
466 
467 	*dynbuffer = dbuf;
468 
469 	return (ISC_R_SUCCESS);
470 }
471 
472 void
isc_buffer_free(isc_buffer_t ** dynbuffer)473 isc_buffer_free(isc_buffer_t **dynbuffer) {
474 	unsigned int real_length;
475 	isc_buffer_t *dbuf;
476 	isc_mem_t *mctx;
477 
478 	REQUIRE(dynbuffer != NULL);
479 	REQUIRE(ISC_BUFFER_VALID(*dynbuffer));
480 	REQUIRE((*dynbuffer)->mctx != NULL);
481 
482 	dbuf = *dynbuffer;
483 	*dynbuffer = NULL;	/* destroy external reference */
484 
485 	real_length = dbuf->length + sizeof(isc_buffer_t);
486 	mctx = dbuf->mctx;
487 	dbuf->mctx = NULL;
488 	isc_buffer_invalidate(dbuf);
489 
490 	isc_mem_put(mctx, dbuf, real_length);
491 }
492