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