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(ldns_buffer *ATTR_UNUSED(buffer)) 78 { 79 } 80 #else 81 INLINE void 82 ldns_buffer_invariant(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, 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(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(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(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(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(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(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(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(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(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 lenght 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 * writes the given byte of data at the given position in the buffer 404 * \param[in] buffer the buffer 405 * \param[in] at the position in the buffer 406 * \param[in] data the 8 bits to write 407 */ 408 INLINE void 409 ldns_buffer_write_u8_at(ldns_buffer *buffer, size_t at, uint8_t data) 410 { 411 assert(ldns_buffer_available_at(buffer, at, sizeof(data))); 412 buffer->_data[at] = data; 413 } 414 415 /** 416 * writes the given byte of data at the current position in the buffer 417 * \param[in] buffer the buffer 418 * \param[in] data the 8 bits to write 419 */ 420 INLINE void 421 ldns_buffer_write_u8(ldns_buffer *buffer, uint8_t data) 422 { 423 ldns_buffer_write_u8_at(buffer, buffer->_position, data); 424 buffer->_position += sizeof(data); 425 } 426 427 /** 428 * writes the given 2 byte integer at the given position in the buffer 429 * \param[in] buffer the buffer 430 * \param[in] at the position in the buffer 431 * \param[in] data the 16 bits to write 432 */ 433 INLINE void 434 ldns_buffer_write_u16_at(ldns_buffer *buffer, size_t at, uint16_t data) 435 { 436 assert(ldns_buffer_available_at(buffer, at, sizeof(data))); 437 ldns_write_uint16(buffer->_data + at, data); 438 } 439 440 /** 441 * writes the given 2 byte integer at the current position in the buffer 442 * \param[in] buffer the buffer 443 * \param[in] data the 16 bits to write 444 */ 445 INLINE void 446 ldns_buffer_write_u16(ldns_buffer *buffer, uint16_t data) 447 { 448 ldns_buffer_write_u16_at(buffer, buffer->_position, data); 449 buffer->_position += sizeof(data); 450 } 451 452 /** 453 * writes the given 4 byte integer at the given position in the buffer 454 * \param[in] buffer the buffer 455 * \param[in] at the position in the buffer 456 * \param[in] data the 32 bits to write 457 */ 458 INLINE void 459 ldns_buffer_write_u32_at(ldns_buffer *buffer, size_t at, uint32_t data) 460 { 461 assert(ldns_buffer_available_at(buffer, at, sizeof(data))); 462 ldns_write_uint32(buffer->_data + at, data); 463 } 464 465 /** 466 * writes the given 4 byte integer at the current position in the buffer 467 * \param[in] buffer the buffer 468 * \param[in] data the 32 bits to write 469 */ 470 INLINE void 471 ldns_buffer_write_u32(ldns_buffer *buffer, uint32_t data) 472 { 473 ldns_buffer_write_u32_at(buffer, buffer->_position, data); 474 buffer->_position += sizeof(data); 475 } 476 477 /** 478 * copies count bytes of data at the given position to the given data-array 479 * \param[in] buffer the buffer 480 * \param[in] at the position in the buffer to start 481 * \param[out] data buffer to copy to 482 * \param[in] count the length of the data to copy 483 */ 484 INLINE void 485 ldns_buffer_read_at(ldns_buffer *buffer, size_t at, void *data, size_t count) 486 { 487 assert(ldns_buffer_available_at(buffer, at, count)); 488 memcpy(data, buffer->_data + at, count); 489 } 490 491 /** 492 * copies count bytes of data at the current position to the given data-array 493 * \param[in] buffer the buffer 494 * \param[out] data buffer to copy to 495 * \param[in] count the length of the data to copy 496 */ 497 INLINE void 498 ldns_buffer_read(ldns_buffer *buffer, void *data, size_t count) 499 { 500 ldns_buffer_read_at(buffer, buffer->_position, data, count); 501 buffer->_position += count; 502 } 503 504 /** 505 * returns the byte value at the given position in the buffer 506 * \param[in] buffer the buffer 507 * \param[in] at the position in the buffer 508 * \return 1 byte integer 509 */ 510 INLINE uint8_t 511 ldns_buffer_read_u8_at(ldns_buffer *buffer, size_t at) 512 { 513 assert(ldns_buffer_available_at(buffer, at, sizeof(uint8_t))); 514 return buffer->_data[at]; 515 } 516 517 /** 518 * returns the byte value at the current position in the buffer 519 * \param[in] buffer the buffer 520 * \return 1 byte integer 521 */ 522 INLINE uint8_t 523 ldns_buffer_read_u8(ldns_buffer *buffer) 524 { 525 uint8_t result = ldns_buffer_read_u8_at(buffer, buffer->_position); 526 buffer->_position += sizeof(uint8_t); 527 return result; 528 } 529 530 /** 531 * returns the 2-byte integer value at the given position in the buffer 532 * \param[in] buffer the buffer 533 * \param[in] at position in the buffer 534 * \return 2 byte integer 535 */ 536 INLINE uint16_t 537 ldns_buffer_read_u16_at(ldns_buffer *buffer, size_t at) 538 { 539 assert(ldns_buffer_available_at(buffer, at, sizeof(uint16_t))); 540 return ldns_read_uint16(buffer->_data + at); 541 } 542 543 /** 544 * returns the 2-byte integer value at the current position in the buffer 545 * \param[in] buffer the buffer 546 * \return 2 byte integer 547 */ 548 INLINE uint16_t 549 ldns_buffer_read_u16(ldns_buffer *buffer) 550 { 551 uint16_t result = ldns_buffer_read_u16_at(buffer, buffer->_position); 552 buffer->_position += sizeof(uint16_t); 553 return result; 554 } 555 556 /** 557 * returns the 4-byte integer value at the given position in the buffer 558 * \param[in] buffer the buffer 559 * \param[in] at position in the buffer 560 * \return 4 byte integer 561 */ 562 INLINE uint32_t 563 ldns_buffer_read_u32_at(ldns_buffer *buffer, size_t at) 564 { 565 assert(ldns_buffer_available_at(buffer, at, sizeof(uint32_t))); 566 return ldns_read_uint32(buffer->_data + at); 567 } 568 569 /** 570 * returns the 4-byte integer value at the current position in the buffer 571 * \param[in] buffer the buffer 572 * \return 4 byte integer 573 */ 574 INLINE uint32_t 575 ldns_buffer_read_u32(ldns_buffer *buffer) 576 { 577 uint32_t result = ldns_buffer_read_u32_at(buffer, buffer->_position); 578 buffer->_position += sizeof(uint32_t); 579 return result; 580 } 581 582 /** 583 * returns the status of the buffer 584 * \param[in] buffer 585 * \return the status 586 */ 587 INLINE ldns_status 588 ldns_buffer_status(ldns_buffer *buffer) 589 { 590 return buffer->_status; 591 } 592 593 /** 594 * returns true if the status of the buffer is LDNS_STATUS_OK, false otherwise 595 * \param[in] buffer the buffer 596 * \return true or false 597 */ 598 INLINE bool 599 ldns_buffer_status_ok(ldns_buffer *buffer) 600 { 601 if (buffer) { 602 return ldns_buffer_status(buffer) == LDNS_STATUS_OK; 603 } else { 604 return false; 605 } 606 } 607 608 /** 609 * prints to the buffer, increasing the capacity if required using 610 * buffer_reserve(). The buffer's position is set to the terminating '\\0' 611 * Returns the number of characters written (not including the 612 * terminating '\\0') or -1 on failure. 613 */ 614 int ldns_buffer_printf(ldns_buffer *buffer, const char *format, ...); 615 /* ATTR_FORMAT(printf, 2, 3);*/ 616 617 /** 618 * frees the buffer. 619 * \param[in] *buffer the buffer to be freed 620 * \return void 621 */ 622 void ldns_buffer_free(ldns_buffer *buffer); 623 624 /** 625 * Makes the buffer fixed and returns a pointer to the data. The 626 * caller is responsible for free'ing the result. 627 * \param[in] *buffer the buffer to be exported 628 * \return void 629 */ 630 void *ldns_buffer_export(ldns_buffer *buffer); 631 632 /** 633 * Copy contents of the from buffer to the result buffer and then flips 634 * the result buffer. Data will be silently truncated if the result buffer is 635 * too small. 636 * \param[out] *result resulting buffer which is copied to. 637 * \param[in] *from what to copy to result. 638 */ 639 void ldns_buffer_copy(ldns_buffer* result, ldns_buffer* from); 640 641 #ifdef __cplusplus 642 } 643 #endif 644 645 #endif /* LDNS_BUFFER_H */ 646