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