xref: /dragonfly/contrib/ldns/ldns/buffer.h (revision f9993810)
1 /*
2  * buffer.h -- generic memory buffer.
3  *
4  * Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
5  *
6  * See LICENSE for the license.
7  *
8  *
9  * The buffer module implements a generic buffer.  The API is based on
10  * the java.nio.Buffer interface.
11  */
12 
13 #ifndef LDNS_BUFFER_H
14 #define LDNS_BUFFER_H
15 
16 #include <assert.h>
17 #include <stdarg.h>
18 #include <string.h>
19 
20 #include <ldns/error.h>
21 #include <ldns/common.h>
22 
23 #include "ldns/util.h"
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 
29 /**
30  * number of initial bytes in buffer of
31  * which we cannot tell the size before hand
32  */
33 #define LDNS_MIN_BUFLEN	512
34 
35 /**
36  * \file buffer.h
37  *
38  * This file contains the definition of ldns_buffer, and functions to manipulate those.
39  */
40 
41 /**
42  * implementation of buffers to ease operations
43  *
44  * ldns_buffers can contain arbitrary information, per octet. You can write
45  * to the current end of a buffer, read from the current position, and
46  * access any data within it.
47  *
48  * Example use of buffers is in the source code of \ref host2str.c
49  */
50 struct ldns_struct_buffer
51 {
52 	/** The current position used for reading/writing */
53 	size_t   _position;
54 
55 	/** The read/write limit */
56 	size_t   _limit;
57 
58 	/** The amount of data the buffer can contain */
59 	size_t   _capacity;
60 
61 	/** The data contained in the buffer */
62 	uint8_t *_data;
63 
64 	/** If the buffer is fixed it cannot be resized */
65 	unsigned _fixed : 1;
66 
67 	/** The current state of the buffer. If writing to the buffer fails
68 	 * for any reason, this value is changed. This way, you can perform
69 	 * multiple writes in sequence and check for success afterwards. */
70 	ldns_status _status;
71 };
72 typedef struct ldns_struct_buffer ldns_buffer;
73 
74 
75 #ifdef NDEBUG
76 INLINE void
77 ldns_buffer_invariant(const ldns_buffer *ATTR_UNUSED(buffer))
78 {
79 }
80 #else
81 INLINE void
82 ldns_buffer_invariant(const ldns_buffer *buffer)
83 {
84 	assert(buffer != NULL);
85 	assert(buffer->_position <= buffer->_limit);
86 	assert(buffer->_limit <= buffer->_capacity);
87 	assert(buffer->_data != NULL);
88 }
89 #endif
90 
91 /**
92  * creates a new buffer with the specified capacity.
93  *
94  * \param[in] capacity the size (in bytes) to allocate for the buffer
95  * \return the created buffer
96  */
97 ldns_buffer *ldns_buffer_new(size_t capacity);
98 
99 /**
100  * creates a buffer with the specified data.  The data IS copied
101  * and MEMORY allocations are done.  The buffer is not fixed and can
102  * be resized using buffer_reserve().
103  *
104  * \param[in] buffer pointer to the buffer to put the data in
105  * \param[in] data the data to encapsulate in the buffer
106  * \param[in] size the size of the data
107  */
108 void ldns_buffer_new_frm_data(ldns_buffer *buffer, const void *data, size_t size);
109 
110 /**
111  * clears the buffer and make it ready for writing.  The buffer's limit
112  * is set to the capacity and the position is set to 0.
113  * \param[in] buffer the buffer to clear
114  */
115 INLINE void ldns_buffer_clear(ldns_buffer *buffer)
116 {
117 	ldns_buffer_invariant(buffer);
118 
119 	/* reset status here? */
120 
121 	buffer->_position = 0;
122 	buffer->_limit = buffer->_capacity;
123 }
124 
125 /**
126  * makes the buffer ready for reading the data that has been written to
127  * the buffer.  The buffer's limit is set to the current position and
128  * the position is set to 0.
129  *
130  * \param[in] buffer the buffer to flip
131  * \return void
132  */
133 INLINE void ldns_buffer_flip(ldns_buffer *buffer)
134 {
135 	ldns_buffer_invariant(buffer);
136 
137 	buffer->_limit = buffer->_position;
138 	buffer->_position = 0;
139 }
140 
141 /**
142  * make the buffer ready for re-reading the data.  The buffer's
143  * position is reset to 0.
144  * \param[in] buffer the buffer to rewind
145  */
146 INLINE void ldns_buffer_rewind(ldns_buffer *buffer)
147 {
148 	ldns_buffer_invariant(buffer);
149 
150 	buffer->_position = 0;
151 }
152 
153 /**
154  * returns the current position in the buffer (as a number of bytes)
155  * \param[in] buffer the buffer
156  * \return the current position
157  */
158 INLINE size_t
159 ldns_buffer_position(const ldns_buffer *buffer)
160 {
161 	return buffer->_position;
162 }
163 
164 /**
165  * sets the buffer's position to MARK.  The position must be less than
166  * or equal to the buffer's limit.
167  * \param[in] buffer the buffer
168  * \param[in] mark the mark to use
169  */
170 INLINE void
171 ldns_buffer_set_position(ldns_buffer *buffer, size_t mark)
172 {
173 	assert(mark <= buffer->_limit);
174 	buffer->_position = mark;
175 }
176 
177 /**
178  * changes the buffer's position by COUNT bytes.  The position must not
179  * be moved behind the buffer's limit or before the beginning of the
180  * buffer.
181  * \param[in] buffer the buffer
182  * \param[in] count the count to use
183  */
184 INLINE void
185 ldns_buffer_skip(ldns_buffer *buffer, ssize_t count)
186 {
187 	assert(buffer->_position + count <= buffer->_limit);
188 	buffer->_position += count;
189 }
190 
191 /**
192  * returns the maximum size of the buffer
193  * \param[in] buffer
194  * \return the size
195  */
196 INLINE size_t
197 ldns_buffer_limit(const ldns_buffer *buffer)
198 {
199 	return buffer->_limit;
200 }
201 
202 /**
203  * changes the buffer's limit.  If the buffer's position is greater
204  * than the new limit the position is set to the limit.
205  * \param[in] buffer the buffer
206  * \param[in] limit the new limit
207  */
208 INLINE void
209 ldns_buffer_set_limit(ldns_buffer *buffer, size_t limit)
210 {
211 	assert(limit <= buffer->_capacity);
212 	buffer->_limit = limit;
213 	if (buffer->_position > buffer->_limit)
214 		buffer->_position = buffer->_limit;
215 }
216 
217 /**
218  * returns the number of bytes the buffer can hold.
219  * \param[in] buffer the buffer
220  * \return the number of bytes
221  */
222 INLINE size_t
223 ldns_buffer_capacity(const ldns_buffer *buffer)
224 {
225 	return buffer->_capacity;
226 }
227 
228 /**
229  * changes the buffer's capacity.  The data is reallocated so any
230  * pointers to the data may become invalid.  The buffer's limit is set
231  * to the buffer's new capacity.
232  * \param[in] buffer the buffer
233  * \param[in] capacity the capacity to use
234  * \return whether this failed or succeeded
235  */
236 bool ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity);
237 
238 /**
239  * ensures BUFFER can contain at least AMOUNT more bytes.  The buffer's
240  * capacity is increased if necessary using buffer_set_capacity().
241  *
242  * The buffer's limit is always set to the (possibly increased)
243  * capacity.
244  * \param[in] buffer the buffer
245  * \param[in] amount amount to use
246  * \return whether this failed or succeeded
247  */
248 bool ldns_buffer_reserve(ldns_buffer *buffer, size_t amount);
249 
250 /**
251  * returns a pointer to the data at the indicated position.
252  * \param[in] buffer the buffer
253  * \param[in] at position
254  * \return the pointer to the data
255  */
256 INLINE uint8_t *
257 ldns_buffer_at(const ldns_buffer *buffer, size_t at)
258 {
259 	assert(at <= buffer->_limit);
260 	return buffer->_data + at;
261 }
262 
263 /**
264  * returns a pointer to the beginning of the buffer (the data at
265  * position 0).
266  * \param[in] buffer the buffer
267  * \return the pointer
268  */
269 INLINE uint8_t *
270 ldns_buffer_begin(const ldns_buffer *buffer)
271 {
272 	return ldns_buffer_at(buffer, 0);
273 }
274 
275 /**
276  * returns a pointer to the end of the buffer (the data at the buffer's
277  * limit).
278  * \param[in] buffer the buffer
279  * \return the pointer
280  */
281 INLINE uint8_t *
282 ldns_buffer_end(const ldns_buffer *buffer)
283 {
284 	return ldns_buffer_at(buffer, buffer->_limit);
285 }
286 
287 /**
288  * returns a pointer to the data at the buffer's current position.
289  * \param[in] buffer the buffer
290  * \return the pointer
291  */
292 INLINE uint8_t *
293 ldns_buffer_current(const ldns_buffer *buffer)
294 {
295 	return ldns_buffer_at(buffer, buffer->_position);
296 }
297 
298 /**
299  * returns the number of bytes remaining between the indicated position and
300  * the limit.
301  * \param[in] buffer the buffer
302  * \param[in] at indicated position
303  * \return number of bytes
304  */
305 INLINE size_t
306 ldns_buffer_remaining_at(const ldns_buffer *buffer, size_t at)
307 {
308 	ldns_buffer_invariant(buffer);
309 	assert(at <= buffer->_limit);
310 	return buffer->_limit - at;
311 }
312 
313 /**
314  * returns the number of bytes remaining between the buffer's position and
315  * limit.
316  * \param[in] buffer the buffer
317  * \return the number of bytes
318  */
319 INLINE size_t
320 ldns_buffer_remaining(const ldns_buffer *buffer)
321 {
322 	return ldns_buffer_remaining_at(buffer, buffer->_position);
323 }
324 
325 /**
326  * checks if the buffer has at least COUNT more bytes available.
327  * Before reading or writing the caller needs to ensure enough space
328  * is available!
329  * \param[in] buffer the buffer
330  * \param[in] at indicated position
331  * \param[in] count how much is available
332  * \return true or false (as int?)
333  */
334 INLINE int
335 ldns_buffer_available_at(const ldns_buffer *buffer, size_t at, size_t count)
336 {
337 	return count <= ldns_buffer_remaining_at(buffer, at);
338 }
339 
340 /**
341  * checks if the buffer has count bytes available at the current position
342  * \param[in] buffer the buffer
343  * \param[in] count how much is available
344  * \return true or false (as int?)
345  */
346 INLINE int
347 ldns_buffer_available(const ldns_buffer *buffer, size_t count)
348 {
349 	return ldns_buffer_available_at(buffer, buffer->_position, count);
350 }
351 
352 /**
353  * writes the given data to the buffer at the specified position
354  * \param[in] buffer the buffer
355  * \param[in] at the position (in number of bytes) to write the data at
356  * \param[in] data pointer to the data to write to the buffer
357  * \param[in] count the number of bytes of data to write
358  */
359 INLINE void
360 ldns_buffer_write_at(ldns_buffer *buffer, size_t at, const void *data, size_t count)
361 {
362 	assert(ldns_buffer_available_at(buffer, at, count));
363 	memcpy(buffer->_data + at, data, count);
364 }
365 
366 /**
367  * writes count bytes of data to the current position of the buffer
368  * \param[in] buffer the buffer
369  * \param[in] data the data to write
370  * \param[in] count the length of the data to write
371  */
372 INLINE void
373 ldns_buffer_write(ldns_buffer *buffer, const void *data, size_t count)
374 {
375 	ldns_buffer_write_at(buffer, buffer->_position, data, count);
376 	buffer->_position += count;
377 }
378 
379 /**
380  * copies the given (null-delimited) string to the specified position at the buffer
381  * \param[in] buffer the buffer
382  * \param[in] at the position in the buffer
383  * \param[in] str the string to write
384  */
385 INLINE void
386 ldns_buffer_write_string_at(ldns_buffer *buffer, size_t at, const char *str)
387 {
388 	ldns_buffer_write_at(buffer, at, str, strlen(str));
389 }
390 
391 /**
392  * copies the given (null-delimited) string to the current position at the buffer
393  * \param[in] buffer the buffer
394  * \param[in] str the string to write
395  */
396 INLINE void
397 ldns_buffer_write_string(ldns_buffer *buffer, const char *str)
398 {
399 	ldns_buffer_write(buffer, str, strlen(str));
400 }
401 
402 /**
403  * copies the given (null-delimited) string to the current position at the buffer
404  * increasing the capacity if necessary
405  * \param[in] buffer the buffer
406  * \param[in] str the string to write
407  */
408 INLINE void
409 ldns_buffer_write_chars(ldns_buffer *buffer, const char *str)
410 {
411 	if (!ldns_buffer_reserve(buffer, strlen(str)))
412 		buffer->_status = LDNS_STATUS_MEM_ERR;
413 	else
414 		ldns_buffer_write_string(buffer, str);
415 }
416 
417 
418 /**
419  * writes the given byte of data at the given position in the buffer
420  * \param[in] buffer the buffer
421  * \param[in] at the position in the buffer
422  * \param[in] data the 8 bits to write
423  */
424 INLINE void
425 ldns_buffer_write_u8_at(ldns_buffer *buffer, size_t at, uint8_t data)
426 {
427 	assert(ldns_buffer_available_at(buffer, at, sizeof(data)));
428 	buffer->_data[at] = data;
429 }
430 
431 /**
432  * writes the given byte of data at the current position in the buffer
433  * \param[in] buffer the buffer
434  * \param[in] data the 8 bits to write
435  */
436 INLINE void
437 ldns_buffer_write_u8(ldns_buffer *buffer, uint8_t data)
438 {
439 	ldns_buffer_write_u8_at(buffer, buffer->_position, data);
440 	buffer->_position += sizeof(data);
441 }
442 
443 /**
444  * writes the given byte of data at the current position in the buffer
445  * increasing the capacity if necessary
446  * \param[in] buffer the buffer
447  * \param[in] data the 8 bits to write
448  */
449 INLINE void
450 ldns_buffer_write_char(ldns_buffer *buffer, uint8_t data)
451 {
452 	if (!ldns_buffer_reserve(buffer, sizeof(data)))
453 		buffer->_status = LDNS_STATUS_MEM_ERR;
454 	else
455 		ldns_buffer_write_u8(buffer, data);
456 }
457 
458 /**
459  * writes the given 2 byte integer at the given position in the buffer
460  * \param[in] buffer the buffer
461  * \param[in] at the position in the buffer
462  * \param[in] data the 16 bits to write
463  */
464 INLINE void
465 ldns_buffer_write_u16_at(ldns_buffer *buffer, size_t at, uint16_t data)
466 {
467 	assert(ldns_buffer_available_at(buffer, at, sizeof(data)));
468 	ldns_write_uint16(buffer->_data + at, data);
469 }
470 
471 /**
472  * writes the given 2 byte integer at the current position in the buffer
473  * \param[in] buffer the buffer
474  * \param[in] data the 16 bits to write
475  */
476 INLINE void
477 ldns_buffer_write_u16(ldns_buffer *buffer, uint16_t data)
478 {
479 	ldns_buffer_write_u16_at(buffer, buffer->_position, data);
480 	buffer->_position += sizeof(data);
481 }
482 
483 /**
484  * writes the given 4 byte integer at the given position in the buffer
485  * \param[in] buffer the buffer
486  * \param[in] at the position in the buffer
487  * \param[in] data the 32 bits to write
488  */
489 INLINE void
490 ldns_buffer_write_u32_at(ldns_buffer *buffer, size_t at, uint32_t data)
491 {
492 	assert(ldns_buffer_available_at(buffer, at, sizeof(data)));
493 	ldns_write_uint32(buffer->_data + at, data);
494 }
495 
496 /**
497  * writes the given 4 byte integer at the current position in the buffer
498  * \param[in] buffer the buffer
499  * \param[in] data the 32 bits to write
500  */
501 INLINE void
502 ldns_buffer_write_u32(ldns_buffer *buffer, uint32_t data)
503 {
504 	ldns_buffer_write_u32_at(buffer, buffer->_position, data);
505 	buffer->_position += sizeof(data);
506 }
507 
508 /**
509  * copies count bytes of data at the given position to the given data-array
510  * \param[in] buffer the buffer
511  * \param[in] at the position in the buffer to start
512  * \param[out] data buffer to copy to
513  * \param[in] count the length of the data to copy
514  */
515 INLINE void
516 ldns_buffer_read_at(const ldns_buffer *buffer, size_t at, void *data, size_t count)
517 {
518 	assert(ldns_buffer_available_at(buffer, at, count));
519 	memcpy(data, buffer->_data + at, count);
520 }
521 
522 /**
523  * copies count bytes of data at the current position to the given data-array
524  * \param[in] buffer the buffer
525  * \param[out] data buffer to copy to
526  * \param[in] count the length of the data to copy
527  */
528 INLINE void
529 ldns_buffer_read(ldns_buffer *buffer, void *data, size_t count)
530 {
531 	ldns_buffer_read_at(buffer, buffer->_position, data, count);
532 	buffer->_position += count;
533 }
534 
535 /**
536  * returns the byte value at the given position in the buffer
537  * \param[in] buffer the buffer
538  * \param[in] at the position in the buffer
539  * \return 1 byte integer
540  */
541 INLINE uint8_t
542 ldns_buffer_read_u8_at(const ldns_buffer *buffer, size_t at)
543 {
544 	assert(ldns_buffer_available_at(buffer, at, sizeof(uint8_t)));
545 	return buffer->_data[at];
546 }
547 
548 /**
549  * returns the byte value at the current position in the buffer
550  * \param[in] buffer the buffer
551  * \return 1 byte integer
552  */
553 INLINE uint8_t
554 ldns_buffer_read_u8(ldns_buffer *buffer)
555 {
556 	uint8_t result = ldns_buffer_read_u8_at(buffer, buffer->_position);
557 	buffer->_position += sizeof(uint8_t);
558 	return result;
559 }
560 
561 /**
562  * returns the 2-byte integer value at the given position in the buffer
563  * \param[in] buffer the buffer
564  * \param[in] at position in the buffer
565  * \return 2 byte integer
566  */
567 INLINE uint16_t
568 ldns_buffer_read_u16_at(ldns_buffer *buffer, size_t at)
569 {
570 	assert(ldns_buffer_available_at(buffer, at, sizeof(uint16_t)));
571 	return ldns_read_uint16(buffer->_data + at);
572 }
573 
574 /**
575  * returns the 2-byte integer value at the current position in the buffer
576  * \param[in] buffer the buffer
577  * \return 2 byte integer
578  */
579 INLINE uint16_t
580 ldns_buffer_read_u16(ldns_buffer *buffer)
581 {
582 	uint16_t result = ldns_buffer_read_u16_at(buffer, buffer->_position);
583 	buffer->_position += sizeof(uint16_t);
584 	return result;
585 }
586 
587 /**
588  * returns the 4-byte integer value at the given position in the buffer
589  * \param[in] buffer the buffer
590  * \param[in] at position in the buffer
591  * \return 4 byte integer
592  */
593 INLINE uint32_t
594 ldns_buffer_read_u32_at(ldns_buffer *buffer, size_t at)
595 {
596 	assert(ldns_buffer_available_at(buffer, at, sizeof(uint32_t)));
597 	return ldns_read_uint32(buffer->_data + at);
598 }
599 
600 /**
601  * returns the 4-byte integer value at the current position in the buffer
602  * \param[in] buffer the buffer
603  * \return 4 byte integer
604  */
605 INLINE uint32_t
606 ldns_buffer_read_u32(ldns_buffer *buffer)
607 {
608 	uint32_t result = ldns_buffer_read_u32_at(buffer, buffer->_position);
609 	buffer->_position += sizeof(uint32_t);
610 	return result;
611 }
612 
613 /**
614  * returns the status of the buffer
615  * \param[in] buffer
616  * \return the status
617  */
618 INLINE ldns_status
619 ldns_buffer_status(const ldns_buffer *buffer)
620 {
621 	return buffer->_status;
622 }
623 
624 /**
625  * returns true if the status of the buffer is LDNS_STATUS_OK, false otherwise
626  * \param[in] buffer the buffer
627  * \return true or false
628  */
629 INLINE bool
630 ldns_buffer_status_ok(const ldns_buffer *buffer)
631 {
632 	if (buffer) {
633 		return ldns_buffer_status(buffer) == LDNS_STATUS_OK;
634 	} else {
635 		return false;
636 	}
637 }
638 
639 /**
640  * prints to the buffer, increasing the capacity if required using
641  * buffer_reserve(). The buffer's position is set to the terminating '\\0'
642  * Returns the number of characters written (not including the
643  * terminating '\\0') or -1 on failure.
644  */
645 int ldns_buffer_printf(ldns_buffer *buffer, const char *format, ...);
646 /*	ATTR_FORMAT(printf, 2, 3);*/
647 
648 /**
649  * frees the buffer.
650  * \param[in] *buffer the buffer to be freed
651  * \return void
652  */
653 void ldns_buffer_free(ldns_buffer *buffer);
654 
655 /**
656  * Makes the buffer fixed and returns a pointer to the data.  The
657  * caller is responsible for free'ing the result.
658  * \param[in] *buffer the buffer to be exported
659  * \return void
660  */
661 void *ldns_buffer_export(ldns_buffer *buffer);
662 
663 /**
664  * Copy contents of the from buffer to the result buffer and then flips
665  * the result buffer. Data will be silently truncated if the result buffer is
666  * too small.
667  * \param[out] *result resulting buffer which is copied to.
668  * \param[in] *from what to copy to result.
669  */
670 void ldns_buffer_copy(ldns_buffer* result, const ldns_buffer* from);
671 
672 #ifdef __cplusplus
673 }
674 #endif
675 
676 #endif /* LDNS_BUFFER_H */
677