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