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 /** If the buffer is vfixed, no more than capacity bytes will be
134 * written to _data, however the _position counter will be updated
135 * with the amount that would have been written in consecutive
136 * writes. This allows for a modus operandi in which a sequence is
137 * written on a fixed capacity buffer (perhaps with _data on stack).
138 * When everything could be written, then the _data is immediately
139 * usable, if not, then a buffer could be allocated sized precisely
140 * to fit the data for a second attempt.
142 unsigned _vfixed : 1;
144 /** The current state of the buffer. If writing to the buffer fails
145 * for any reason, this value is changed. This way, you can perform
146 * multiple writes in sequence and check for success afterwards. */
147 unsigned _status_err : 1;
149 typedef struct sldns_buffer sldns_buffer;
153 sldns_buffer_invariant(sldns_buffer *ATTR_UNUSED(buffer))
158 sldns_buffer_invariant(sldns_buffer *buffer)
160 assert(buffer != NULL);
161 assert(buffer->_position <= buffer->_limit || buffer->_vfixed);
162 assert(buffer->_limit <= buffer->_capacity);
163 assert(buffer->_data != NULL || (buffer->_vfixed && buffer->_capacity == 0 && buffer->_limit == 0));
168 * creates a new buffer with the specified capacity.
170 * \param[in] capacity the size (in bytes) to allocate for the buffer
171 * \return the created buffer
173 sldns_buffer *sldns_buffer_new(size_t capacity);
176 * creates a buffer with the specified data. The data IS copied
177 * and MEMORY allocations are done. The buffer is not fixed and can
178 * be resized using buffer_reserve().
180 * \param[in] buffer pointer to the buffer to put the data in
181 * \param[in] data the data to encapsulate in the buffer
182 * \param[in] size the size of the data
184 void sldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size);
187 * Setup a buffer with the data pointed to. No data copied, no memory allocs.
188 * The buffer is fixed.
189 * \param[in] buffer pointer to the buffer to put the data in
190 * \param[in] data the data to encapsulate in the buffer
191 * \param[in] size the size of the data
193 void sldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size);
196 * Setup a buffer with the data pointed to. No data copied, no memory allocs.
197 * The buffer is "virtually" fixed. Writes beyond size (the capacity) will
198 * only update position, but no data will be written beyond capacity. This
199 * allows to determine how big the buffer should have been to contain all the
200 * written data, by looking at the position with sldns_buffer_position(),
201 * similarly to the return value of POSIX's snprintf.
202 * \param[in] buffer pointer to the buffer to put the data in
203 * \param[in] data the data to encapsulate in the buffer
204 * \param[in] size the size of the data
206 void sldns_buffer_init_vfixed_frm_data(sldns_buffer *buffer, void *data, size_t size);
209 * clears the buffer and make it ready for writing. The buffer's limit
210 * is set to the capacity and the position is set to 0.
211 * \param[in] buffer the buffer to clear
213 INLINE void sldns_buffer_clear(sldns_buffer *buffer)
215 sldns_buffer_invariant(buffer);
217 /* reset status here? */
219 buffer->_position = 0;
220 buffer->_limit = buffer->_capacity;
224 * makes the buffer ready for reading the data that has been written to
225 * the buffer. The buffer's limit is set to the current position and
226 * the position is set to 0.
228 * \param[in] buffer the buffer to flip
231 INLINE void sldns_buffer_flip(sldns_buffer *buffer)
233 sldns_buffer_invariant(buffer);
235 buffer->_limit = buffer->_position;
236 buffer->_position = 0;
240 * make the buffer ready for re-reading the data. The buffer's
241 * position is reset to 0.
242 * \param[in] buffer the buffer to rewind
244 INLINE void sldns_buffer_rewind(sldns_buffer *buffer)
246 sldns_buffer_invariant(buffer);
248 buffer->_position = 0;
252 * returns the current position in the buffer (as a number of bytes)
253 * \param[in] buffer the buffer
254 * \return the current position
257 sldns_buffer_position(sldns_buffer *buffer)
259 return buffer->_position;
263 * sets the buffer's position to MARK. The position must be less than
264 * or equal to the buffer's limit.
265 * \param[in] buffer the buffer
266 * \param[in] mark the mark to use
269 sldns_buffer_set_position(sldns_buffer *buffer, size_t mark)
271 assert(mark <= buffer->_limit || buffer->_vfixed);
272 buffer->_position = mark;
276 * changes the buffer's position by COUNT bytes. The position must not
277 * be moved behind the buffer's limit or before the beginning of the
279 * \param[in] buffer the buffer
280 * \param[in] count the count to use
283 sldns_buffer_skip(sldns_buffer *buffer, ssize_t count)
285 assert(buffer->_position + count <= buffer->_limit || buffer->_vfixed);
286 buffer->_position += count;
290 * returns the maximum size of the buffer
295 sldns_buffer_limit(sldns_buffer *buffer)
297 return buffer->_limit;
301 * changes the buffer's limit. If the buffer's position is greater
302 * than the new limit the position is set to the limit.
303 * \param[in] buffer the buffer
304 * \param[in] limit the new limit
307 sldns_buffer_set_limit(sldns_buffer *buffer, size_t limit)
309 assert(limit <= buffer->_capacity);
310 buffer->_limit = limit;
311 if (buffer->_position > buffer->_limit)
312 buffer->_position = buffer->_limit;
316 * returns the number of bytes the buffer can hold.
317 * \param[in] buffer the buffer
318 * \return the number of bytes
321 sldns_buffer_capacity(sldns_buffer *buffer)
323 return buffer->_capacity;
327 * changes the buffer's capacity. The data is reallocated so any
328 * pointers to the data may become invalid. The buffer's limit is set
329 * to the buffer's new capacity.
330 * \param[in] buffer the buffer
331 * \param[in] capacity the capacity to use
332 * \return whether this failed or succeeded
334 int sldns_buffer_set_capacity(sldns_buffer *buffer, size_t capacity);
337 * ensures BUFFER can contain at least AMOUNT more bytes. The buffer's
338 * capacity is increased if necessary using buffer_set_capacity().
340 * The buffer's limit is always set to the (possibly increased)
342 * \param[in] buffer the buffer
343 * \param[in] amount amount to use
344 * \return whether this failed or succeeded
346 int sldns_buffer_reserve(sldns_buffer *buffer, size_t amount);
349 * returns a pointer to the data at the indicated position.
350 * \param[in] buffer the buffer
351 * \param[in] at position
352 * \return the pointer to the data
355 sldns_buffer_at(const sldns_buffer *buffer, size_t at)
357 assert(at <= buffer->_limit || buffer->_vfixed);
358 return buffer->_data + at;
362 * returns a pointer to the beginning of the buffer (the data at
364 * \param[in] buffer the buffer
365 * \return the pointer
368 sldns_buffer_begin(const sldns_buffer *buffer)
370 return sldns_buffer_at(buffer, 0);
374 * returns a pointer to the end of the buffer (the data at the buffer's
376 * \param[in] buffer the buffer
377 * \return the pointer
380 sldns_buffer_end(sldns_buffer *buffer)
382 return sldns_buffer_at(buffer, buffer->_limit);
386 * returns a pointer to the data at the buffer's current position.
387 * \param[in] buffer the buffer
388 * \return the pointer
391 sldns_buffer_current(sldns_buffer *buffer)
393 return sldns_buffer_at(buffer, buffer->_position);
397 * returns the number of bytes remaining between the indicated position and
399 * \param[in] buffer the buffer
400 * \param[in] at indicated position
401 * \return number of bytes
404 sldns_buffer_remaining_at(sldns_buffer *buffer, size_t at)
406 sldns_buffer_invariant(buffer);
407 assert(at <= buffer->_limit || buffer->_vfixed);
408 return at < buffer->_limit ? buffer->_limit - at : 0;
412 * returns the number of bytes remaining between the buffer's position and
414 * \param[in] buffer the buffer
415 * \return the number of bytes
418 sldns_buffer_remaining(sldns_buffer *buffer)
420 return sldns_buffer_remaining_at(buffer, buffer->_position);
424 * checks if the buffer has at least COUNT more bytes available.
425 * Before reading or writing the caller needs to ensure enough space
427 * \param[in] buffer the buffer
428 * \param[in] at indicated position
429 * \param[in] count how much is available
430 * \return true or false (as int?)
433 sldns_buffer_available_at(sldns_buffer *buffer, size_t at, size_t count)
435 return count <= sldns_buffer_remaining_at(buffer, at);
439 * checks if the buffer has count bytes available at the current position
440 * \param[in] buffer the buffer
441 * \param[in] count how much is available
442 * \return true or false (as int?)
445 sldns_buffer_available(sldns_buffer *buffer, size_t count)
447 return sldns_buffer_available_at(buffer, buffer->_position, count);
451 * writes the given data to the buffer at the specified position
452 * \param[in] buffer the buffer
453 * \param[in] at the position (in number of bytes) to write the data at
454 * \param[in] data pointer to the data to write to the buffer
455 * \param[in] count the number of bytes of data to write
458 sldns_buffer_write_at(sldns_buffer *buffer, size_t at, const void *data, size_t count)
460 if (!buffer->_vfixed)
461 assert(sldns_buffer_available_at(buffer, at, count));
462 else if (sldns_buffer_remaining_at(buffer, at) == 0)
464 else if (count > sldns_buffer_remaining_at(buffer, at)) {
465 memcpy(buffer->_data + at, data,
466 sldns_buffer_remaining_at(buffer, at));
469 memcpy(buffer->_data + at, data, count);
473 * set the given byte to the buffer at the specified position
474 * \param[in] buffer the buffer
475 * \param[in] at the position (in number of bytes) to write the data at
476 * \param[in] c the byte to set to the buffer
477 * \param[in] count the number of bytes of bytes to write
481 sldns_buffer_set_at(sldns_buffer *buffer, size_t at, int c, size_t count)
483 if (!buffer->_vfixed)
484 assert(sldns_buffer_available_at(buffer, at, count));
485 else if (sldns_buffer_remaining_at(buffer, at) == 0)
487 else if (count > sldns_buffer_remaining_at(buffer, at)) {
488 memset(buffer->_data + at, c,
489 sldns_buffer_remaining_at(buffer, at));
492 memset(buffer->_data + at, c, count);
497 * writes count bytes of data to the current position of the buffer
498 * \param[in] buffer the buffer
499 * \param[in] data the data to write
500 * \param[in] count the length of the data to write
503 sldns_buffer_write(sldns_buffer *buffer, const void *data, size_t count)
505 sldns_buffer_write_at(buffer, buffer->_position, data, count);
506 buffer->_position += count;
510 * copies the given (null-delimited) string to the specified position at the buffer
511 * \param[in] buffer the buffer
512 * \param[in] at the position in the buffer
513 * \param[in] str the string to write
516 sldns_buffer_write_string_at(sldns_buffer *buffer, size_t at, const char *str)
518 sldns_buffer_write_at(buffer, at, str, strlen(str));
522 * copies the given (null-delimited) string to the current position at the buffer
523 * \param[in] buffer the buffer
524 * \param[in] str the string to write
527 sldns_buffer_write_string(sldns_buffer *buffer, const char *str)
529 sldns_buffer_write(buffer, str, strlen(str));
533 * writes the given byte of data at the given position in the buffer
534 * \param[in] buffer the buffer
535 * \param[in] at the position in the buffer
536 * \param[in] data the 8 bits to write
539 sldns_buffer_write_u8_at(sldns_buffer *buffer, size_t at, uint8_t data)
541 if (buffer->_vfixed && at + sizeof(data) > buffer->_limit) return;
542 assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
543 buffer->_data[at] = data;
547 * writes the given byte of data at the current position in the buffer
548 * \param[in] buffer the buffer
549 * \param[in] data the 8 bits to write
552 sldns_buffer_write_u8(sldns_buffer *buffer, uint8_t data)
554 sldns_buffer_write_u8_at(buffer, buffer->_position, data);
555 buffer->_position += sizeof(data);
559 * writes the given 2 byte integer at the given position in the buffer
560 * \param[in] buffer the buffer
561 * \param[in] at the position in the buffer
562 * \param[in] data the 16 bits to write
565 sldns_buffer_write_u16_at(sldns_buffer *buffer, size_t at, uint16_t data)
567 if (buffer->_vfixed && at + sizeof(data) > buffer->_limit) return;
568 assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
569 sldns_write_uint16(buffer->_data + at, data);
573 * writes the given 2 byte integer at the current position in the buffer
574 * \param[in] buffer the buffer
575 * \param[in] data the 16 bits to write
578 sldns_buffer_write_u16(sldns_buffer *buffer, uint16_t data)
580 sldns_buffer_write_u16_at(buffer, buffer->_position, data);
581 buffer->_position += sizeof(data);
585 * writes the given 4 byte integer at the given position in the buffer
586 * \param[in] buffer the buffer
587 * \param[in] at the position in the buffer
588 * \param[in] data the 32 bits to write
591 sldns_buffer_write_u32_at(sldns_buffer *buffer, size_t at, uint32_t data)
593 if (buffer->_vfixed && at + sizeof(data) > buffer->_limit) return;
594 assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
595 sldns_write_uint32(buffer->_data + at, data);
599 * writes the given 6 byte integer at the given position in the buffer
600 * \param[in] buffer the buffer
601 * \param[in] at the position in the buffer
602 * \param[in] data the (lower) 48 bits to write
605 sldns_buffer_write_u48_at(sldns_buffer *buffer, size_t at, uint64_t data)
607 if (buffer->_vfixed && at + 6 > buffer->_limit) return;
608 assert(sldns_buffer_available_at(buffer, at, 6));
609 sldns_write_uint48(buffer->_data + at, data);
613 * writes the given 4 byte integer at the current position in the buffer
614 * \param[in] buffer the buffer
615 * \param[in] data the 32 bits to write
618 sldns_buffer_write_u32(sldns_buffer *buffer, uint32_t data)
620 sldns_buffer_write_u32_at(buffer, buffer->_position, data);
621 buffer->_position += sizeof(data);
625 * writes the given 6 byte integer at the current position in the buffer
626 * \param[in] buffer the buffer
627 * \param[in] data the 48 bits to write
630 sldns_buffer_write_u48(sldns_buffer *buffer, uint64_t data)
632 sldns_buffer_write_u48_at(buffer, buffer->_position, data);
633 buffer->_position += 6;
637 * copies count bytes of data at the given position to the given data-array
638 * \param[in] buffer the buffer
639 * \param[in] at the position in the buffer to start
640 * \param[out] data buffer to copy to
641 * \param[in] count the length of the data to copy
644 sldns_buffer_read_at(sldns_buffer *buffer, size_t at, void *data, size_t count)
646 assert(sldns_buffer_available_at(buffer, at, count));
647 memcpy(data, buffer->_data + at, count);
651 * copies count bytes of data at the current position to the given data-array
652 * \param[in] buffer the buffer
653 * \param[out] data buffer to copy to
654 * \param[in] count the length of the data to copy
657 sldns_buffer_read(sldns_buffer *buffer, void *data, size_t count)
659 sldns_buffer_read_at(buffer, buffer->_position, data, count);
660 buffer->_position += count;
664 * returns the byte value at the given position in the buffer
665 * \param[in] buffer the buffer
666 * \param[in] at the position in the buffer
667 * \return 1 byte integer
670 sldns_buffer_read_u8_at(sldns_buffer *buffer, size_t at)
672 assert(sldns_buffer_available_at(buffer, at, sizeof(uint8_t)));
673 return buffer->_data[at];
677 * returns the byte value at the current position in the buffer
678 * \param[in] buffer the buffer
679 * \return 1 byte integer
682 sldns_buffer_read_u8(sldns_buffer *buffer)
684 uint8_t result = sldns_buffer_read_u8_at(buffer, buffer->_position);
685 buffer->_position += sizeof(uint8_t);
690 * returns the 2-byte integer value at the given position in the buffer
691 * \param[in] buffer the buffer
692 * \param[in] at position in the buffer
693 * \return 2 byte integer
696 sldns_buffer_read_u16_at(sldns_buffer *buffer, size_t at)
698 assert(sldns_buffer_available_at(buffer, at, sizeof(uint16_t)));
699 return sldns_read_uint16(buffer->_data + at);
703 * returns the 2-byte integer value at the current position in the buffer
704 * \param[in] buffer the buffer
705 * \return 2 byte integer
708 sldns_buffer_read_u16(sldns_buffer *buffer)
710 uint16_t result = sldns_buffer_read_u16_at(buffer, buffer->_position);
711 buffer->_position += sizeof(uint16_t);
716 * returns the 4-byte integer value at the given position in the buffer
717 * \param[in] buffer the buffer
718 * \param[in] at position in the buffer
719 * \return 4 byte integer
722 sldns_buffer_read_u32_at(sldns_buffer *buffer, size_t at)
724 assert(sldns_buffer_available_at(buffer, at, sizeof(uint32_t)));
725 return sldns_read_uint32(buffer->_data + at);
729 * returns the 4-byte integer value at the current position in the buffer
730 * \param[in] buffer the buffer
731 * \return 4 byte integer
734 sldns_buffer_read_u32(sldns_buffer *buffer)
736 uint32_t result = sldns_buffer_read_u32_at(buffer, buffer->_position);
737 buffer->_position += sizeof(uint32_t);
742 * returns the status of the buffer
747 sldns_buffer_status(sldns_buffer *buffer)
749 return (int)buffer->_status_err;
753 * returns true if the status of the buffer is LDNS_STATUS_OK, false otherwise
754 * \param[in] buffer the buffer
755 * \return true or false
758 sldns_buffer_status_ok(sldns_buffer *buffer)
761 return sldns_buffer_status(buffer) == 0;
768 * prints to the buffer, increasing the capacity if required using
769 * buffer_reserve(). The buffer's position is set to the terminating '\\0'
770 * Returns the number of characters written (not including the
771 * terminating '\\0') or -1 on failure.
773 int sldns_buffer_printf(sldns_buffer *buffer, const char *format, ...)
774 ATTR_FORMAT(printf, 2, 3);
778 * \param[in] *buffer the buffer to be freed
781 void sldns_buffer_free(sldns_buffer *buffer);
784 * Makes the buffer fixed and returns a pointer to the data. The
785 * caller is responsible for free'ing the result.
786 * \param[in] *buffer the buffer to be exported
789 void *sldns_buffer_export(sldns_buffer *buffer);
792 * Copy contents of the from buffer to the result buffer and then flips
793 * the result buffer. Data will be silently truncated if the result buffer is
795 * \param[out] *result resulting buffer which is copied to.
796 * \param[in] *from what to copy to result.
798 void sldns_buffer_copy(sldns_buffer* result, sldns_buffer* from);
804 #endif /* LDNS_SBUFFER_H */