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