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