1290001Sglebius/*
2290001Sglebius * Copyright (C) 2004-2008, 2010  Internet Systems Consortium, Inc. ("ISC")
3290001Sglebius * Copyright (C) 1998-2002  Internet Software Consortium.
4290001Sglebius *
5290001Sglebius * Permission to use, copy, modify, and/or distribute this software for any
6290001Sglebius * purpose with or without fee is hereby granted, provided that the above
7290001Sglebius * copyright notice and this permission notice appear in all copies.
8290001Sglebius *
9290001Sglebius * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10290001Sglebius * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11290001Sglebius * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12290001Sglebius * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13290001Sglebius * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14290001Sglebius * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15290001Sglebius * PERFORMANCE OF THIS SOFTWARE.
16290001Sglebius */
17290001Sglebius
18290001Sglebius/* $Id: buffer.h,v 1.55 2010/12/20 23:47:21 tbox Exp $ */
19290001Sglebius
20290001Sglebius#ifndef ISC_BUFFER_H
21290001Sglebius#define ISC_BUFFER_H 1
22290001Sglebius
23290001Sglebius/*****
24290001Sglebius ***** Module Info
25290001Sglebius *****/
26290001Sglebius
27290001Sglebius/*! \file isc/buffer.h
28290001Sglebius *
29290001Sglebius * \brief A buffer is a region of memory, together with a set of related subregions.
30290001Sglebius * Buffers are used for parsing and I/O operations.
31290001Sglebius *
32290001Sglebius * The 'used region' and the 'available' region are disjoint, and their
33290001Sglebius * union is the buffer's region.  The used region extends from the beginning
34290001Sglebius * of the buffer region to the last used byte.  The available region
35290001Sglebius * extends from one byte greater than the last used byte to the end of the
36290001Sglebius * buffer's region.  The size of the used region can be changed using various
37290001Sglebius * buffer commands.  Initially, the used region is empty.
38290001Sglebius *
39290001Sglebius * The used region is further subdivided into two disjoint regions: the
40290001Sglebius * 'consumed region' and the 'remaining region'.  The union of these two
41290001Sglebius * regions is the used region.  The consumed region extends from the beginning
42290001Sglebius * of the used region to the byte before the 'current' offset (if any).  The
43290001Sglebius * 'remaining' region the current pointer to the end of the used
44290001Sglebius * region.  The size of the consumed region can be changed using various
45290001Sglebius * buffer commands.  Initially, the consumed region is empty.
46290001Sglebius *
47290001Sglebius * The 'active region' is an (optional) subregion of the remaining region.
48290001Sglebius * It extends from the current offset to an offset in the remaining region
49290001Sglebius * that is selected with isc_buffer_setactive().  Initially, the active region
50290001Sglebius * is empty.  If the current offset advances beyond the chosen offset, the
51290001Sglebius * active region will also be empty.
52290001Sglebius *
53290001Sglebius * \verbatim
54290001Sglebius *  /------------entire length---------------\
55290001Sglebius *  /----- used region -----\/-- available --\
56290001Sglebius *  +----------------------------------------+
57290001Sglebius *  | consumed  | remaining |                |
58290001Sglebius *  +----------------------------------------+
59290001Sglebius *  a           b     c     d                e
60290001Sglebius *
61290001Sglebius * a == base of buffer.
62290001Sglebius * b == current pointer.  Can be anywhere between a and d.
63290001Sglebius * c == active pointer.  Meaningful between b and d.
64290001Sglebius * d == used pointer.
65290001Sglebius * e == length of buffer.
66290001Sglebius *
67290001Sglebius * a-e == entire length of buffer.
68290001Sglebius * a-d == used region.
69290001Sglebius * a-b == consumed region.
70290001Sglebius * b-d == remaining region.
71290001Sglebius * b-c == optional active region.
72290001Sglebius *\endverbatim
73290001Sglebius *
74290001Sglebius * The following invariants are maintained by all routines:
75290001Sglebius *
76290001Sglebius *\code
77290001Sglebius *	length > 0
78290001Sglebius *
79290001Sglebius *	base is a valid pointer to length bytes of memory
80290001Sglebius *
81290001Sglebius *	0 <= used <= length
82290001Sglebius *
83290001Sglebius *	0 <= current <= used
84290001Sglebius *
85290001Sglebius *	0 <= active <= used
86290001Sglebius *	(although active < current implies empty active region)
87290001Sglebius *\endcode
88290001Sglebius *
89290001Sglebius * \li MP:
90290001Sglebius *	Buffers have no synchronization.  Clients must ensure exclusive
91290001Sglebius *	access.
92290001Sglebius *
93290001Sglebius * \li Reliability:
94290001Sglebius *	No anticipated impact.
95290001Sglebius *
96290001Sglebius * \li Resources:
97290001Sglebius *	Memory: 1 pointer + 6 unsigned integers per buffer.
98290001Sglebius *
99290001Sglebius * \li Security:
100290001Sglebius *	No anticipated impact.
101290001Sglebius *
102290001Sglebius * \li Standards:
103290001Sglebius *	None.
104290001Sglebius */
105290001Sglebius
106290001Sglebius/***
107290001Sglebius *** Imports
108290001Sglebius ***/
109290001Sglebius
110290001Sglebius#include <isc/lang.h>
111290001Sglebius#include <isc/magic.h>
112290001Sglebius#include <isc/types.h>
113290001Sglebius
114290001Sglebius/*!
115290001Sglebius * To make many functions be inline macros (via \#define) define this.
116290001Sglebius * If it is undefined, a function will be used.
117290001Sglebius */
118290001Sglebius/* #define ISC_BUFFER_USEINLINE */
119290001Sglebius
120290001SglebiusISC_LANG_BEGINDECLS
121290001Sglebius
122290001Sglebius/*@{*/
123290001Sglebius/*!
124290001Sglebius *** Magic numbers
125290001Sglebius ***/
126290001Sglebius#define ISC_BUFFER_MAGIC		0x42756621U	/* Buf!. */
127290001Sglebius#define ISC_BUFFER_VALID(b)		ISC_MAGIC_VALID(b, ISC_BUFFER_MAGIC)
128290001Sglebius/*@}*/
129290001Sglebius
130290001Sglebius/*
131290001Sglebius * The following macros MUST be used only on valid buffers.  It is the
132290001Sglebius * caller's responsibility to ensure this by using the ISC_BUFFER_VALID
133290001Sglebius * check above, or by calling another isc_buffer_*() function (rather than
134290001Sglebius * another macro.)
135290001Sglebius */
136290001Sglebius
137290001Sglebius/*@{*/
138290001Sglebius/*!
139290001Sglebius * Fundamental buffer elements.  (A through E in the introductory comment.)
140290001Sglebius */
141290001Sglebius#define isc_buffer_base(b)    ((void *)(b)->base)			  /*a*/
142290001Sglebius#define isc_buffer_current(b) \
143290001Sglebius		((void *)((unsigned char *)(b)->base + (b)->current))     /*b*/
144290001Sglebius#define isc_buffer_active(b)  \
145290001Sglebius		((void *)((unsigned char *)(b)->base + (b)->active))      /*c*/
146290001Sglebius#define isc_buffer_used(b)    \
147290001Sglebius		((void *)((unsigned char *)(b)->base + (b)->used))        /*d*/
148290001Sglebius#define isc_buffer_length(b)  ((b)->length)				  /*e*/
149290001Sglebius/*@}*/
150290001Sglebius
151290001Sglebius/*@{*/
152290001Sglebius/*!
153290001Sglebius * Derived lengths.  (Described in the introductory comment.)
154290001Sglebius */
155290001Sglebius#define isc_buffer_usedlength(b)	((b)->used)		      /* d-a */
156290001Sglebius#define isc_buffer_consumedlength(b)	((b)->current)		      /* b-a */
157290001Sglebius#define isc_buffer_remaininglength(b)	((b)->used - (b)->current)    /* d-b */
158290001Sglebius#define isc_buffer_activelength(b)	((b)->active - (b)->current)  /* c-b */
159290001Sglebius#define isc_buffer_availablelength(b)	((b)->length - (b)->used)     /* e-d */
160290001Sglebius/*@}*/
161290001Sglebius
162290001Sglebius/*!
163290001Sglebius * Note that the buffer structure is public.  This is principally so buffer
164290001Sglebius * operations can be implemented using macros.  Applications are strongly
165290001Sglebius * discouraged from directly manipulating the structure.
166290001Sglebius */
167290001Sglebius
168290001Sglebiusstruct isc_buffer {
169290001Sglebius	unsigned int		magic;
170290001Sglebius	void		       *base;
171290001Sglebius	/*@{*/
172290001Sglebius	/*! The following integers are byte offsets from 'base'. */
173290001Sglebius	unsigned int		length;
174290001Sglebius	unsigned int		used;
175290001Sglebius	unsigned int 		current;
176290001Sglebius	unsigned int 		active;
177290001Sglebius	/*@}*/
178290001Sglebius	/*! linkable */
179290001Sglebius	ISC_LINK(isc_buffer_t)	link;
180290001Sglebius	/*! private internal elements */
181290001Sglebius	isc_mem_t	       *mctx;
182290001Sglebius};
183290001Sglebius
184290001Sglebius/***
185290001Sglebius *** Functions
186290001Sglebius ***/
187290001Sglebius
188290001Sglebiusisc_result_t
189290001Sglebiusisc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
190290001Sglebius		    unsigned int length);
191290001Sglebius/*!<
192290001Sglebius * \brief Allocate a dynamic linkable buffer which has "length" bytes in the
193290001Sglebius * data region.
194290001Sglebius *
195290001Sglebius * Requires:
196290001Sglebius *\li	"mctx" is valid.
197290001Sglebius *
198290001Sglebius *\li	"dynbuffer" is non-NULL, and "*dynbuffer" is NULL.
199290001Sglebius *
200290001Sglebius * Returns:
201290001Sglebius *\li	ISC_R_SUCCESS		- success
202290001Sglebius *\li	ISC_R_NOMEMORY		- no memory available
203290001Sglebius *
204290001Sglebius * Note:
205290001Sglebius *\li	Changing the buffer's length field is not permitted.
206290001Sglebius */
207290001Sglebius
208290001Sglebiusvoid
209290001Sglebiusisc_buffer_free(isc_buffer_t **dynbuffer);
210290001Sglebius/*!<
211290001Sglebius * \brief Release resources allocated for a dynamic buffer.
212290001Sglebius *
213290001Sglebius * Requires:
214290001Sglebius *\li	"dynbuffer" is not NULL.
215290001Sglebius *
216290001Sglebius *\li	"*dynbuffer" is a valid dynamic buffer.
217290001Sglebius *
218290001Sglebius * Ensures:
219290001Sglebius *\li	"*dynbuffer" will be NULL on return, and all memory associated with
220290001Sglebius *	the dynamic buffer is returned to the memory context used in
221290001Sglebius *	isc_buffer_allocate().
222290001Sglebius */
223290001Sglebius
224290001Sglebiusvoid
225290001Sglebiusisc__buffer_init(isc_buffer_t *b, const void *base, unsigned int length);
226290001Sglebius/*!<
227290001Sglebius * \brief Make 'b' refer to the 'length'-byte region starting at base.
228290001Sglebius *
229290001Sglebius * Requires:
230290001Sglebius *
231290001Sglebius *\li	'length' > 0
232290001Sglebius *
233290001Sglebius *\li	'base' is a pointer to a sequence of 'length' bytes.
234290001Sglebius *
235290001Sglebius */
236290001Sglebius
237290001Sglebiusvoid
238290001Sglebiusisc__buffer_initnull(isc_buffer_t *b);
239290001Sglebius/*!<
240290001Sglebius *\brief Initialize a buffer 'b' with a null data and zero length/
241290001Sglebius */
242290001Sglebius
243290001Sglebiusvoid
244290001Sglebiusisc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length);
245290001Sglebius/*!<
246290001Sglebius * \brief Make 'b' refer to the 'length'-byte region starting at base.
247290001Sglebius * Any existing data will be copied.
248290001Sglebius *
249290001Sglebius * Requires:
250290001Sglebius *
251290001Sglebius *\li	'length' > 0 AND length >= previous length
252290001Sglebius *
253290001Sglebius *\li	'base' is a pointer to a sequence of 'length' bytes.
254290001Sglebius *
255290001Sglebius */
256290001Sglebius
257290001Sglebiusvoid
258290001Sglebiusisc__buffer_invalidate(isc_buffer_t *b);
259290001Sglebius/*!<
260290001Sglebius * \brief Make 'b' an invalid buffer.
261290001Sglebius *
262290001Sglebius * Requires:
263290001Sglebius *\li	'b' is a valid buffer.
264290001Sglebius *
265290001Sglebius * Ensures:
266290001Sglebius *\li	If assertion checking is enabled, future attempts to use 'b' without
267290001Sglebius *	calling isc_buffer_init() on it will cause an assertion failure.
268290001Sglebius */
269290001Sglebius
270290001Sglebiusvoid
271290001Sglebiusisc__buffer_region(isc_buffer_t *b, isc_region_t *r);
272290001Sglebius/*!<
273290001Sglebius * \brief Make 'r' refer to the region of 'b'.
274290001Sglebius *
275290001Sglebius * Requires:
276290001Sglebius *
277290001Sglebius *\li	'b' is a valid buffer.
278290001Sglebius *
279290001Sglebius *\li	'r' points to a region structure.
280290001Sglebius */
281290001Sglebius
282290001Sglebiusvoid
283290001Sglebiusisc__buffer_usedregion(isc_buffer_t *b, isc_region_t *r);
284290001Sglebius/*!<
285290001Sglebius * \brief Make 'r' refer to the used region of 'b'.
286290001Sglebius *
287290001Sglebius * Requires:
288290001Sglebius *
289290001Sglebius *\li	'b' is a valid buffer.
290290001Sglebius *
291290001Sglebius *\li	'r' points to a region structure.
292290001Sglebius */
293290001Sglebius
294290001Sglebiusvoid
295290001Sglebiusisc__buffer_availableregion(isc_buffer_t *b, isc_region_t *r);
296290001Sglebius/*!<
297290001Sglebius * \brief Make 'r' refer to the available region of 'b'.
298290001Sglebius *
299290001Sglebius * Requires:
300290001Sglebius *
301290001Sglebius *\li	'b' is a valid buffer.
302290001Sglebius *
303290001Sglebius *\li	'r' points to a region structure.
304290001Sglebius */
305290001Sglebius
306290001Sglebiusvoid
307290001Sglebiusisc__buffer_add(isc_buffer_t *b, unsigned int n);
308290001Sglebius/*!<
309290001Sglebius * \brief Increase the 'used' region of 'b' by 'n' bytes.
310290001Sglebius *
311290001Sglebius * Requires:
312290001Sglebius *
313290001Sglebius *\li	'b' is a valid buffer
314290001Sglebius *
315290001Sglebius *\li	used + n <= length
316290001Sglebius *
317290001Sglebius */
318290001Sglebius
319290001Sglebiusvoid
320290001Sglebiusisc__buffer_subtract(isc_buffer_t *b, unsigned int n);
321290001Sglebius/*!<
322290001Sglebius * \brief Decrease the 'used' region of 'b' by 'n' bytes.
323290001Sglebius *
324290001Sglebius * Requires:
325290001Sglebius *
326290001Sglebius *\li	'b' is a valid buffer
327290001Sglebius *
328290001Sglebius *\li	used >= n
329290001Sglebius *
330290001Sglebius */
331290001Sglebius
332290001Sglebiusvoid
333290001Sglebiusisc__buffer_clear(isc_buffer_t *b);
334290001Sglebius/*!<
335290001Sglebius * \brief Make the used region empty.
336290001Sglebius *
337290001Sglebius * Requires:
338290001Sglebius *
339290001Sglebius *\li	'b' is a valid buffer
340290001Sglebius *
341290001Sglebius * Ensures:
342290001Sglebius *
343290001Sglebius *\li	used = 0
344290001Sglebius *
345290001Sglebius */
346290001Sglebius
347290001Sglebiusvoid
348290001Sglebiusisc__buffer_consumedregion(isc_buffer_t *b, isc_region_t *r);
349290001Sglebius/*!<
350290001Sglebius * \brief Make 'r' refer to the consumed region of 'b'.
351290001Sglebius *
352290001Sglebius * Requires:
353290001Sglebius *
354290001Sglebius *\li	'b' is a valid buffer.
355290001Sglebius *
356290001Sglebius *\li	'r' points to a region structure.
357290001Sglebius */
358290001Sglebius
359290001Sglebiusvoid
360290001Sglebiusisc__buffer_remainingregion(isc_buffer_t *b, isc_region_t *r);
361290001Sglebius/*!<
362290001Sglebius * \brief Make 'r' refer to the remaining region of 'b'.
363290001Sglebius *
364290001Sglebius * Requires:
365290001Sglebius *
366290001Sglebius *\li	'b' is a valid buffer.
367290001Sglebius *
368290001Sglebius *\li	'r' points to a region structure.
369290001Sglebius */
370290001Sglebius
371290001Sglebiusvoid
372290001Sglebiusisc__buffer_activeregion(isc_buffer_t *b, isc_region_t *r);
373290001Sglebius/*!<
374290001Sglebius * \brief Make 'r' refer to the active region of 'b'.
375290001Sglebius *
376290001Sglebius * Requires:
377290001Sglebius *
378290001Sglebius *\li	'b' is a valid buffer.
379290001Sglebius *
380290001Sglebius *\li	'r' points to a region structure.
381290001Sglebius */
382290001Sglebius
383290001Sglebiusvoid
384290001Sglebiusisc__buffer_setactive(isc_buffer_t *b, unsigned int n);
385290001Sglebius/*!<
386290001Sglebius * \brief Sets the end of the active region 'n' bytes after current.
387290001Sglebius *
388290001Sglebius * Requires:
389290001Sglebius *
390290001Sglebius *\li	'b' is a valid buffer.
391290001Sglebius *
392290001Sglebius *\li	current + n <= used
393290001Sglebius */
394290001Sglebius
395290001Sglebiusvoid
396290001Sglebiusisc__buffer_first(isc_buffer_t *b);
397290001Sglebius/*!<
398290001Sglebius * \brief Make the consumed region empty.
399290001Sglebius *
400290001Sglebius * Requires:
401290001Sglebius *
402290001Sglebius *\li	'b' is a valid buffer
403290001Sglebius *
404290001Sglebius * Ensures:
405290001Sglebius *
406290001Sglebius *\li	current == 0
407290001Sglebius *
408290001Sglebius */
409290001Sglebius
410290001Sglebiusvoid
411290001Sglebiusisc__buffer_forward(isc_buffer_t *b, unsigned int n);
412290001Sglebius/*!<
413290001Sglebius * \brief Increase the 'consumed' region of 'b' by 'n' bytes.
414290001Sglebius *
415290001Sglebius * Requires:
416290001Sglebius *
417290001Sglebius *\li	'b' is a valid buffer
418290001Sglebius *
419290001Sglebius *\li	current + n <= used
420290001Sglebius *
421290001Sglebius */
422290001Sglebius
423290001Sglebiusvoid
424290001Sglebiusisc__buffer_back(isc_buffer_t *b, unsigned int n);
425290001Sglebius/*!<
426290001Sglebius * \brief Decrease the 'consumed' region of 'b' by 'n' bytes.
427290001Sglebius *
428290001Sglebius * Requires:
429290001Sglebius *
430290001Sglebius *\li	'b' is a valid buffer
431290001Sglebius *
432290001Sglebius *\li	n <= current
433290001Sglebius *
434290001Sglebius */
435290001Sglebius
436290001Sglebiusvoid
437290001Sglebiusisc_buffer_compact(isc_buffer_t *b);
438290001Sglebius/*!<
439290001Sglebius * \brief Compact the used region by moving the remaining region so it occurs
440290001Sglebius * at the start of the buffer.  The used region is shrunk by the size of
441290001Sglebius * the consumed region, and the consumed region is then made empty.
442290001Sglebius *
443290001Sglebius * Requires:
444290001Sglebius *
445290001Sglebius *\li	'b' is a valid buffer
446290001Sglebius *
447290001Sglebius * Ensures:
448290001Sglebius *
449290001Sglebius *\li	current == 0
450290001Sglebius *
451290001Sglebius *\li	The size of the used region is now equal to the size of the remaining
452290001Sglebius *	region (as it was before the call).  The contents of the used region
453290001Sglebius *	are those of the remaining region (as it was before the call).
454290001Sglebius */
455290001Sglebius
456290001Sglebiusisc_uint8_t
457290001Sglebiusisc_buffer_getuint8(isc_buffer_t *b);
458290001Sglebius/*!<
459290001Sglebius * \brief Read an unsigned 8-bit integer from 'b' and return it.
460290001Sglebius *
461290001Sglebius * Requires:
462290001Sglebius *
463290001Sglebius *\li	'b' is a valid buffer.
464290001Sglebius *
465290001Sglebius *\li	The length of the available region of 'b' is at least 1.
466290001Sglebius *
467290001Sglebius * Ensures:
468290001Sglebius *
469290001Sglebius *\li	The current pointer in 'b' is advanced by 1.
470290001Sglebius *
471290001Sglebius * Returns:
472290001Sglebius *
473290001Sglebius *\li	A 8-bit unsigned integer.
474290001Sglebius */
475290001Sglebius
476290001Sglebiusvoid
477290001Sglebiusisc__buffer_putuint8(isc_buffer_t *b, isc_uint8_t val);
478290001Sglebius/*!<
479290001Sglebius * \brief Store an unsigned 8-bit integer from 'val' into 'b'.
480290001Sglebius *
481290001Sglebius * Requires:
482290001Sglebius *\li	'b' is a valid buffer.
483290001Sglebius *
484290001Sglebius *\li	The length of the unused region of 'b' is at least 1.
485290001Sglebius *
486290001Sglebius * Ensures:
487290001Sglebius *\li	The used pointer in 'b' is advanced by 1.
488290001Sglebius */
489290001Sglebius
490290001Sglebiusisc_uint16_t
491290001Sglebiusisc_buffer_getuint16(isc_buffer_t *b);
492290001Sglebius/*!<
493290001Sglebius * \brief Read an unsigned 16-bit integer in network byte order from 'b', convert
494290001Sglebius * it to host byte order, and return it.
495290001Sglebius *
496290001Sglebius * Requires:
497290001Sglebius *
498290001Sglebius *\li	'b' is a valid buffer.
499290001Sglebius *
500290001Sglebius *\li	The length of the available region of 'b' is at least 2.
501290001Sglebius *
502290001Sglebius * Ensures:
503290001Sglebius *
504290001Sglebius *\li	The current pointer in 'b' is advanced by 2.
505290001Sglebius *
506290001Sglebius * Returns:
507290001Sglebius *
508290001Sglebius *\li	A 16-bit unsigned integer.
509290001Sglebius */
510290001Sglebius
511290001Sglebiusvoid
512290001Sglebiusisc__buffer_putuint16(isc_buffer_t *b, isc_uint16_t val);
513290001Sglebius/*!<
514290001Sglebius * \brief Store an unsigned 16-bit integer in host byte order from 'val'
515290001Sglebius * into 'b' in network byte order.
516290001Sglebius *
517290001Sglebius * Requires:
518290001Sglebius *\li	'b' is a valid buffer.
519290001Sglebius *
520290001Sglebius *\li	The length of the unused region of 'b' is at least 2.
521290001Sglebius *
522290001Sglebius * Ensures:
523290001Sglebius *\li	The used pointer in 'b' is advanced by 2.
524290001Sglebius */
525290001Sglebius
526290001Sglebiusisc_uint32_t
527290001Sglebiusisc_buffer_getuint32(isc_buffer_t *b);
528290001Sglebius/*!<
529290001Sglebius * \brief Read an unsigned 32-bit integer in network byte order from 'b', convert
530290001Sglebius * it to host byte order, and return it.
531290001Sglebius *
532290001Sglebius * Requires:
533290001Sglebius *
534290001Sglebius *\li	'b' is a valid buffer.
535290001Sglebius *
536290001Sglebius *\li	The length of the available region of 'b' is at least 4.
537290001Sglebius *
538290001Sglebius * Ensures:
539290001Sglebius *
540290001Sglebius *\li	The current pointer in 'b' is advanced by 4.
541290001Sglebius *
542290001Sglebius * Returns:
543290001Sglebius *
544290001Sglebius *\li	A 32-bit unsigned integer.
545290001Sglebius */
546290001Sglebius
547290001Sglebiusvoid
548290001Sglebiusisc__buffer_putuint32(isc_buffer_t *b, isc_uint32_t val);
549290001Sglebius/*!<
550290001Sglebius * \brief Store an unsigned 32-bit integer in host byte order from 'val'
551290001Sglebius * into 'b' in network byte order.
552290001Sglebius *
553290001Sglebius * Requires:
554290001Sglebius *\li	'b' is a valid buffer.
555290001Sglebius *
556290001Sglebius *\li	The length of the unused region of 'b' is at least 4.
557290001Sglebius *
558290001Sglebius * Ensures:
559290001Sglebius *\li	The used pointer in 'b' is advanced by 4.
560290001Sglebius */
561290001Sglebius
562290001Sglebiusisc_uint64_t
563290001Sglebiusisc_buffer_getuint48(isc_buffer_t *b);
564290001Sglebius/*!<
565290001Sglebius * \brief Read an unsigned 48-bit integer in network byte order from 'b',
566290001Sglebius * convert it to host byte order, and return it.
567290001Sglebius *
568290001Sglebius * Requires:
569290001Sglebius *
570290001Sglebius *\li	'b' is a valid buffer.
571290001Sglebius *
572290001Sglebius *\li	The length of the available region of 'b' is at least 6.
573290001Sglebius *
574290001Sglebius * Ensures:
575290001Sglebius *
576290001Sglebius *\li	The current pointer in 'b' is advanced by 6.
577290001Sglebius *
578290001Sglebius * Returns:
579290001Sglebius *
580290001Sglebius *\li	A 48-bit unsigned integer (stored in a 64-bit integer).
581290001Sglebius */
582290001Sglebius
583290001Sglebiusvoid
584290001Sglebiusisc__buffer_putuint48(isc_buffer_t *b, isc_uint64_t val);
585290001Sglebius/*!<
586290001Sglebius * \brief Store an unsigned 48-bit integer in host byte order from 'val'
587290001Sglebius * into 'b' in network byte order.
588290001Sglebius *
589290001Sglebius * Requires:
590290001Sglebius *\li	'b' is a valid buffer.
591290001Sglebius *
592290001Sglebius *\li	The length of the unused region of 'b' is at least 6.
593290001Sglebius *
594290001Sglebius * Ensures:
595290001Sglebius *\li	The used pointer in 'b' is advanced by 6.
596290001Sglebius */
597290001Sglebius
598290001Sglebiusvoid
599290001Sglebiusisc__buffer_putuint24(isc_buffer_t *b, isc_uint32_t val);
600290001Sglebius/*!<
601290001Sglebius * Store an unsigned 24-bit integer in host byte order from 'val'
602290001Sglebius * into 'b' in network byte order.
603290001Sglebius *
604290001Sglebius * Requires:
605290001Sglebius *\li	'b' is a valid buffer.
606290001Sglebius *
607290001Sglebius *	The length of the unused region of 'b' is at least 3.
608290001Sglebius *
609290001Sglebius * Ensures:
610290001Sglebius *\li	The used pointer in 'b' is advanced by 3.
611290001Sglebius */
612290001Sglebius
613290001Sglebiusvoid
614290001Sglebiusisc__buffer_putmem(isc_buffer_t *b, const unsigned char *base,
615290001Sglebius		   unsigned int length);
616290001Sglebius/*!<
617290001Sglebius * \brief Copy 'length' bytes of memory at 'base' into 'b'.
618290001Sglebius *
619290001Sglebius * Requires:
620290001Sglebius *\li	'b' is a valid buffer.
621290001Sglebius *
622290001Sglebius *\li	'base' points to 'length' bytes of valid memory.
623290001Sglebius *
624290001Sglebius */
625290001Sglebius
626290001Sglebiusvoid
627290001Sglebiusisc__buffer_putstr(isc_buffer_t *b, const char *source);
628290001Sglebius/*!<
629290001Sglebius * \brief Copy 'source' into 'b', not including terminating NUL.
630290001Sglebius *
631290001Sglebius * Requires:
632290001Sglebius *\li	'b' is a valid buffer.
633290001Sglebius *
634290001Sglebius *\li	'source' to be a valid NULL terminated string.
635290001Sglebius *
636290001Sglebius *\li	strlen(source) <= isc_buffer_available(b)
637290001Sglebius */
638290001Sglebius
639290001Sglebiusisc_result_t
640290001Sglebiusisc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r);
641290001Sglebius/*!<
642290001Sglebius * \brief Copy the contents of 'r' into 'b'.
643290001Sglebius *
644290001Sglebius * Requires:
645290001Sglebius *\li	'b' is a valid buffer.
646290001Sglebius *
647290001Sglebius *\li	'r' is a valid region.
648290001Sglebius *
649290001Sglebius * Returns:
650290001Sglebius *
651290001Sglebius *\li	ISC_R_SUCCESS
652290001Sglebius *\li	ISC_R_NOSPACE			The available region of 'b' is not
653290001Sglebius *					big enough.
654290001Sglebius */
655290001Sglebius
656290001SglebiusISC_LANG_ENDDECLS
657290001Sglebius
658290001Sglebius/*
659290001Sglebius * Inline macro versions of the functions.  These should never be called
660290001Sglebius * directly by an application, but will be used by the functions within
661290001Sglebius * buffer.c.  The callers should always use "isc_buffer_*()" names, never
662290001Sglebius * ones beginning with "isc__"
663290001Sglebius */
664290001Sglebius
665290001Sglebius/*! \note
666290001Sglebius * XXXDCL Something more could be done with initializing buffers that
667290001Sglebius * point to const data.  For example, a new function, isc_buffer_initconst,
668290001Sglebius * could be used, and a new boolean flag in the buffer structure could
669290001Sglebius * indicate whether the buffer was initialized with that function.
670290001Sglebius * (isc_bufer_init itself would be reprototyped to *not* have its "base"
671290001Sglebius * parameter be const.)  Then if the boolean were true, the isc_buffer_put*
672290001Sglebius * functions could assert a contractual requirement for a non-const buffer.
673290001Sglebius * One drawback is that the isc_buffer_* functions (macros) that return
674290001Sglebius * pointers would still need to return non-const pointers to avoid compiler
675290001Sglebius * warnings, so it would be up to code that uses them to have to deal
676290001Sglebius * with the possibility that the buffer was initialized as const --
677290001Sglebius * a problem that they *already* have to deal with but have absolutely
678290001Sglebius * no ability to.  With a new isc_buffer_isconst() function returning
679290001Sglebius * true/false, they could at least assert a contractual requirement for
680290001Sglebius * non-const buffers when needed.
681290001Sglebius */
682290001Sglebius#define ISC__BUFFER_INIT(_b, _base, _length) \
683290001Sglebius	do { \
684290001Sglebius		union { \
685290001Sglebius			const void *	konst; \
686290001Sglebius			void *		var; \
687290001Sglebius		} _u; \
688290001Sglebius		_u.konst = (_base); \
689290001Sglebius		(_b)->base = _u.var; \
690290001Sglebius		(_b)->length = (_length); \
691290001Sglebius		(_b)->used = 0; \
692290001Sglebius		(_b)->current = 0; \
693290001Sglebius		(_b)->active = 0; \
694290001Sglebius		(_b)->mctx = NULL; \
695290001Sglebius		ISC_LINK_INIT(_b, link); \
696290001Sglebius		(_b)->magic = ISC_BUFFER_MAGIC; \
697290001Sglebius	} while (0)
698290001Sglebius
699290001Sglebius#define ISC__BUFFER_INITNULL(_b) ISC__BUFFER_INIT(_b, NULL, 0)
700290001Sglebius
701290001Sglebius#define ISC__BUFFER_INVALIDATE(_b) \
702290001Sglebius	do { \
703290001Sglebius		(_b)->magic = 0; \
704290001Sglebius		(_b)->base = NULL; \
705290001Sglebius		(_b)->length = 0; \
706290001Sglebius		(_b)->used = 0; \
707290001Sglebius		(_b)->current = 0; \
708290001Sglebius		(_b)->active = 0; \
709290001Sglebius	} while (0)
710290001Sglebius
711290001Sglebius#define ISC__BUFFER_REGION(_b, _r) \
712290001Sglebius	do { \
713290001Sglebius		(_r)->base = (_b)->base; \
714290001Sglebius		(_r)->length = (_b)->length; \
715290001Sglebius	} while (0)
716290001Sglebius
717290001Sglebius#define ISC__BUFFER_USEDREGION(_b, _r) \
718290001Sglebius	do { \
719290001Sglebius		(_r)->base = (_b)->base; \
720290001Sglebius		(_r)->length = (_b)->used; \
721290001Sglebius	} while (0)
722290001Sglebius
723290001Sglebius#define ISC__BUFFER_AVAILABLEREGION(_b, _r) \
724290001Sglebius	do { \
725290001Sglebius		(_r)->base = isc_buffer_used(_b); \
726290001Sglebius		(_r)->length = isc_buffer_availablelength(_b); \
727290001Sglebius	} while (0)
728290001Sglebius
729290001Sglebius#define ISC__BUFFER_ADD(_b, _n) \
730290001Sglebius	do { \
731290001Sglebius		(_b)->used += (_n); \
732290001Sglebius	} while (0)
733290001Sglebius
734290001Sglebius#define ISC__BUFFER_SUBTRACT(_b, _n) \
735290001Sglebius	do { \
736290001Sglebius		(_b)->used -= (_n); \
737290001Sglebius		if ((_b)->current > (_b)->used) \
738290001Sglebius			(_b)->current = (_b)->used; \
739290001Sglebius		if ((_b)->active > (_b)->used) \
740290001Sglebius			(_b)->active = (_b)->used; \
741290001Sglebius	} while (0)
742290001Sglebius
743290001Sglebius#define ISC__BUFFER_CLEAR(_b) \
744290001Sglebius	do { \
745290001Sglebius		(_b)->used = 0; \
746290001Sglebius		(_b)->current = 0; \
747290001Sglebius		(_b)->active = 0; \
748290001Sglebius	} while (0)
749290001Sglebius
750290001Sglebius#define ISC__BUFFER_CONSUMEDREGION(_b, _r) \
751290001Sglebius	do { \
752290001Sglebius		(_r)->base = (_b)->base; \
753290001Sglebius		(_r)->length = (_b)->current; \
754290001Sglebius	} while (0)
755290001Sglebius
756290001Sglebius#define ISC__BUFFER_REMAININGREGION(_b, _r) \
757290001Sglebius	do { \
758290001Sglebius		(_r)->base = isc_buffer_current(_b); \
759290001Sglebius		(_r)->length = isc_buffer_remaininglength(_b); \
760290001Sglebius	} while (0)
761290001Sglebius
762290001Sglebius#define ISC__BUFFER_ACTIVEREGION(_b, _r) \
763290001Sglebius	do { \
764290001Sglebius		if ((_b)->current < (_b)->active) { \
765290001Sglebius			(_r)->base = isc_buffer_current(_b); \
766290001Sglebius			(_r)->length = isc_buffer_activelength(_b); \
767290001Sglebius		} else { \
768290001Sglebius			(_r)->base = NULL; \
769290001Sglebius			(_r)->length = 0; \
770290001Sglebius		} \
771290001Sglebius	} while (0)
772290001Sglebius
773290001Sglebius#define ISC__BUFFER_SETACTIVE(_b, _n) \
774290001Sglebius	do { \
775290001Sglebius		(_b)->active = (_b)->current + (_n); \
776290001Sglebius	} while (0)
777290001Sglebius
778290001Sglebius#define ISC__BUFFER_FIRST(_b) \
779290001Sglebius	do { \
780290001Sglebius		(_b)->current = 0; \
781290001Sglebius	} while (0)
782290001Sglebius
783290001Sglebius#define ISC__BUFFER_FORWARD(_b, _n) \
784290001Sglebius	do { \
785290001Sglebius		(_b)->current += (_n); \
786290001Sglebius	} while (0)
787290001Sglebius
788290001Sglebius#define ISC__BUFFER_BACK(_b, _n) \
789290001Sglebius	do { \
790290001Sglebius		(_b)->current -= (_n); \
791290001Sglebius	} while (0)
792290001Sglebius
793290001Sglebius#define ISC__BUFFER_PUTMEM(_b, _base, _length) \
794290001Sglebius	do { \
795290001Sglebius		memcpy(isc_buffer_used(_b), (_base), (_length)); \
796290001Sglebius		(_b)->used += (_length); \
797290001Sglebius	} while (0)
798290001Sglebius
799290001Sglebius#define ISC__BUFFER_PUTSTR(_b, _source) \
800290001Sglebius	do { \
801290001Sglebius		unsigned int _length; \
802290001Sglebius		unsigned char *_cp; \
803290001Sglebius		_length = strlen(_source); \
804290001Sglebius		_cp = isc_buffer_used(_b); \
805290001Sglebius		memcpy(_cp, (_source), _length); \
806290001Sglebius		(_b)->used += (_length); \
807290001Sglebius	} while (0)
808290001Sglebius
809290001Sglebius#define ISC__BUFFER_PUTUINT8(_b, _val) \
810290001Sglebius	do { \
811290001Sglebius		unsigned char *_cp; \
812290001Sglebius		isc_uint8_t _val2 = (_val); \
813290001Sglebius		_cp = isc_buffer_used(_b); \
814290001Sglebius		(_b)->used++; \
815290001Sglebius		_cp[0] = _val2 & 0x00ff; \
816290001Sglebius	} while (0)
817290001Sglebius
818290001Sglebius#define ISC__BUFFER_PUTUINT16(_b, _val) \
819290001Sglebius	do { \
820290001Sglebius		unsigned char *_cp; \
821290001Sglebius		isc_uint16_t _val2 = (_val); \
822290001Sglebius		_cp = isc_buffer_used(_b); \
823290001Sglebius		(_b)->used += 2; \
824290001Sglebius		_cp[0] = (unsigned char)((_val2 & 0xff00U) >> 8); \
825290001Sglebius		_cp[1] = (unsigned char)(_val2 & 0x00ffU); \
826290001Sglebius	} while (0)
827290001Sglebius
828290001Sglebius#define ISC__BUFFER_PUTUINT24(_b, _val) \
829290001Sglebius	do { \
830290001Sglebius		unsigned char *_cp; \
831290001Sglebius		isc_uint32_t _val2 = (_val); \
832290001Sglebius		_cp = isc_buffer_used(_b); \
833290001Sglebius		(_b)->used += 3; \
834290001Sglebius		_cp[0] = (unsigned char)((_val2 & 0xff0000U) >> 16); \
835290001Sglebius		_cp[1] = (unsigned char)((_val2 & 0xff00U) >> 8); \
836290001Sglebius		_cp[2] = (unsigned char)(_val2 & 0x00ffU); \
837290001Sglebius	} while (0)
838290001Sglebius
839290001Sglebius#define ISC__BUFFER_PUTUINT32(_b, _val) \
840290001Sglebius	do { \
841290001Sglebius		unsigned char *_cp; \
842290001Sglebius		isc_uint32_t _val2 = (_val); \
843290001Sglebius		_cp = isc_buffer_used(_b); \
844290001Sglebius		(_b)->used += 4; \
845290001Sglebius		_cp[0] = (unsigned char)((_val2 & 0xff000000) >> 24); \
846290001Sglebius		_cp[1] = (unsigned char)((_val2 & 0x00ff0000) >> 16); \
847290001Sglebius		_cp[2] = (unsigned char)((_val2 & 0x0000ff00) >> 8); \
848290001Sglebius		_cp[3] = (unsigned char)((_val2 & 0x000000ff)); \
849290001Sglebius	} while (0)
850290001Sglebius
851290001Sglebius#if defined(ISC_BUFFER_USEINLINE)
852290001Sglebius#define isc_buffer_init			ISC__BUFFER_INIT
853290001Sglebius#define isc_buffer_initnull		ISC__BUFFER_INITNULL
854290001Sglebius#define isc_buffer_invalidate		ISC__BUFFER_INVALIDATE
855290001Sglebius#define isc_buffer_region		ISC__BUFFER_REGION
856290001Sglebius#define isc_buffer_usedregion		ISC__BUFFER_USEDREGION
857290001Sglebius#define isc_buffer_availableregion	ISC__BUFFER_AVAILABLEREGION
858290001Sglebius#define isc_buffer_add			ISC__BUFFER_ADD
859290001Sglebius#define isc_buffer_subtract		ISC__BUFFER_SUBTRACT
860290001Sglebius#define isc_buffer_clear		ISC__BUFFER_CLEAR
861290001Sglebius#define isc_buffer_consumedregion	ISC__BUFFER_CONSUMEDREGION
862290001Sglebius#define isc_buffer_remainingregion	ISC__BUFFER_REMAININGREGION
863290001Sglebius#define isc_buffer_activeregion		ISC__BUFFER_ACTIVEREGION
864290001Sglebius#define isc_buffer_setactive		ISC__BUFFER_SETACTIVE
865290001Sglebius#define isc_buffer_first		ISC__BUFFER_FIRST
866290001Sglebius#define isc_buffer_forward		ISC__BUFFER_FORWARD
867290001Sglebius#define isc_buffer_back			ISC__BUFFER_BACK
868290001Sglebius#define isc_buffer_putmem		ISC__BUFFER_PUTMEM
869290001Sglebius#define isc_buffer_putstr		ISC__BUFFER_PUTSTR
870290001Sglebius#define isc_buffer_putuint8		ISC__BUFFER_PUTUINT8
871290001Sglebius#define isc_buffer_putuint16		ISC__BUFFER_PUTUINT16
872290001Sglebius#define isc_buffer_putuint24		ISC__BUFFER_PUTUINT24
873290001Sglebius#define isc_buffer_putuint32		ISC__BUFFER_PUTUINT32
874290001Sglebius#else
875290001Sglebius#define isc_buffer_init			isc__buffer_init
876290001Sglebius#define isc_buffer_initnull		isc__buffer_initnull
877290001Sglebius#define isc_buffer_invalidate		isc__buffer_invalidate
878290001Sglebius#define isc_buffer_region		isc__buffer_region
879290001Sglebius#define isc_buffer_usedregion		isc__buffer_usedregion
880290001Sglebius#define isc_buffer_availableregion	isc__buffer_availableregion
881290001Sglebius#define isc_buffer_add			isc__buffer_add
882290001Sglebius#define isc_buffer_subtract		isc__buffer_subtract
883290001Sglebius#define isc_buffer_clear		isc__buffer_clear
884290001Sglebius#define isc_buffer_consumedregion	isc__buffer_consumedregion
885290001Sglebius#define isc_buffer_remainingregion	isc__buffer_remainingregion
886290001Sglebius#define isc_buffer_activeregion		isc__buffer_activeregion
887290001Sglebius#define isc_buffer_setactive		isc__buffer_setactive
888290001Sglebius#define isc_buffer_first		isc__buffer_first
889290001Sglebius#define isc_buffer_forward		isc__buffer_forward
890290001Sglebius#define isc_buffer_back			isc__buffer_back
891290001Sglebius#define isc_buffer_putmem		isc__buffer_putmem
892290001Sglebius#define isc_buffer_putstr		isc__buffer_putstr
893290001Sglebius#define isc_buffer_putuint8		isc__buffer_putuint8
894290001Sglebius#define isc_buffer_putuint16		isc__buffer_putuint16
895290001Sglebius#define isc_buffer_putuint24		isc__buffer_putuint24
896290001Sglebius#define isc_buffer_putuint32		isc__buffer_putuint32
897290001Sglebius#endif
898290001Sglebius
899290001Sglebius/*
900290001Sglebius * No inline method for this one (yet).
901290001Sglebius */
902290001Sglebius#define isc_buffer_putuint48		isc__buffer_putuint48
903290001Sglebius
904290001Sglebius#endif /* ISC_BUFFER_H */
905