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