2 * buffer.h -- generic memory buffer.
4 * Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
6 * See LICENSE for the license.
9 * The buffer module implements a generic buffer. The API is based on
10 * the java.nio.Buffer interface.
13 #ifndef LDNS_SBUFFER_H
14 #define LDNS_SBUFFER_H
24 # define INLINE static
26 # define INLINE static inline
31 * Copy data allowing for unaligned accesses in network byte order
35 sldns_read_uint16(const void *src)
37 #ifdef ALLOW_UNALIGNED_ACCESSES
38 return ntohs(*(const uint16_t *) src);
40 const uint8_t *p = (const uint8_t *) src;
41 return ((uint16_t) p[0] << 8) | (uint16_t) p[1];
46 sldns_read_uint32(const void *src)
48 #ifdef ALLOW_UNALIGNED_ACCESSES
49 return ntohl(*(const uint32_t *) src);
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)
60 * Copy data allowing for unaligned accesses in network byte order
64 sldns_write_uint16(void *dst, uint16_t data)
66 #ifdef ALLOW_UNALIGNED_ACCESSES
67 * (uint16_t *) dst = htons(data);
69 uint8_t *p = (uint8_t *) dst;
70 p[0] = (uint8_t) ((data >> 8) & 0xff);
71 p[1] = (uint8_t) (data & 0xff);
76 sldns_write_uint32(void *dst, uint32_t data)
78 #ifdef ALLOW_UNALIGNED_ACCESSES
79 * (uint32_t *) dst = htonl(data);
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);
91 sldns_write_uint48(void *dst, uint64_t data)
93 uint8_t *p = (uint8_t *) dst;
94 p[0] = (uint8_t) ((data >> 40) & 0xff);
95 p[1] = (uint8_t) ((data >> 32) & 0xff);
96 p[2] = (uint8_t) ((data >> 24) & 0xff);
97 p[3] = (uint8_t) ((data >> 16) & 0xff);
98 p[4] = (uint8_t) ((data >> 8) & 0xff);
99 p[5] = (uint8_t) (data & 0xff);
106 * This file contains the definition of sldns_buffer, and functions to manipulate those.
110 * implementation of buffers to ease operations
112 * sldns_buffers can contain arbitrary information, per octet. You can write
113 * to the current end of a buffer, read from the current position, and
114 * access any data within it.
118 /** The current position used for reading/writing */
121 /** The read/write limit */
124 /** The amount of data the buffer can contain */
127 /** The data contained in the buffer */
130 /** If the buffer is fixed it cannot be resized */
133 /** The current state of the buffer. If writing to the buffer fails
134 * for any reason, this value is changed. This way, you can perform
135 * multiple writes in sequence and check for success afterwards. */
136 unsigned _status_err : 1;
138 typedef struct sldns_buffer sldns_buffer;
142 sldns_buffer_invariant(sldns_buffer *ATTR_UNUSED(buffer))
147 sldns_buffer_invariant(sldns_buffer *buffer)
149 assert(buffer != NULL);
150 assert(buffer->_position <= buffer->_limit);
151 assert(buffer->_limit <= buffer->_capacity);
152 assert(buffer->_data != NULL);
157 * creates a new buffer with the specified capacity.
159 * \param[in] capacity the size (in bytes) to allocate for the buffer
160 * \return the created buffer
162 sldns_buffer *sldns_buffer_new(size_t capacity);
165 * creates a buffer with the specified data. The data IS copied
166 * and MEMORY allocations are done. The buffer is not fixed and can
167 * be resized using buffer_reserve().
169 * \param[in] buffer pointer to the buffer to put the data in
170 * \param[in] data the data to encapsulate in the buffer
171 * \param[in] size the size of the data
173 void sldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size);
176 * Setup a buffer with the data pointed to. No data copied, no memory allocs.
177 * The buffer is fixed.
178 * \param[in] buffer pointer to the buffer to put the data in
179 * \param[in] data the data to encapsulate in the buffer
180 * \param[in] size the size of the data
182 void sldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size);
185 * clears the buffer and make it ready for writing. The buffer's limit
186 * is set to the capacity and the position is set to 0.
187 * \param[in] buffer the buffer to clear
189 INLINE void sldns_buffer_clear(sldns_buffer *buffer)
191 sldns_buffer_invariant(buffer);
193 /* reset status here? */
195 buffer->_position = 0;
196 buffer->_limit = buffer->_capacity;
200 * makes the buffer ready for reading the data that has been written to
201 * the buffer. The buffer's limit is set to the current position and
202 * the position is set to 0.
204 * \param[in] buffer the buffer to flip
206 INLINE void sldns_buffer_flip(sldns_buffer *buffer)
208 sldns_buffer_invariant(buffer);
210 buffer->_limit = buffer->_position;
211 buffer->_position = 0;
215 * make the buffer ready for re-reading the data. The buffer's
216 * position is reset to 0.
217 * \param[in] buffer the buffer to rewind
219 INLINE void sldns_buffer_rewind(sldns_buffer *buffer)
221 sldns_buffer_invariant(buffer);
223 buffer->_position = 0;
227 * returns the current position in the buffer (as a number of bytes)
228 * \param[in] buffer the buffer
229 * \return the current position
232 sldns_buffer_position(sldns_buffer *buffer)
234 return buffer->_position;
238 * sets the buffer's position to MARK. The position must be less than
239 * or equal to the buffer's limit.
240 * \param[in] buffer the buffer
241 * \param[in] mark the mark to use
244 sldns_buffer_set_position(sldns_buffer *buffer, size_t mark)
246 assert(mark <= buffer->_limit);
247 buffer->_position = mark;
251 * changes the buffer's position by COUNT bytes. The position must not
252 * be moved behind the buffer's limit or before the beginning of the
254 * \param[in] buffer the buffer
255 * \param[in] count the count to use
258 sldns_buffer_skip(sldns_buffer *buffer, ssize_t count)
260 assert(buffer->_position + count <= buffer->_limit);
261 buffer->_position += count;
265 * returns the maximum size of the buffer
270 sldns_buffer_limit(sldns_buffer *buffer)
272 return buffer->_limit;
276 * changes the buffer's limit. If the buffer's position is greater
277 * than the new limit the position is set to the limit.
278 * \param[in] buffer the buffer
279 * \param[in] limit the new limit
282 sldns_buffer_set_limit(sldns_buffer *buffer, size_t limit)
284 assert(limit <= buffer->_capacity);
285 buffer->_limit = limit;
286 if (buffer->_position > buffer->_limit)
287 buffer->_position = buffer->_limit;
291 * returns the number of bytes the buffer can hold.
292 * \param[in] buffer the buffer
293 * \return the number of bytes
296 sldns_buffer_capacity(sldns_buffer *buffer)
298 return buffer->_capacity;
302 * changes the buffer's capacity. The data is reallocated so any
303 * pointers to the data may become invalid. The buffer's limit is set
304 * to the buffer's new capacity.
305 * \param[in] buffer the buffer
306 * \param[in] capacity the capacity to use
307 * \return whether this failed or succeeded
309 int sldns_buffer_set_capacity(sldns_buffer *buffer, size_t capacity);
312 * ensures BUFFER can contain at least AMOUNT more bytes. The buffer's
313 * capacity is increased if necessary using buffer_set_capacity().
315 * The buffer's limit is always set to the (possibly increased)
317 * \param[in] buffer the buffer
318 * \param[in] amount amount to use
319 * \return whether this failed or succeeded
321 int sldns_buffer_reserve(sldns_buffer *buffer, size_t amount);
324 * returns a pointer to the data at the indicated position.
325 * \param[in] buffer the buffer
326 * \param[in] at position
327 * \return the pointer to the data
330 sldns_buffer_at(const sldns_buffer *buffer, size_t at)
332 assert(at <= buffer->_limit);
333 return buffer->_data + at;
337 * returns a pointer to the beginning of the buffer (the data at
339 * \param[in] buffer the buffer
340 * \return the pointer
343 sldns_buffer_begin(const sldns_buffer *buffer)
345 return sldns_buffer_at(buffer, 0);
349 * returns a pointer to the end of the buffer (the data at the buffer's
351 * \param[in] buffer the buffer
352 * \return the pointer
355 sldns_buffer_end(sldns_buffer *buffer)
357 return sldns_buffer_at(buffer, buffer->_limit);
361 * returns a pointer to the data at the buffer's current position.
362 * \param[in] buffer the buffer
363 * \return the pointer
366 sldns_buffer_current(sldns_buffer *buffer)
368 return sldns_buffer_at(buffer, buffer->_position);
372 * returns the number of bytes remaining between the indicated position and
374 * \param[in] buffer the buffer
375 * \param[in] at indicated position
376 * \return number of bytes
379 sldns_buffer_remaining_at(sldns_buffer *buffer, size_t at)
381 sldns_buffer_invariant(buffer);
382 assert(at <= buffer->_limit);
383 return at < buffer->_limit ? buffer->_limit - at : 0;
387 * returns the number of bytes remaining between the buffer's position and
389 * \param[in] buffer the buffer
390 * \return the number of bytes
393 sldns_buffer_remaining(sldns_buffer *buffer)
395 return sldns_buffer_remaining_at(buffer, buffer->_position);
399 * checks if the buffer has at least COUNT more bytes available.
400 * Before reading or writing the caller needs to ensure enough space
402 * \param[in] buffer the buffer
403 * \param[in] at indicated position
404 * \param[in] count how much is available
405 * \return true or false (as int?)
408 sldns_buffer_available_at(sldns_buffer *buffer, size_t at, size_t count)
410 return count <= sldns_buffer_remaining_at(buffer, at);
414 * checks if the buffer has count bytes available at the current position
415 * \param[in] buffer the buffer
416 * \param[in] count how much is available
417 * \return true or false (as int?)
420 sldns_buffer_available(sldns_buffer *buffer, size_t count)
422 return sldns_buffer_available_at(buffer, buffer->_position, count);
426 * writes the given data to the buffer at the specified position
427 * \param[in] buffer the buffer
428 * \param[in] at the position (in number of bytes) to write the data at
429 * \param[in] data pointer to the data to write to the buffer
430 * \param[in] count the number of bytes of data to write
433 sldns_buffer_write_at(sldns_buffer *buffer, size_t at, const void *data, size_t count)
435 assert(sldns_buffer_available_at(buffer, at, count));
436 memcpy(buffer->_data + at, data, count);
440 * set the given byte to the buffer at the specified position
441 * \param[in] buffer the buffer
442 * \param[in] at the position (in number of bytes) to write the data at
443 * \param[in] c the byte to set to the buffer
444 * \param[in] count the number of bytes of bytes to write
448 sldns_buffer_set_at(sldns_buffer *buffer, size_t at, int c, size_t count)
450 assert(sldns_buffer_available_at(buffer, at, count));
451 memset(buffer->_data + at, c, count);
456 * writes count bytes of data to the current position of the buffer
457 * \param[in] buffer the buffer
458 * \param[in] data the data to write
459 * \param[in] count the length of the data to write
462 sldns_buffer_write(sldns_buffer *buffer, const void *data, size_t count)
464 sldns_buffer_write_at(buffer, buffer->_position, data, count);
465 buffer->_position += count;
469 * copies the given (null-delimited) string to the specified position at the buffer
470 * \param[in] buffer the buffer
471 * \param[in] at the position in the buffer
472 * \param[in] str the string to write
475 sldns_buffer_write_string_at(sldns_buffer *buffer, size_t at, const char *str)
477 sldns_buffer_write_at(buffer, at, str, strlen(str));
481 * copies the given (null-delimited) string to the current position at the buffer
482 * \param[in] buffer the buffer
483 * \param[in] str the string to write
486 sldns_buffer_write_string(sldns_buffer *buffer, const char *str)
488 sldns_buffer_write(buffer, str, strlen(str));
492 * writes the given byte of data at the given position in the buffer
493 * \param[in] buffer the buffer
494 * \param[in] at the position in the buffer
495 * \param[in] data the 8 bits to write
498 sldns_buffer_write_u8_at(sldns_buffer *buffer, size_t at, uint8_t data)
500 assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
501 buffer->_data[at] = data;
505 * writes the given byte of data at the current position in the buffer
506 * \param[in] buffer the buffer
507 * \param[in] data the 8 bits to write
510 sldns_buffer_write_u8(sldns_buffer *buffer, uint8_t data)
512 sldns_buffer_write_u8_at(buffer, buffer->_position, data);
513 buffer->_position += sizeof(data);
517 * writes the given 2 byte integer at the given position in the buffer
518 * \param[in] buffer the buffer
519 * \param[in] at the position in the buffer
520 * \param[in] data the 16 bits to write
523 sldns_buffer_write_u16_at(sldns_buffer *buffer, size_t at, uint16_t data)
525 assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
526 sldns_write_uint16(buffer->_data + at, data);
530 * writes the given 2 byte integer at the current position in the buffer
531 * \param[in] buffer the buffer
532 * \param[in] data the 16 bits to write
535 sldns_buffer_write_u16(sldns_buffer *buffer, uint16_t data)
537 sldns_buffer_write_u16_at(buffer, buffer->_position, data);
538 buffer->_position += sizeof(data);
542 * writes the given 4 byte integer at the given position in the buffer
543 * \param[in] buffer the buffer
544 * \param[in] at the position in the buffer
545 * \param[in] data the 32 bits to write
548 sldns_buffer_write_u32_at(sldns_buffer *buffer, size_t at, uint32_t data)
550 assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
551 sldns_write_uint32(buffer->_data + at, data);
555 * writes the given 6 byte integer at the given position in the buffer
556 * \param[in] buffer the buffer
557 * \param[in] at the position in the buffer
558 * \param[in] data the (lower) 48 bits to write
561 sldns_buffer_write_u48_at(sldns_buffer *buffer, size_t at, uint64_t data)
563 assert(sldns_buffer_available_at(buffer, at, 6));
564 sldns_write_uint48(buffer->_data + at, data);
568 * writes the given 4 byte integer at the current position in the buffer
569 * \param[in] buffer the buffer
570 * \param[in] data the 32 bits to write
573 sldns_buffer_write_u32(sldns_buffer *buffer, uint32_t data)
575 sldns_buffer_write_u32_at(buffer, buffer->_position, data);
576 buffer->_position += sizeof(data);
580 * writes the given 6 byte integer at the current position in the buffer
581 * \param[in] buffer the buffer
582 * \param[in] data the 48 bits to write
585 sldns_buffer_write_u48(sldns_buffer *buffer, uint64_t data)
587 sldns_buffer_write_u48_at(buffer, buffer->_position, data);
588 buffer->_position += 6;
592 * copies count bytes of data at the given position to the given data-array
593 * \param[in] buffer the buffer
594 * \param[in] at the position in the buffer to start
595 * \param[out] data buffer to copy to
596 * \param[in] count the length of the data to copy
599 sldns_buffer_read_at(sldns_buffer *buffer, size_t at, void *data, size_t count)
601 assert(sldns_buffer_available_at(buffer, at, count));
602 memcpy(data, buffer->_data + at, count);
606 * copies count bytes of data at the current position to the given data-array
607 * \param[in] buffer the buffer
608 * \param[out] data buffer to copy to
609 * \param[in] count the length of the data to copy
612 sldns_buffer_read(sldns_buffer *buffer, void *data, size_t count)
614 sldns_buffer_read_at(buffer, buffer->_position, data, count);
615 buffer->_position += count;
619 * returns the byte value at the given position in the buffer
620 * \param[in] buffer the buffer
621 * \param[in] at the position in the buffer
622 * \return 1 byte integer
625 sldns_buffer_read_u8_at(sldns_buffer *buffer, size_t at)
627 assert(sldns_buffer_available_at(buffer, at, sizeof(uint8_t)));
628 return buffer->_data[at];
632 * returns the byte value at the current position in the buffer
633 * \param[in] buffer the buffer
634 * \return 1 byte integer
637 sldns_buffer_read_u8(sldns_buffer *buffer)
639 uint8_t result = sldns_buffer_read_u8_at(buffer, buffer->_position);
640 buffer->_position += sizeof(uint8_t);
645 * returns the 2-byte integer value at the given position in the buffer
646 * \param[in] buffer the buffer
647 * \param[in] at position in the buffer
648 * \return 2 byte integer
651 sldns_buffer_read_u16_at(sldns_buffer *buffer, size_t at)
653 assert(sldns_buffer_available_at(buffer, at, sizeof(uint16_t)));
654 return sldns_read_uint16(buffer->_data + at);
658 * returns the 2-byte integer value at the current position in the buffer
659 * \param[in] buffer the buffer
660 * \return 2 byte integer
663 sldns_buffer_read_u16(sldns_buffer *buffer)
665 uint16_t result = sldns_buffer_read_u16_at(buffer, buffer->_position);
666 buffer->_position += sizeof(uint16_t);
671 * returns the 4-byte integer value at the given position in the buffer
672 * \param[in] buffer the buffer
673 * \param[in] at position in the buffer
674 * \return 4 byte integer
677 sldns_buffer_read_u32_at(sldns_buffer *buffer, size_t at)
679 assert(sldns_buffer_available_at(buffer, at, sizeof(uint32_t)));
680 return sldns_read_uint32(buffer->_data + at);
684 * returns the 4-byte integer value at the current position in the buffer
685 * \param[in] buffer the buffer
686 * \return 4 byte integer
689 sldns_buffer_read_u32(sldns_buffer *buffer)
691 uint32_t result = sldns_buffer_read_u32_at(buffer, buffer->_position);
692 buffer->_position += sizeof(uint32_t);
697 * returns the status of the buffer
702 sldns_buffer_status(sldns_buffer *buffer)
704 return (int)buffer->_status_err;
708 * returns true if the status of the buffer is LDNS_STATUS_OK, false otherwise
709 * \param[in] buffer the buffer
710 * \return true or false
713 sldns_buffer_status_ok(sldns_buffer *buffer)
716 return sldns_buffer_status(buffer) == 0;
723 * prints to the buffer, increasing the capacity if required using
724 * buffer_reserve(). The buffer's position is set to the terminating '\\0'
725 * Returns the number of characters written (not including the
726 * terminating '\\0') or -1 on failure.
728 int sldns_buffer_printf(sldns_buffer *buffer, const char *format, ...)
729 ATTR_FORMAT(printf, 2, 3);
733 * \param[in] *buffer the buffer to be freed
735 void sldns_buffer_free(sldns_buffer *buffer);
738 * Copy contents of the from buffer to the result buffer and then flips
739 * the result buffer. Data will be silently truncated if the result buffer is
741 * \param[out] *result resulting buffer which is copied to.
742 * \param[in] *from what to copy to result.
744 void sldns_buffer_copy(sldns_buffer* result, sldns_buffer* from);
750 #endif /* LDNS_SBUFFER_H */