1 /* 2 * buffer.h -- generic memory buffer. 3 * 4 * Copyright (c) 2005-2008, NLnet Labs. All rights reserved. 5 * 6 * See LICENSE for the license. 7 * 8 * 9 * The buffer module implements a generic buffer. The API is based on 10 * the java.nio.Buffer interface. 11 */ 12 13 #ifndef LDNS_BUFFER_H 14 #define LDNS_BUFFER_H 15 16 #include <assert.h> 17 #include <stdarg.h> 18 #include <string.h> 19 20 #include <ldns/error.h> 21 #include <ldns/common.h> 22 23 #include "ldns/util.h" 24 25 /** 26 * number of initial bytes in buffer of 27 * which we cannot tell the size before hand 28 */ 29 #define LDNS_MIN_BUFLEN 512 30 31 /** 32 * \file buffer.h 33 * 34 * This file contains the definition of ldns_buffer, and functions to manipulate those. 35 */ 36 37 /** 38 * implementation of buffers to ease operations 39 * 40 * ldns_buffers can contain arbitrary information, per octet. You can write 41 * to the current end of a buffer, read from the current position, and 42 * access any data within it. 43 * 44 * Example use of buffers is in the source code of \ref host2str.c 45 */ 46 struct ldns_struct_buffer 47 { 48 /** The current position used for reading/writing */ 49 size_t _position; 50 51 /** The read/write limit */ 52 size_t _limit; 53 54 /** The amount of data the buffer can contain */ 55 size_t _capacity; 56 57 /** The data contained in the buffer */ 58 uint8_t *_data; 59 60 /** If the buffer is fixed it cannot be resized */ 61 unsigned _fixed : 1; 62 63 /** The current state of the buffer. If writing to the buffer fails 64 * for any reason, this value is changed. This way, you can perform 65 * multiple writes in sequence and check for success afterwards. */ 66 ldns_status _status; 67 }; 68 typedef struct ldns_struct_buffer ldns_buffer; 69 70 71 #ifdef NDEBUG 72 INLINE void 73 ldns_buffer_invariant(ldns_buffer *ATTR_UNUSED(buffer)) 74 { 75 } 76 #else 77 INLINE void 78 ldns_buffer_invariant(ldns_buffer *buffer) 79 { 80 assert(buffer != NULL); 81 assert(buffer->_position <= buffer->_limit); 82 assert(buffer->_limit <= buffer->_capacity); 83 assert(buffer->_data != NULL); 84 } 85 #endif 86 87 /** 88 * creates a new buffer with the specified capacity. 89 * 90 * \param[in] capacity the size (in bytes) to allocate for the buffer 91 * \return the created buffer 92 */ 93 ldns_buffer *ldns_buffer_new(size_t capacity); 94 95 /** 96 * creates a buffer with the specified data. The data IS copied 97 * and MEMORY allocations are done. The buffer is not fixed and can 98 * be resized using buffer_reserve(). 99 * 100 * \param[in] buffer pointer to the buffer to put the data in 101 * \param[in] data the data to encapsulate in the buffer 102 * \param[in] size the size of the data 103 */ 104 void ldns_buffer_new_frm_data(ldns_buffer *buffer, void *data, size_t size); 105 106 /** 107 * clears the buffer and make it ready for writing. The buffer's limit 108 * is set to the capacity and the position is set to 0. 109 * \param[in] buffer the buffer to clear 110 */ 111 INLINE void ldns_buffer_clear(ldns_buffer *buffer) 112 { 113 ldns_buffer_invariant(buffer); 114 115 /* reset status here? */ 116 117 buffer->_position = 0; 118 buffer->_limit = buffer->_capacity; 119 } 120 121 /** 122 * makes the buffer ready for reading the data that has been written to 123 * the buffer. The buffer's limit is set to the current position and 124 * the position is set to 0. 125 * 126 * \param[in] buffer the buffer to flip 127 * \return void 128 */ 129 INLINE void ldns_buffer_flip(ldns_buffer *buffer) 130 { 131 ldns_buffer_invariant(buffer); 132 133 buffer->_limit = buffer->_position; 134 buffer->_position = 0; 135 } 136 137 /** 138 * make the buffer ready for re-reading the data. The buffer's 139 * position is reset to 0. 140 * \param[in] buffer the buffer to rewind 141 */ 142 INLINE void ldns_buffer_rewind(ldns_buffer *buffer) 143 { 144 ldns_buffer_invariant(buffer); 145 146 buffer->_position = 0; 147 } 148 149 /** 150 * returns the current position in the buffer (as a number of bytes) 151 * \param[in] buffer the buffer 152 * \return the current position 153 */ 154 INLINE size_t 155 ldns_buffer_position(ldns_buffer *buffer) 156 { 157 return buffer->_position; 158 } 159 160 /** 161 * sets the buffer's position to MARK. The position must be less than 162 * or equal to the buffer's limit. 163 * \param[in] buffer the buffer 164 * \param[in] mark the mark to use 165 */ 166 INLINE void 167 ldns_buffer_set_position(ldns_buffer *buffer, size_t mark) 168 { 169 assert(mark <= buffer->_limit); 170 buffer->_position = mark; 171 } 172 173 /** 174 * changes the buffer's position by COUNT bytes. The position must not 175 * be moved behind the buffer's limit or before the beginning of the 176 * buffer. 177 * \param[in] buffer the buffer 178 * \param[in] count the count to use 179 */ 180 INLINE void 181 ldns_buffer_skip(ldns_buffer *buffer, ssize_t count) 182 { 183 assert(buffer->_position + count <= buffer->_limit); 184 buffer->_position += count; 185 } 186 187 /** 188 * returns the maximum size of the buffer 189 * \param[in] buffer 190 * \return the size 191 */ 192 INLINE size_t 193 ldns_buffer_limit(ldns_buffer *buffer) 194 { 195 return buffer->_limit; 196 } 197 198 /** 199 * changes the buffer's limit. If the buffer's position is greater 200 * than the new limit the position is set to the limit. 201 * \param[in] buffer the buffer 202 * \param[in] limit the new limit 203 */ 204 INLINE void 205 ldns_buffer_set_limit(ldns_buffer *buffer, size_t limit) 206 { 207 assert(limit <= buffer->_capacity); 208 buffer->_limit = limit; 209 if (buffer->_position > buffer->_limit) 210 buffer->_position = buffer->_limit; 211 } 212 213 /** 214 * returns the number of bytes the buffer can hold. 215 * \param[in] buffer the buffer 216 * \return the number of bytes 217 */ 218 INLINE size_t 219 ldns_buffer_capacity(ldns_buffer *buffer) 220 { 221 return buffer->_capacity; 222 } 223 224 /** 225 * changes the buffer's capacity. The data is reallocated so any 226 * pointers to the data may become invalid. The buffer's limit is set 227 * to the buffer's new capacity. 228 * \param[in] buffer the buffer 229 * \param[in] capacity the capacity to use 230 * \return whether this failed or succeeded 231 */ 232 bool ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity); 233 234 /** 235 * ensures BUFFER can contain at least AMOUNT more bytes. The buffer's 236 * capacity is increased if necessary using buffer_set_capacity(). 237 * 238 * The buffer's limit is always set to the (possibly increased) 239 * capacity. 240 * \param[in] buffer the buffer 241 * \param[in] amount amount to use 242 * \return whether this failed or succeeded 243 */ 244 bool ldns_buffer_reserve(ldns_buffer *buffer, size_t amount); 245 246 /** 247 * returns a pointer to the data at the indicated position. 248 * \param[in] buffer the buffer 249 * \param[in] at position 250 * \return the pointer to the data 251 */ 252 INLINE uint8_t * 253 ldns_buffer_at(const ldns_buffer *buffer, size_t at) 254 { 255 assert(at <= buffer->_limit); 256 return buffer->_data + at; 257 } 258 259 /** 260 * returns a pointer to the beginning of the buffer (the data at 261 * position 0). 262 * \param[in] buffer the buffer 263 * \return the pointer 264 */ 265 INLINE uint8_t * 266 ldns_buffer_begin(const ldns_buffer *buffer) 267 { 268 return ldns_buffer_at(buffer, 0); 269 } 270 271 /** 272 * returns a pointer to the end of the buffer (the data at the buffer's 273 * limit). 274 * \param[in] buffer the buffer 275 * \return the pointer 276 */ 277 INLINE uint8_t * 278 ldns_buffer_end(ldns_buffer *buffer) 279 { 280 return ldns_buffer_at(buffer, buffer->_limit); 281 } 282 283 /** 284 * returns a pointer to the data at the buffer's current position. 285 * \param[in] buffer the buffer 286 * \return the pointer 287 */ 288 INLINE uint8_t * 289 ldns_buffer_current(ldns_buffer *buffer) 290 { 291 return ldns_buffer_at(buffer, buffer->_position); 292 } 293 294 /** 295 * returns the number of bytes remaining between the indicated position and 296 * the limit. 297 * \param[in] buffer the buffer 298 * \param[in] at indicated position 299 * \return number of bytes 300 */ 301 INLINE size_t 302 ldns_buffer_remaining_at(ldns_buffer *buffer, size_t at) 303 { 304 ldns_buffer_invariant(buffer); 305 assert(at <= buffer->_limit); 306 return buffer->_limit - at; 307 } 308 309 /** 310 * returns the number of bytes remaining between the buffer's position and 311 * limit. 312 * \param[in] buffer the buffer 313 * \return the number of bytes 314 */ 315 INLINE size_t 316 ldns_buffer_remaining(ldns_buffer *buffer) 317 { 318 return ldns_buffer_remaining_at(buffer, buffer->_position); 319 } 320 321 /** 322 * checks if the buffer has at least COUNT more bytes available. 323 * Before reading or writing the caller needs to ensure enough space 324 * is available! 325 * \param[in] buffer the buffer 326 * \param[in] at indicated position 327 * \param[in] count how much is available 328 * \return true or false (as int?) 329 */ 330 INLINE int 331 ldns_buffer_available_at(ldns_buffer *buffer, size_t at, size_t count) 332 { 333 return count <= ldns_buffer_remaining_at(buffer, at); 334 } 335 336 /** 337 * checks if the buffer has count bytes available at the current position 338 * \param[in] buffer the buffer 339 * \param[in] count how much is available 340 * \return true or false (as int?) 341 */ 342 INLINE int 343 ldns_buffer_available(ldns_buffer *buffer, size_t count) 344 { 345 return ldns_buffer_available_at(buffer, buffer->_position, count); 346 } 347 348 /** 349 * writes the given data to the buffer at the specified position 350 * \param[in] buffer the buffer 351 * \param[in] at the position (in number of bytes) to write the data at 352 * \param[in] data pointer to the data to write to the buffer 353 * \param[in] count the number of bytes of data to write 354 */ 355 INLINE void 356 ldns_buffer_write_at(ldns_buffer *buffer, size_t at, const void *data, size_t count) 357 { 358 assert(ldns_buffer_available_at(buffer, at, count)); 359 memcpy(buffer->_data + at, data, count); 360 } 361 362 /** 363 * writes count bytes of data to the current position of the buffer 364 * \param[in] buffer the buffer 365 * \param[in] data the data to write 366 * \param[in] count the lenght of the data to write 367 */ 368 INLINE void 369 ldns_buffer_write(ldns_buffer *buffer, const void *data, size_t count) 370 { 371 ldns_buffer_write_at(buffer, buffer->_position, data, count); 372 buffer->_position += count; 373 } 374 375 /** 376 * copies the given (null-delimited) string to the specified position at the buffer 377 * \param[in] buffer the buffer 378 * \param[in] at the position in the buffer 379 * \param[in] str the string to write 380 */ 381 INLINE void 382 ldns_buffer_write_string_at(ldns_buffer *buffer, size_t at, const char *str) 383 { 384 ldns_buffer_write_at(buffer, at, str, strlen(str)); 385 } 386 387 /** 388 * copies the given (null-delimited) string to the current position at the buffer 389 * \param[in] buffer the buffer 390 * \param[in] str the string to write 391 */ 392 INLINE void 393 ldns_buffer_write_string(ldns_buffer *buffer, const char *str) 394 { 395 ldns_buffer_write(buffer, str, strlen(str)); 396 } 397 398 /** 399 * writes the given byte of data at the given position in the buffer 400 * \param[in] buffer the buffer 401 * \param[in] at the position in the buffer 402 * \param[in] data the 8 bits to write 403 */ 404 INLINE void 405 ldns_buffer_write_u8_at(ldns_buffer *buffer, size_t at, uint8_t data) 406 { 407 assert(ldns_buffer_available_at(buffer, at, sizeof(data))); 408 buffer->_data[at] = data; 409 } 410 411 /** 412 * writes the given byte of data at the current position in the buffer 413 * \param[in] buffer the buffer 414 * \param[in] data the 8 bits to write 415 */ 416 INLINE void 417 ldns_buffer_write_u8(ldns_buffer *buffer, uint8_t data) 418 { 419 ldns_buffer_write_u8_at(buffer, buffer->_position, data); 420 buffer->_position += sizeof(data); 421 } 422 423 /** 424 * writes the given 2 byte integer at the given position in the buffer 425 * \param[in] buffer the buffer 426 * \param[in] at the position in the buffer 427 * \param[in] data the 16 bits to write 428 */ 429 INLINE void 430 ldns_buffer_write_u16_at(ldns_buffer *buffer, size_t at, uint16_t data) 431 { 432 assert(ldns_buffer_available_at(buffer, at, sizeof(data))); 433 ldns_write_uint16(buffer->_data + at, data); 434 } 435 436 /** 437 * writes the given 2 byte integer at the current position in the buffer 438 * \param[in] buffer the buffer 439 * \param[in] data the 16 bits to write 440 */ 441 INLINE void 442 ldns_buffer_write_u16(ldns_buffer *buffer, uint16_t data) 443 { 444 ldns_buffer_write_u16_at(buffer, buffer->_position, data); 445 buffer->_position += sizeof(data); 446 } 447 448 /** 449 * writes the given 4 byte integer at the given position in the buffer 450 * \param[in] buffer the buffer 451 * \param[in] at the position in the buffer 452 * \param[in] data the 32 bits to write 453 */ 454 INLINE void 455 ldns_buffer_write_u32_at(ldns_buffer *buffer, size_t at, uint32_t data) 456 { 457 assert(ldns_buffer_available_at(buffer, at, sizeof(data))); 458 ldns_write_uint32(buffer->_data + at, data); 459 } 460 461 /** 462 * writes the given 4 byte integer at the current position in the buffer 463 * \param[in] buffer the buffer 464 * \param[in] data the 32 bits to write 465 */ 466 INLINE void 467 ldns_buffer_write_u32(ldns_buffer *buffer, uint32_t data) 468 { 469 ldns_buffer_write_u32_at(buffer, buffer->_position, data); 470 buffer->_position += sizeof(data); 471 } 472 473 /** 474 * copies count bytes of data at the given position to the given data-array 475 * \param[in] buffer the buffer 476 * \param[in] at the position in the buffer to start 477 * \param[out] data buffer to copy to 478 * \param[in] count the length of the data to copy 479 */ 480 INLINE void 481 ldns_buffer_read_at(ldns_buffer *buffer, size_t at, void *data, size_t count) 482 { 483 assert(ldns_buffer_available_at(buffer, at, count)); 484 memcpy(data, buffer->_data + at, count); 485 } 486 487 /** 488 * copies count bytes of data at the current position to the given data-array 489 * \param[in] buffer the buffer 490 * \param[out] data buffer to copy to 491 * \param[in] count the length of the data to copy 492 */ 493 INLINE void 494 ldns_buffer_read(ldns_buffer *buffer, void *data, size_t count) 495 { 496 ldns_buffer_read_at(buffer, buffer->_position, data, count); 497 buffer->_position += count; 498 } 499 500 /** 501 * returns the byte value at the given position in the buffer 502 * \param[in] buffer the buffer 503 * \param[in] at the position in the buffer 504 * \return 1 byte integer 505 */ 506 INLINE uint8_t 507 ldns_buffer_read_u8_at(ldns_buffer *buffer, size_t at) 508 { 509 assert(ldns_buffer_available_at(buffer, at, sizeof(uint8_t))); 510 return buffer->_data[at]; 511 } 512 513 /** 514 * returns the byte value at the current position in the buffer 515 * \param[in] buffer the buffer 516 * \return 1 byte integer 517 */ 518 INLINE uint8_t 519 ldns_buffer_read_u8(ldns_buffer *buffer) 520 { 521 uint8_t result = ldns_buffer_read_u8_at(buffer, buffer->_position); 522 buffer->_position += sizeof(uint8_t); 523 return result; 524 } 525 526 /** 527 * returns the 2-byte integer value at the given position in the buffer 528 * \param[in] buffer the buffer 529 * \param[in] at position in the buffer 530 * \return 2 byte integer 531 */ 532 INLINE uint16_t 533 ldns_buffer_read_u16_at(ldns_buffer *buffer, size_t at) 534 { 535 assert(ldns_buffer_available_at(buffer, at, sizeof(uint16_t))); 536 return ldns_read_uint16(buffer->_data + at); 537 } 538 539 /** 540 * returns the 2-byte integer value at the current position in the buffer 541 * \param[in] buffer the buffer 542 * \return 2 byte integer 543 */ 544 INLINE uint16_t 545 ldns_buffer_read_u16(ldns_buffer *buffer) 546 { 547 uint16_t result = ldns_buffer_read_u16_at(buffer, buffer->_position); 548 buffer->_position += sizeof(uint16_t); 549 return result; 550 } 551 552 /** 553 * returns the 4-byte integer value at the given position in the buffer 554 * \param[in] buffer the buffer 555 * \param[in] at position in the buffer 556 * \return 4 byte integer 557 */ 558 INLINE uint32_t 559 ldns_buffer_read_u32_at(ldns_buffer *buffer, size_t at) 560 { 561 assert(ldns_buffer_available_at(buffer, at, sizeof(uint32_t))); 562 return ldns_read_uint32(buffer->_data + at); 563 } 564 565 /** 566 * returns the 4-byte integer value at the current position in the buffer 567 * \param[in] buffer the buffer 568 * \return 4 byte integer 569 */ 570 INLINE uint32_t 571 ldns_buffer_read_u32(ldns_buffer *buffer) 572 { 573 uint32_t result = ldns_buffer_read_u32_at(buffer, buffer->_position); 574 buffer->_position += sizeof(uint32_t); 575 return result; 576 } 577 578 /** 579 * returns the status of the buffer 580 * \param[in] buffer 581 * \return the status 582 */ 583 INLINE ldns_status 584 ldns_buffer_status(ldns_buffer *buffer) 585 { 586 return buffer->_status; 587 } 588 589 /** 590 * returns true if the status of the buffer is LDNS_STATUS_OK, false otherwise 591 * \param[in] buffer the buffer 592 * \return true or false 593 */ 594 INLINE bool 595 ldns_buffer_status_ok(ldns_buffer *buffer) 596 { 597 if (buffer) { 598 return ldns_buffer_status(buffer) == LDNS_STATUS_OK; 599 } else { 600 return false; 601 } 602 } 603 604 /** 605 * prints to the buffer, increasing the capacity if required using 606 * buffer_reserve(). The buffer's position is set to the terminating 607 * '\\0'. Returns the number of characters written (not including the 608 * terminating '\\0') or -1 on failure. 609 */ 610 int ldns_buffer_printf(ldns_buffer *buffer, const char *format, ...); 611 /* ATTR_FORMAT(printf, 2, 3);*/ 612 613 /** 614 * frees the buffer. 615 * \param[in] *buffer the buffer to be freed 616 * \return void 617 */ 618 void ldns_buffer_free(ldns_buffer *buffer); 619 620 /** 621 * Makes the buffer fixed and returns a pointer to the data. The 622 * caller is responsible for free'ing the result. 623 * \param[in] *buffer the buffer to be exported 624 * \return void 625 */ 626 void *ldns_buffer_export(ldns_buffer *buffer); 627 628 /** 629 * Copy contents of the other buffer to this buffer. Silently truncated 630 * if this buffer is too small. 631 * \param[out] *result resulting buffer which is copied to. 632 * \param[in] *from what to copy to result. 633 */ 634 void ldns_buffer_copy(ldns_buffer* result, ldns_buffer* from); 635 636 #endif /* LDNS_BUFFER_H */ 637