sbuffer.h revision 356345
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_SBUFFER_H 14#define LDNS_SBUFFER_H 15 16#ifdef __cplusplus 17extern "C" { 18#endif 19 20#ifdef S_SPLINT_S 21# define INLINE 22#else 23# ifdef SWIG 24# define INLINE static 25# else 26# define INLINE static inline 27# endif 28#endif 29 30/* 31 * Copy data allowing for unaligned accesses in network byte order 32 * (big endian). 33 */ 34INLINE uint16_t 35sldns_read_uint16(const void *src) 36{ 37#ifdef ALLOW_UNALIGNED_ACCESSES 38 return ntohs(*(const uint16_t *) src); 39#else 40 const uint8_t *p = (const uint8_t *) src; 41 return ((uint16_t) p[0] << 8) | (uint16_t) p[1]; 42#endif 43} 44 45INLINE uint32_t 46sldns_read_uint32(const void *src) 47{ 48#ifdef ALLOW_UNALIGNED_ACCESSES 49 return ntohl(*(const uint32_t *) src); 50#else 51 const uint8_t *p = (const uint8_t *) src; 52 return ( ((uint32_t) p[0] << 24) 53 | ((uint32_t) p[1] << 16) 54 | ((uint32_t) p[2] << 8) 55 | (uint32_t) p[3]); 56#endif 57} 58 59/* 60 * Copy data allowing for unaligned accesses in network byte order 61 * (big endian). 62 */ 63INLINE void 64sldns_write_uint16(void *dst, uint16_t data) 65{ 66#ifdef ALLOW_UNALIGNED_ACCESSES 67 * (uint16_t *) dst = htons(data); 68#else 69 uint8_t *p = (uint8_t *) dst; 70 p[0] = (uint8_t) ((data >> 8) & 0xff); 71 p[1] = (uint8_t) (data & 0xff); 72#endif 73} 74 75INLINE void 76sldns_write_uint32(void *dst, uint32_t data) 77{ 78#ifdef ALLOW_UNALIGNED_ACCESSES 79 * (uint32_t *) dst = htonl(data); 80#else 81 uint8_t *p = (uint8_t *) dst; 82 p[0] = (uint8_t) ((data >> 24) & 0xff); 83 p[1] = (uint8_t) ((data >> 16) & 0xff); 84 p[2] = (uint8_t) ((data >> 8) & 0xff); 85 p[3] = (uint8_t) (data & 0xff); 86#endif 87} 88 89 90INLINE void 91sldns_write_uint48(void *dst, uint64_t data) 92{ 93 uint8_t *p = (uint8_t *) dst; 94 p[0] = (uint8_t) ((data >> 40) & 0xff); 95 p[1] = (uint8_t) ((data >> 32) & 0xff); 96 p[2] = (uint8_t) ((data >> 24) & 0xff); 97 p[3] = (uint8_t) ((data >> 16) & 0xff); 98 p[4] = (uint8_t) ((data >> 8) & 0xff); 99 p[5] = (uint8_t) (data & 0xff); 100} 101 102 103/** 104 * \file sbuffer.h 105 * 106 * This file contains the definition of sldns_buffer, and functions to manipulate those. 107 */ 108 109/** 110 * implementation of buffers to ease operations 111 * 112 * sldns_buffers can contain arbitrary information, per octet. You can write 113 * to the current end of a buffer, read from the current position, and 114 * access any data within it. 115 */ 116struct sldns_buffer 117{ 118 /** The current position used for reading/writing */ 119 size_t _position; 120 121 /** The read/write limit */ 122 size_t _limit; 123 124 /** The amount of data the buffer can contain */ 125 size_t _capacity; 126 127 /** The data contained in the buffer */ 128 uint8_t *_data; 129 130 /** If the buffer is fixed it cannot be resized */ 131 unsigned _fixed : 1; 132 133 /** The current state of the buffer. If writing to the buffer fails 134 * for any reason, this value is changed. This way, you can perform 135 * multiple writes in sequence and check for success afterwards. */ 136 unsigned _status_err : 1; 137}; 138typedef struct sldns_buffer sldns_buffer; 139 140#ifdef NDEBUG 141INLINE void 142sldns_buffer_invariant(sldns_buffer *ATTR_UNUSED(buffer)) 143{ 144} 145#else 146INLINE void 147sldns_buffer_invariant(sldns_buffer *buffer) 148{ 149 assert(buffer != NULL); 150 assert(buffer->_position <= buffer->_limit); 151 assert(buffer->_limit <= buffer->_capacity); 152 assert(buffer->_data != NULL); 153} 154#endif 155 156/** 157 * creates a new buffer with the specified capacity. 158 * 159 * \param[in] capacity the size (in bytes) to allocate for the buffer 160 * \return the created buffer 161 */ 162sldns_buffer *sldns_buffer_new(size_t capacity); 163 164/** 165 * creates a buffer with the specified data. The data IS copied 166 * and MEMORY allocations are done. The buffer is not fixed and can 167 * be resized using buffer_reserve(). 168 * 169 * \param[in] buffer pointer to the buffer to put the data in 170 * \param[in] data the data to encapsulate in the buffer 171 * \param[in] size the size of the data 172 */ 173void sldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size); 174 175/** 176 * Setup a buffer with the data pointed to. No data copied, no memory allocs. 177 * The buffer is fixed. 178 * \param[in] buffer pointer to the buffer to put the data in 179 * \param[in] data the data to encapsulate in the buffer 180 * \param[in] size the size of the data 181 */ 182void sldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size); 183 184/** 185 * clears the buffer and make it ready for writing. The buffer's limit 186 * is set to the capacity and the position is set to 0. 187 * \param[in] buffer the buffer to clear 188 */ 189INLINE void sldns_buffer_clear(sldns_buffer *buffer) 190{ 191 sldns_buffer_invariant(buffer); 192 193 /* reset status here? */ 194 195 buffer->_position = 0; 196 buffer->_limit = buffer->_capacity; 197} 198 199/** 200 * makes the buffer ready for reading the data that has been written to 201 * the buffer. The buffer's limit is set to the current position and 202 * the position is set to 0. 203 * 204 * \param[in] buffer the buffer to flip 205 * \return void 206 */ 207INLINE void sldns_buffer_flip(sldns_buffer *buffer) 208{ 209 sldns_buffer_invariant(buffer); 210 211 buffer->_limit = buffer->_position; 212 buffer->_position = 0; 213} 214 215/** 216 * make the buffer ready for re-reading the data. The buffer's 217 * position is reset to 0. 218 * \param[in] buffer the buffer to rewind 219 */ 220INLINE void sldns_buffer_rewind(sldns_buffer *buffer) 221{ 222 sldns_buffer_invariant(buffer); 223 224 buffer->_position = 0; 225} 226 227/** 228 * returns the current position in the buffer (as a number of bytes) 229 * \param[in] buffer the buffer 230 * \return the current position 231 */ 232INLINE size_t 233sldns_buffer_position(sldns_buffer *buffer) 234{ 235 return buffer->_position; 236} 237 238/** 239 * sets the buffer's position to MARK. The position must be less than 240 * or equal to the buffer's limit. 241 * \param[in] buffer the buffer 242 * \param[in] mark the mark to use 243 */ 244INLINE void 245sldns_buffer_set_position(sldns_buffer *buffer, size_t mark) 246{ 247 assert(mark <= buffer->_limit); 248 buffer->_position = mark; 249} 250 251/** 252 * changes the buffer's position by COUNT bytes. The position must not 253 * be moved behind the buffer's limit or before the beginning of the 254 * buffer. 255 * \param[in] buffer the buffer 256 * \param[in] count the count to use 257 */ 258INLINE void 259sldns_buffer_skip(sldns_buffer *buffer, ssize_t count) 260{ 261 assert(buffer->_position + count <= buffer->_limit); 262 buffer->_position += count; 263} 264 265/** 266 * returns the maximum size of the buffer 267 * \param[in] buffer 268 * \return the size 269 */ 270INLINE size_t 271sldns_buffer_limit(sldns_buffer *buffer) 272{ 273 return buffer->_limit; 274} 275 276/** 277 * changes the buffer's limit. If the buffer's position is greater 278 * than the new limit the position is set to the limit. 279 * \param[in] buffer the buffer 280 * \param[in] limit the new limit 281 */ 282INLINE void 283sldns_buffer_set_limit(sldns_buffer *buffer, size_t limit) 284{ 285 assert(limit <= buffer->_capacity); 286 buffer->_limit = limit; 287 if (buffer->_position > buffer->_limit) 288 buffer->_position = buffer->_limit; 289} 290 291/** 292 * returns the number of bytes the buffer can hold. 293 * \param[in] buffer the buffer 294 * \return the number of bytes 295 */ 296INLINE size_t 297sldns_buffer_capacity(sldns_buffer *buffer) 298{ 299 return buffer->_capacity; 300} 301 302/** 303 * changes the buffer's capacity. The data is reallocated so any 304 * pointers to the data may become invalid. The buffer's limit is set 305 * to the buffer's new capacity. 306 * \param[in] buffer the buffer 307 * \param[in] capacity the capacity to use 308 * \return whether this failed or succeeded 309 */ 310int sldns_buffer_set_capacity(sldns_buffer *buffer, size_t capacity); 311 312/** 313 * ensures BUFFER can contain at least AMOUNT more bytes. The buffer's 314 * capacity is increased if necessary using buffer_set_capacity(). 315 * 316 * The buffer's limit is always set to the (possibly increased) 317 * capacity. 318 * \param[in] buffer the buffer 319 * \param[in] amount amount to use 320 * \return whether this failed or succeeded 321 */ 322int sldns_buffer_reserve(sldns_buffer *buffer, size_t amount); 323 324/** 325 * returns a pointer to the data at the indicated position. 326 * \param[in] buffer the buffer 327 * \param[in] at position 328 * \return the pointer to the data 329 */ 330INLINE uint8_t * 331sldns_buffer_at(const sldns_buffer *buffer, size_t at) 332{ 333 assert(at <= buffer->_limit); 334 return buffer->_data + at; 335} 336 337/** 338 * returns a pointer to the beginning of the buffer (the data at 339 * position 0). 340 * \param[in] buffer the buffer 341 * \return the pointer 342 */ 343INLINE uint8_t * 344sldns_buffer_begin(const sldns_buffer *buffer) 345{ 346 return sldns_buffer_at(buffer, 0); 347} 348 349/** 350 * returns a pointer to the end of the buffer (the data at the buffer's 351 * limit). 352 * \param[in] buffer the buffer 353 * \return the pointer 354 */ 355INLINE uint8_t * 356sldns_buffer_end(sldns_buffer *buffer) 357{ 358 return sldns_buffer_at(buffer, buffer->_limit); 359} 360 361/** 362 * returns a pointer to the data at the buffer's current position. 363 * \param[in] buffer the buffer 364 * \return the pointer 365 */ 366INLINE uint8_t * 367sldns_buffer_current(sldns_buffer *buffer) 368{ 369 return sldns_buffer_at(buffer, buffer->_position); 370} 371 372/** 373 * returns the number of bytes remaining between the indicated position and 374 * the limit. 375 * \param[in] buffer the buffer 376 * \param[in] at indicated position 377 * \return number of bytes 378 */ 379INLINE size_t 380sldns_buffer_remaining_at(sldns_buffer *buffer, size_t at) 381{ 382 sldns_buffer_invariant(buffer); 383 assert(at <= buffer->_limit); 384 return at < buffer->_limit ? buffer->_limit - at : 0; 385} 386 387/** 388 * returns the number of bytes remaining between the buffer's position and 389 * limit. 390 * \param[in] buffer the buffer 391 * \return the number of bytes 392 */ 393INLINE size_t 394sldns_buffer_remaining(sldns_buffer *buffer) 395{ 396 return sldns_buffer_remaining_at(buffer, buffer->_position); 397} 398 399/** 400 * checks if the buffer has at least COUNT more bytes available. 401 * Before reading or writing the caller needs to ensure enough space 402 * is available! 403 * \param[in] buffer the buffer 404 * \param[in] at indicated position 405 * \param[in] count how much is available 406 * \return true or false (as int?) 407 */ 408INLINE int 409sldns_buffer_available_at(sldns_buffer *buffer, size_t at, size_t count) 410{ 411 return count <= sldns_buffer_remaining_at(buffer, at); 412} 413 414/** 415 * checks if the buffer has count bytes available at the current position 416 * \param[in] buffer the buffer 417 * \param[in] count how much is available 418 * \return true or false (as int?) 419 */ 420INLINE int 421sldns_buffer_available(sldns_buffer *buffer, size_t count) 422{ 423 return sldns_buffer_available_at(buffer, buffer->_position, count); 424} 425 426/** 427 * writes the given data to the buffer at the specified position 428 * \param[in] buffer the buffer 429 * \param[in] at the position (in number of bytes) to write the data at 430 * \param[in] data pointer to the data to write to the buffer 431 * \param[in] count the number of bytes of data to write 432 */ 433INLINE void 434sldns_buffer_write_at(sldns_buffer *buffer, size_t at, const void *data, size_t count) 435{ 436 assert(sldns_buffer_available_at(buffer, at, count)); 437 memcpy(buffer->_data + at, data, count); 438} 439 440/** 441 * set the given byte to the buffer at the specified position 442 * \param[in] buffer the buffer 443 * \param[in] at the position (in number of bytes) to write the data at 444 * \param[in] c the byte to set to the buffer 445 * \param[in] count the number of bytes of bytes to write 446 */ 447 448INLINE void 449sldns_buffer_set_at(sldns_buffer *buffer, size_t at, int c, size_t count) 450{ 451 assert(sldns_buffer_available_at(buffer, at, count)); 452 memset(buffer->_data + at, c, count); 453} 454 455 456/** 457 * writes count bytes of data to the current position of the buffer 458 * \param[in] buffer the buffer 459 * \param[in] data the data to write 460 * \param[in] count the length of the data to write 461 */ 462INLINE void 463sldns_buffer_write(sldns_buffer *buffer, const void *data, size_t count) 464{ 465 sldns_buffer_write_at(buffer, buffer->_position, data, count); 466 buffer->_position += count; 467} 468 469/** 470 * copies the given (null-delimited) string to the specified position at the buffer 471 * \param[in] buffer the buffer 472 * \param[in] at the position in the buffer 473 * \param[in] str the string to write 474 */ 475INLINE void 476sldns_buffer_write_string_at(sldns_buffer *buffer, size_t at, const char *str) 477{ 478 sldns_buffer_write_at(buffer, at, str, strlen(str)); 479} 480 481/** 482 * copies the given (null-delimited) string to the current position at the buffer 483 * \param[in] buffer the buffer 484 * \param[in] str the string to write 485 */ 486INLINE void 487sldns_buffer_write_string(sldns_buffer *buffer, const char *str) 488{ 489 sldns_buffer_write(buffer, str, strlen(str)); 490} 491 492/** 493 * writes the given byte of data at the given position in the buffer 494 * \param[in] buffer the buffer 495 * \param[in] at the position in the buffer 496 * \param[in] data the 8 bits to write 497 */ 498INLINE void 499sldns_buffer_write_u8_at(sldns_buffer *buffer, size_t at, uint8_t data) 500{ 501 assert(sldns_buffer_available_at(buffer, at, sizeof(data))); 502 buffer->_data[at] = data; 503} 504 505/** 506 * writes the given byte of data at the current position in the buffer 507 * \param[in] buffer the buffer 508 * \param[in] data the 8 bits to write 509 */ 510INLINE void 511sldns_buffer_write_u8(sldns_buffer *buffer, uint8_t data) 512{ 513 sldns_buffer_write_u8_at(buffer, buffer->_position, data); 514 buffer->_position += sizeof(data); 515} 516 517/** 518 * writes the given 2 byte integer at the given position in the buffer 519 * \param[in] buffer the buffer 520 * \param[in] at the position in the buffer 521 * \param[in] data the 16 bits to write 522 */ 523INLINE void 524sldns_buffer_write_u16_at(sldns_buffer *buffer, size_t at, uint16_t data) 525{ 526 assert(sldns_buffer_available_at(buffer, at, sizeof(data))); 527 sldns_write_uint16(buffer->_data + at, data); 528} 529 530/** 531 * writes the given 2 byte integer at the current position in the buffer 532 * \param[in] buffer the buffer 533 * \param[in] data the 16 bits to write 534 */ 535INLINE void 536sldns_buffer_write_u16(sldns_buffer *buffer, uint16_t data) 537{ 538 sldns_buffer_write_u16_at(buffer, buffer->_position, data); 539 buffer->_position += sizeof(data); 540} 541 542/** 543 * writes the given 4 byte integer at the given position in the buffer 544 * \param[in] buffer the buffer 545 * \param[in] at the position in the buffer 546 * \param[in] data the 32 bits to write 547 */ 548INLINE void 549sldns_buffer_write_u32_at(sldns_buffer *buffer, size_t at, uint32_t data) 550{ 551 assert(sldns_buffer_available_at(buffer, at, sizeof(data))); 552 sldns_write_uint32(buffer->_data + at, data); 553} 554 555/** 556 * writes the given 6 byte integer at the given position in the buffer 557 * \param[in] buffer the buffer 558 * \param[in] at the position in the buffer 559 * \param[in] data the (lower) 48 bits to write 560 */ 561INLINE void 562sldns_buffer_write_u48_at(sldns_buffer *buffer, size_t at, uint64_t data) 563{ 564 assert(sldns_buffer_available_at(buffer, at, 6)); 565 sldns_write_uint48(buffer->_data + at, data); 566} 567 568/** 569 * writes the given 4 byte integer at the current position in the buffer 570 * \param[in] buffer the buffer 571 * \param[in] data the 32 bits to write 572 */ 573INLINE void 574sldns_buffer_write_u32(sldns_buffer *buffer, uint32_t data) 575{ 576 sldns_buffer_write_u32_at(buffer, buffer->_position, data); 577 buffer->_position += sizeof(data); 578} 579 580/** 581 * writes the given 6 byte integer at the current position in the buffer 582 * \param[in] buffer the buffer 583 * \param[in] data the 48 bits to write 584 */ 585INLINE void 586sldns_buffer_write_u48(sldns_buffer *buffer, uint64_t data) 587{ 588 sldns_buffer_write_u48_at(buffer, buffer->_position, data); 589 buffer->_position += 6; 590} 591 592/** 593 * copies count bytes of data at the given position to the given data-array 594 * \param[in] buffer the buffer 595 * \param[in] at the position in the buffer to start 596 * \param[out] data buffer to copy to 597 * \param[in] count the length of the data to copy 598 */ 599INLINE void 600sldns_buffer_read_at(sldns_buffer *buffer, size_t at, void *data, size_t count) 601{ 602 assert(sldns_buffer_available_at(buffer, at, count)); 603 memcpy(data, buffer->_data + at, count); 604} 605 606/** 607 * copies count bytes of data at the current position to the given data-array 608 * \param[in] buffer the buffer 609 * \param[out] data buffer to copy to 610 * \param[in] count the length of the data to copy 611 */ 612INLINE void 613sldns_buffer_read(sldns_buffer *buffer, void *data, size_t count) 614{ 615 sldns_buffer_read_at(buffer, buffer->_position, data, count); 616 buffer->_position += count; 617} 618 619/** 620 * returns the byte value at the given position in the buffer 621 * \param[in] buffer the buffer 622 * \param[in] at the position in the buffer 623 * \return 1 byte integer 624 */ 625INLINE uint8_t 626sldns_buffer_read_u8_at(sldns_buffer *buffer, size_t at) 627{ 628 assert(sldns_buffer_available_at(buffer, at, sizeof(uint8_t))); 629 return buffer->_data[at]; 630} 631 632/** 633 * returns the byte value at the current position in the buffer 634 * \param[in] buffer the buffer 635 * \return 1 byte integer 636 */ 637INLINE uint8_t 638sldns_buffer_read_u8(sldns_buffer *buffer) 639{ 640 uint8_t result = sldns_buffer_read_u8_at(buffer, buffer->_position); 641 buffer->_position += sizeof(uint8_t); 642 return result; 643} 644 645/** 646 * returns the 2-byte integer value at the given position in the buffer 647 * \param[in] buffer the buffer 648 * \param[in] at position in the buffer 649 * \return 2 byte integer 650 */ 651INLINE uint16_t 652sldns_buffer_read_u16_at(sldns_buffer *buffer, size_t at) 653{ 654 assert(sldns_buffer_available_at(buffer, at, sizeof(uint16_t))); 655 return sldns_read_uint16(buffer->_data + at); 656} 657 658/** 659 * returns the 2-byte integer value at the current position in the buffer 660 * \param[in] buffer the buffer 661 * \return 2 byte integer 662 */ 663INLINE uint16_t 664sldns_buffer_read_u16(sldns_buffer *buffer) 665{ 666 uint16_t result = sldns_buffer_read_u16_at(buffer, buffer->_position); 667 buffer->_position += sizeof(uint16_t); 668 return result; 669} 670 671/** 672 * returns the 4-byte integer value at the given position in the buffer 673 * \param[in] buffer the buffer 674 * \param[in] at position in the buffer 675 * \return 4 byte integer 676 */ 677INLINE uint32_t 678sldns_buffer_read_u32_at(sldns_buffer *buffer, size_t at) 679{ 680 assert(sldns_buffer_available_at(buffer, at, sizeof(uint32_t))); 681 return sldns_read_uint32(buffer->_data + at); 682} 683 684/** 685 * returns the 4-byte integer value at the current position in the buffer 686 * \param[in] buffer the buffer 687 * \return 4 byte integer 688 */ 689INLINE uint32_t 690sldns_buffer_read_u32(sldns_buffer *buffer) 691{ 692 uint32_t result = sldns_buffer_read_u32_at(buffer, buffer->_position); 693 buffer->_position += sizeof(uint32_t); 694 return result; 695} 696 697/** 698 * returns the status of the buffer 699 * \param[in] buffer 700 * \return the status 701 */ 702INLINE int 703sldns_buffer_status(sldns_buffer *buffer) 704{ 705 return (int)buffer->_status_err; 706} 707 708/** 709 * returns true if the status of the buffer is LDNS_STATUS_OK, false otherwise 710 * \param[in] buffer the buffer 711 * \return true or false 712 */ 713INLINE int 714sldns_buffer_status_ok(sldns_buffer *buffer) 715{ 716 if (buffer) { 717 return sldns_buffer_status(buffer) == 0; 718 } else { 719 return 0; 720 } 721} 722 723/** 724 * prints to the buffer, increasing the capacity if required using 725 * buffer_reserve(). The buffer's position is set to the terminating '\\0' 726 * Returns the number of characters written (not including the 727 * terminating '\\0') or -1 on failure. 728 */ 729int sldns_buffer_printf(sldns_buffer *buffer, const char *format, ...) 730 ATTR_FORMAT(printf, 2, 3); 731 732/** 733 * frees the buffer. 734 * \param[in] *buffer the buffer to be freed 735 * \return void 736 */ 737void sldns_buffer_free(sldns_buffer *buffer); 738 739/** 740 * Copy contents of the from buffer to the result buffer and then flips 741 * the result buffer. Data will be silently truncated if the result buffer is 742 * too small. 743 * \param[out] *result resulting buffer which is copied to. 744 * \param[in] *from what to copy to result. 745 */ 746void sldns_buffer_copy(sldns_buffer* result, sldns_buffer* from); 747 748#ifdef __cplusplus 749} 750#endif 751 752#endif /* LDNS_SBUFFER_H */ 753