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);
93 * This file contains the definition of sldns_buffer, and functions to manipulate those.
97 * implementation of buffers to ease operations
99 * sldns_buffers can contain arbitrary information, per octet. You can write
100 * to the current end of a buffer, read from the current position, and
101 * access any data within it.
105 /** The current position used for reading/writing */
108 /** The read/write limit */
111 /** The amount of data the buffer can contain */
114 /** The data contained in the buffer */
117 /** If the buffer is fixed it cannot be resized */
120 /** The current state of the buffer. If writing to the buffer fails
121 * for any reason, this value is changed. This way, you can perform
122 * multiple writes in sequence and check for success afterwards. */
123 unsigned _status_err
: 1;
125 typedef struct sldns_buffer sldns_buffer
;
129 sldns_buffer_invariant(sldns_buffer
*ATTR_UNUSED(buffer
))
134 sldns_buffer_invariant(sldns_buffer
*buffer
)
136 assert(buffer
!= NULL
);
137 assert(buffer
->_position
<= buffer
->_limit
);
138 assert(buffer
->_limit
<= buffer
->_capacity
);
139 assert(buffer
->_data
!= NULL
);
144 * creates a new buffer with the specified capacity.
146 * \param[in] capacity the size (in bytes) to allocate for the buffer
147 * \return the created buffer
149 sldns_buffer
*sldns_buffer_new(size_t capacity
);
152 * creates a buffer with the specified data. The data IS copied
153 * and MEMORY allocations are done. The buffer is not fixed and can
154 * be resized using buffer_reserve().
156 * \param[in] buffer pointer to the buffer to put the data in
157 * \param[in] data the data to encapsulate in the buffer
158 * \param[in] size the size of the data
160 void sldns_buffer_new_frm_data(sldns_buffer
*buffer
, void *data
, size_t size
);
163 * Setup a buffer with the data pointed to. No data copied, no memory allocs.
164 * The buffer is fixed.
165 * \param[in] buffer pointer to the buffer to put the data in
166 * \param[in] data the data to encapsulate in the buffer
167 * \param[in] size the size of the data
169 void sldns_buffer_init_frm_data(sldns_buffer
*buffer
, void *data
, size_t size
);
172 * clears the buffer and make it ready for writing. The buffer's limit
173 * is set to the capacity and the position is set to 0.
174 * \param[in] buffer the buffer to clear
176 INLINE
void sldns_buffer_clear(sldns_buffer
*buffer
)
178 sldns_buffer_invariant(buffer
);
180 /* reset status here? */
182 buffer
->_position
= 0;
183 buffer
->_limit
= buffer
->_capacity
;
187 * makes the buffer ready for reading the data that has been written to
188 * the buffer. The buffer's limit is set to the current position and
189 * the position is set to 0.
191 * \param[in] buffer the buffer to flip
194 INLINE
void sldns_buffer_flip(sldns_buffer
*buffer
)
196 sldns_buffer_invariant(buffer
);
198 buffer
->_limit
= buffer
->_position
;
199 buffer
->_position
= 0;
203 * make the buffer ready for re-reading the data. The buffer's
204 * position is reset to 0.
205 * \param[in] buffer the buffer to rewind
207 INLINE
void sldns_buffer_rewind(sldns_buffer
*buffer
)
209 sldns_buffer_invariant(buffer
);
211 buffer
->_position
= 0;
215 * returns the current position in the buffer (as a number of bytes)
216 * \param[in] buffer the buffer
217 * \return the current position
220 sldns_buffer_position(sldns_buffer
*buffer
)
222 return buffer
->_position
;
226 * sets the buffer's position to MARK. The position must be less than
227 * or equal to the buffer's limit.
228 * \param[in] buffer the buffer
229 * \param[in] mark the mark to use
232 sldns_buffer_set_position(sldns_buffer
*buffer
, size_t mark
)
234 assert(mark
<= buffer
->_limit
);
235 buffer
->_position
= mark
;
239 * changes the buffer's position by COUNT bytes. The position must not
240 * be moved behind the buffer's limit or before the beginning of the
242 * \param[in] buffer the buffer
243 * \param[in] count the count to use
246 sldns_buffer_skip(sldns_buffer
*buffer
, ssize_t count
)
248 assert(buffer
->_position
+ count
<= buffer
->_limit
);
249 buffer
->_position
+= count
;
253 * returns the maximum size of the buffer
258 sldns_buffer_limit(sldns_buffer
*buffer
)
260 return buffer
->_limit
;
264 * changes the buffer's limit. If the buffer's position is greater
265 * than the new limit the position is set to the limit.
266 * \param[in] buffer the buffer
267 * \param[in] limit the new limit
270 sldns_buffer_set_limit(sldns_buffer
*buffer
, size_t limit
)
272 assert(limit
<= buffer
->_capacity
);
273 buffer
->_limit
= limit
;
274 if (buffer
->_position
> buffer
->_limit
)
275 buffer
->_position
= buffer
->_limit
;
279 * returns the number of bytes the buffer can hold.
280 * \param[in] buffer the buffer
281 * \return the number of bytes
284 sldns_buffer_capacity(sldns_buffer
*buffer
)
286 return buffer
->_capacity
;
290 * changes the buffer's capacity. The data is reallocated so any
291 * pointers to the data may become invalid. The buffer's limit is set
292 * to the buffer's new capacity.
293 * \param[in] buffer the buffer
294 * \param[in] capacity the capacity to use
295 * \return whether this failed or succeeded
297 int sldns_buffer_set_capacity(sldns_buffer
*buffer
, size_t capacity
);
300 * ensures BUFFER can contain at least AMOUNT more bytes. The buffer's
301 * capacity is increased if necessary using buffer_set_capacity().
303 * The buffer's limit is always set to the (possibly increased)
305 * \param[in] buffer the buffer
306 * \param[in] amount amount to use
307 * \return whether this failed or succeeded
309 int sldns_buffer_reserve(sldns_buffer
*buffer
, size_t amount
);
312 * returns a pointer to the data at the indicated position.
313 * \param[in] buffer the buffer
314 * \param[in] at position
315 * \return the pointer to the data
318 sldns_buffer_at(const sldns_buffer
*buffer
, size_t at
)
320 assert(at
<= buffer
->_limit
);
321 return buffer
->_data
+ at
;
325 * returns a pointer to the beginning of the buffer (the data at
327 * \param[in] buffer the buffer
328 * \return the pointer
331 sldns_buffer_begin(const sldns_buffer
*buffer
)
333 return sldns_buffer_at(buffer
, 0);
337 * returns a pointer to the end of the buffer (the data at the buffer's
339 * \param[in] buffer the buffer
340 * \return the pointer
343 sldns_buffer_end(sldns_buffer
*buffer
)
345 return sldns_buffer_at(buffer
, buffer
->_limit
);
349 * returns a pointer to the data at the buffer's current position.
350 * \param[in] buffer the buffer
351 * \return the pointer
354 sldns_buffer_current(sldns_buffer
*buffer
)
356 return sldns_buffer_at(buffer
, buffer
->_position
);
360 * returns the number of bytes remaining between the indicated position and
362 * \param[in] buffer the buffer
363 * \param[in] at indicated position
364 * \return number of bytes
367 sldns_buffer_remaining_at(sldns_buffer
*buffer
, size_t at
)
369 sldns_buffer_invariant(buffer
);
370 assert(at
<= buffer
->_limit
);
371 return buffer
->_limit
- at
;
375 * returns the number of bytes remaining between the buffer's position and
377 * \param[in] buffer the buffer
378 * \return the number of bytes
381 sldns_buffer_remaining(sldns_buffer
*buffer
)
383 return sldns_buffer_remaining_at(buffer
, buffer
->_position
);
387 * checks if the buffer has at least COUNT more bytes available.
388 * Before reading or writing the caller needs to ensure enough space
390 * \param[in] buffer the buffer
391 * \param[in] at indicated position
392 * \param[in] count how much is available
393 * \return true or false (as int?)
396 sldns_buffer_available_at(sldns_buffer
*buffer
, size_t at
, size_t count
)
398 return count
<= sldns_buffer_remaining_at(buffer
, at
);
402 * checks if the buffer has count bytes available at the current position
403 * \param[in] buffer the buffer
404 * \param[in] count how much is available
405 * \return true or false (as int?)
408 sldns_buffer_available(sldns_buffer
*buffer
, size_t count
)
410 return sldns_buffer_available_at(buffer
, buffer
->_position
, count
);
414 * writes the given data to the buffer at the specified position
415 * \param[in] buffer the buffer
416 * \param[in] at the position (in number of bytes) to write the data at
417 * \param[in] data pointer to the data to write to the buffer
418 * \param[in] count the number of bytes of data to write
421 sldns_buffer_write_at(sldns_buffer
*buffer
, size_t at
, const void *data
, size_t count
)
423 assert(sldns_buffer_available_at(buffer
, at
, count
));
424 memcpy(buffer
->_data
+ at
, data
, count
);
428 * writes count bytes of data to the current position of the buffer
429 * \param[in] buffer the buffer
430 * \param[in] data the data to write
431 * \param[in] count the lenght of the data to write
434 sldns_buffer_write(sldns_buffer
*buffer
, const void *data
, size_t count
)
436 sldns_buffer_write_at(buffer
, buffer
->_position
, data
, count
);
437 buffer
->_position
+= count
;
441 * copies the given (null-delimited) string to the specified position at the buffer
442 * \param[in] buffer the buffer
443 * \param[in] at the position in the buffer
444 * \param[in] str the string to write
447 sldns_buffer_write_string_at(sldns_buffer
*buffer
, size_t at
, const char *str
)
449 sldns_buffer_write_at(buffer
, at
, str
, strlen(str
));
453 * copies the given (null-delimited) string to the current position at the buffer
454 * \param[in] buffer the buffer
455 * \param[in] str the string to write
458 sldns_buffer_write_string(sldns_buffer
*buffer
, const char *str
)
460 sldns_buffer_write(buffer
, str
, strlen(str
));
464 * writes the given byte of data at the given position in the buffer
465 * \param[in] buffer the buffer
466 * \param[in] at the position in the buffer
467 * \param[in] data the 8 bits to write
470 sldns_buffer_write_u8_at(sldns_buffer
*buffer
, size_t at
, uint8_t data
)
472 assert(sldns_buffer_available_at(buffer
, at
, sizeof(data
)));
473 buffer
->_data
[at
] = data
;
477 * writes the given byte of data at the current position in the buffer
478 * \param[in] buffer the buffer
479 * \param[in] data the 8 bits to write
482 sldns_buffer_write_u8(sldns_buffer
*buffer
, uint8_t data
)
484 sldns_buffer_write_u8_at(buffer
, buffer
->_position
, data
);
485 buffer
->_position
+= sizeof(data
);
489 * writes the given 2 byte integer at the given position in the buffer
490 * \param[in] buffer the buffer
491 * \param[in] at the position in the buffer
492 * \param[in] data the 16 bits to write
495 sldns_buffer_write_u16_at(sldns_buffer
*buffer
, size_t at
, uint16_t data
)
497 assert(sldns_buffer_available_at(buffer
, at
, sizeof(data
)));
498 sldns_write_uint16(buffer
->_data
+ at
, data
);
502 * writes the given 2 byte integer at the current position in the buffer
503 * \param[in] buffer the buffer
504 * \param[in] data the 16 bits to write
507 sldns_buffer_write_u16(sldns_buffer
*buffer
, uint16_t data
)
509 sldns_buffer_write_u16_at(buffer
, buffer
->_position
, data
);
510 buffer
->_position
+= sizeof(data
);
514 * writes the given 4 byte integer at the given position in the buffer
515 * \param[in] buffer the buffer
516 * \param[in] at the position in the buffer
517 * \param[in] data the 32 bits to write
520 sldns_buffer_write_u32_at(sldns_buffer
*buffer
, size_t at
, uint32_t data
)
522 assert(sldns_buffer_available_at(buffer
, at
, sizeof(data
)));
523 sldns_write_uint32(buffer
->_data
+ at
, data
);
527 * writes the given 4 byte integer at the current position in the buffer
528 * \param[in] buffer the buffer
529 * \param[in] data the 32 bits to write
532 sldns_buffer_write_u32(sldns_buffer
*buffer
, uint32_t data
)
534 sldns_buffer_write_u32_at(buffer
, buffer
->_position
, data
);
535 buffer
->_position
+= sizeof(data
);
539 * copies count bytes of data at the given position to the given data-array
540 * \param[in] buffer the buffer
541 * \param[in] at the position in the buffer to start
542 * \param[out] data buffer to copy to
543 * \param[in] count the length of the data to copy
546 sldns_buffer_read_at(sldns_buffer
*buffer
, size_t at
, void *data
, size_t count
)
548 assert(sldns_buffer_available_at(buffer
, at
, count
));
549 memcpy(data
, buffer
->_data
+ at
, count
);
553 * copies count bytes of data at the current position to the given data-array
554 * \param[in] buffer the buffer
555 * \param[out] data buffer to copy to
556 * \param[in] count the length of the data to copy
559 sldns_buffer_read(sldns_buffer
*buffer
, void *data
, size_t count
)
561 sldns_buffer_read_at(buffer
, buffer
->_position
, data
, count
);
562 buffer
->_position
+= count
;
566 * returns the byte value at the given position in the buffer
567 * \param[in] buffer the buffer
568 * \param[in] at the position in the buffer
569 * \return 1 byte integer
572 sldns_buffer_read_u8_at(sldns_buffer
*buffer
, size_t at
)
574 assert(sldns_buffer_available_at(buffer
, at
, sizeof(uint8_t)));
575 return buffer
->_data
[at
];
579 * returns the byte value at the current position in the buffer
580 * \param[in] buffer the buffer
581 * \return 1 byte integer
584 sldns_buffer_read_u8(sldns_buffer
*buffer
)
586 uint8_t result
= sldns_buffer_read_u8_at(buffer
, buffer
->_position
);
587 buffer
->_position
+= sizeof(uint8_t);
592 * returns the 2-byte integer value at the given position in the buffer
593 * \param[in] buffer the buffer
594 * \param[in] at position in the buffer
595 * \return 2 byte integer
598 sldns_buffer_read_u16_at(sldns_buffer
*buffer
, size_t at
)
600 assert(sldns_buffer_available_at(buffer
, at
, sizeof(uint16_t)));
601 return sldns_read_uint16(buffer
->_data
+ at
);
605 * returns the 2-byte integer value at the current position in the buffer
606 * \param[in] buffer the buffer
607 * \return 2 byte integer
610 sldns_buffer_read_u16(sldns_buffer
*buffer
)
612 uint16_t result
= sldns_buffer_read_u16_at(buffer
, buffer
->_position
);
613 buffer
->_position
+= sizeof(uint16_t);
618 * returns the 4-byte integer value at the given position in the buffer
619 * \param[in] buffer the buffer
620 * \param[in] at position in the buffer
621 * \return 4 byte integer
624 sldns_buffer_read_u32_at(sldns_buffer
*buffer
, size_t at
)
626 assert(sldns_buffer_available_at(buffer
, at
, sizeof(uint32_t)));
627 return sldns_read_uint32(buffer
->_data
+ at
);
631 * returns the 4-byte integer value at the current position in the buffer
632 * \param[in] buffer the buffer
633 * \return 4 byte integer
636 sldns_buffer_read_u32(sldns_buffer
*buffer
)
638 uint32_t result
= sldns_buffer_read_u32_at(buffer
, buffer
->_position
);
639 buffer
->_position
+= sizeof(uint32_t);
644 * returns the status of the buffer
649 sldns_buffer_status(sldns_buffer
*buffer
)
651 return (int)buffer
->_status_err
;
655 * returns true if the status of the buffer is LDNS_STATUS_OK, false otherwise
656 * \param[in] buffer the buffer
657 * \return true or false
660 sldns_buffer_status_ok(sldns_buffer
*buffer
)
663 return sldns_buffer_status(buffer
) == 0;
670 * prints to the buffer, increasing the capacity if required using
671 * buffer_reserve(). The buffer's position is set to the terminating '\\0'
672 * Returns the number of characters written (not including the
673 * terminating '\\0') or -1 on failure.
675 int sldns_buffer_printf(sldns_buffer
*buffer
, const char *format
, ...)
676 ATTR_FORMAT(printf
, 2, 3);
680 * \param[in] *buffer the buffer to be freed
683 void sldns_buffer_free(sldns_buffer
*buffer
);
686 * Makes the buffer fixed and returns a pointer to the data. The
687 * caller is responsible for free'ing the result.
688 * \param[in] *buffer the buffer to be exported
691 void *sldns_buffer_export(sldns_buffer
*buffer
);
694 * Copy contents of the from buffer to the result buffer and then flips
695 * the result buffer. Data will be silently truncated if the result buffer is
697 * \param[out] *result resulting buffer which is copied to.
698 * \param[in] *from what to copy to result.
700 void sldns_buffer_copy(sldns_buffer
* result
, sldns_buffer
* from
);
706 #endif /* LDNS_SBUFFER_H */