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 26extern "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 */ 50struct 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}; 72typedef struct ldns_struct_buffer ldns_buffer; 73 74 75#ifdef NDEBUG 76INLINE void 77ldns_buffer_invariant(ldns_buffer *ATTR_UNUSED(buffer)) 78{ 79} 80#else 81INLINE void 82ldns_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 */ 97ldns_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 */ 108void 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 */ 115INLINE 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 */ 133INLINE 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 */ 146INLINE 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 */ 158INLINE size_t 159ldns_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 */ 170INLINE void 171ldns_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 */ 184INLINE void 185ldns_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 */ 196INLINE size_t 197ldns_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 */ 208INLINE void 209ldns_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 */ 222INLINE size_t 223ldns_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 */ 236bool 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 */ 248bool 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 */ 256INLINE uint8_t * 257ldns_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 */ 269INLINE uint8_t * 270ldns_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 */ 281INLINE uint8_t * 282ldns_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 */ 292INLINE uint8_t * 293ldns_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 */ 305INLINE size_t 306ldns_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 */ 319INLINE size_t 320ldns_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 */ 334INLINE int 335ldns_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 */ 346INLINE int 347ldns_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 */ 359INLINE void 360ldns_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 */ 372INLINE void 373ldns_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 */ 385INLINE void 386ldns_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 */ 396INLINE void 397ldns_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 */ 408INLINE void 409ldns_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 */ 420INLINE void 421ldns_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 */ 433INLINE void 434ldns_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 */ 445INLINE void 446ldns_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 */ 458INLINE void 459ldns_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 */ 470INLINE void 471ldns_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 */ 484INLINE void 485ldns_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 */ 497INLINE void 498ldns_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 */ 510INLINE uint8_t 511ldns_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 */ 522INLINE uint8_t 523ldns_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 */ 536INLINE uint16_t 537ldns_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 */ 548INLINE uint16_t 549ldns_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 */ 562INLINE uint32_t 563ldns_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 */ 574INLINE uint32_t 575ldns_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 */ 587INLINE ldns_status 588ldns_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 */ 598INLINE bool 599ldns_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 */ 614int 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 */ 622void 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 */ 630void *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 */ 639void ldns_buffer_copy(ldns_buffer* result, ldns_buffer* from); 640 641#ifdef __cplusplus 642} 643#endif 644 645#endif /* LDNS_BUFFER_H */ 646