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