xref: /freebsd/contrib/unbound/sldns/sbuffer.h (revision 39ee7a7a6bdd1557b1c3532abf60d139798ac88b)
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_SBUFFER_H
14 #define LDNS_SBUFFER_H
15 
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19 
20 #ifdef S_SPLINT_S
21 #  define INLINE
22 #else
23 #  ifdef SWIG
24 #    define INLINE static
25 #  else
26 #    define INLINE static inline
27 #  endif
28 #endif
29 
30 /*
31  * Copy data allowing for unaligned accesses in network byte order
32  * (big endian).
33  */
34 INLINE uint16_t
35 sldns_read_uint16(const void *src)
36 {
37 #ifdef ALLOW_UNALIGNED_ACCESSES
38         return ntohs(*(const uint16_t *) src);
39 #else
40         const uint8_t *p = (const uint8_t *) src;
41         return ((uint16_t) p[0] << 8) | (uint16_t) p[1];
42 #endif
43 }
44 
45 INLINE uint32_t
46 sldns_read_uint32(const void *src)
47 {
48 #ifdef ALLOW_UNALIGNED_ACCESSES
49         return ntohl(*(const uint32_t *) src);
50 #else
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)
55                 |  (uint32_t) p[3]);
56 #endif
57 }
58 
59 /*
60  * Copy data allowing for unaligned accesses in network byte order
61  * (big endian).
62  */
63 INLINE void
64 sldns_write_uint16(void *dst, uint16_t data)
65 {
66 #ifdef ALLOW_UNALIGNED_ACCESSES
67         * (uint16_t *) dst = htons(data);
68 #else
69         uint8_t *p = (uint8_t *) dst;
70         p[0] = (uint8_t) ((data >> 8) & 0xff);
71         p[1] = (uint8_t) (data & 0xff);
72 #endif
73 }
74 
75 INLINE void
76 sldns_write_uint32(void *dst, uint32_t data)
77 {
78 #ifdef ALLOW_UNALIGNED_ACCESSES
79         * (uint32_t *) dst = htonl(data);
80 #else
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);
86 #endif
87 }
88 
89 
90 /**
91  * \file sbuffer.h
92  *
93  * This file contains the definition of sldns_buffer, and functions to manipulate those.
94  */
95 
96 /**
97  * implementation of buffers to ease operations
98  *
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.
102  */
103 struct sldns_buffer
104 {
105 	/** The current position used for reading/writing */
106 	size_t   _position;
107 
108 	/** The read/write limit */
109 	size_t   _limit;
110 
111 	/** The amount of data the buffer can contain */
112 	size_t   _capacity;
113 
114 	/** The data contained in the buffer */
115 	uint8_t *_data;
116 
117 	/** If the buffer is fixed it cannot be resized */
118 	unsigned _fixed : 1;
119 
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;
124 };
125 typedef struct sldns_buffer sldns_buffer;
126 
127 #ifdef NDEBUG
128 INLINE void
129 sldns_buffer_invariant(sldns_buffer *ATTR_UNUSED(buffer))
130 {
131 }
132 #else
133 INLINE void
134 sldns_buffer_invariant(sldns_buffer *buffer)
135 {
136 	assert(buffer != NULL);
137 	assert(buffer->_position <= buffer->_limit);
138 	assert(buffer->_limit <= buffer->_capacity);
139 	assert(buffer->_data != NULL);
140 }
141 #endif
142 
143 /**
144  * creates a new buffer with the specified capacity.
145  *
146  * \param[in] capacity the size (in bytes) to allocate for the buffer
147  * \return the created buffer
148  */
149 sldns_buffer *sldns_buffer_new(size_t capacity);
150 
151 /**
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().
155  *
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
159  */
160 void sldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size);
161 
162 /**
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
168  */
169 void sldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size);
170 
171 /**
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
175  */
176 INLINE void sldns_buffer_clear(sldns_buffer *buffer)
177 {
178 	sldns_buffer_invariant(buffer);
179 
180 	/* reset status here? */
181 
182 	buffer->_position = 0;
183 	buffer->_limit = buffer->_capacity;
184 }
185 
186 /**
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.
190  *
191  * \param[in] buffer the buffer to flip
192  * \return void
193  */
194 INLINE void sldns_buffer_flip(sldns_buffer *buffer)
195 {
196 	sldns_buffer_invariant(buffer);
197 
198 	buffer->_limit = buffer->_position;
199 	buffer->_position = 0;
200 }
201 
202 /**
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
206  */
207 INLINE void sldns_buffer_rewind(sldns_buffer *buffer)
208 {
209 	sldns_buffer_invariant(buffer);
210 
211 	buffer->_position = 0;
212 }
213 
214 /**
215  * returns the current position in the buffer (as a number of bytes)
216  * \param[in] buffer the buffer
217  * \return the current position
218  */
219 INLINE size_t
220 sldns_buffer_position(sldns_buffer *buffer)
221 {
222 	return buffer->_position;
223 }
224 
225 /**
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
230  */
231 INLINE void
232 sldns_buffer_set_position(sldns_buffer *buffer, size_t mark)
233 {
234 	assert(mark <= buffer->_limit);
235 	buffer->_position = mark;
236 }
237 
238 /**
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
241  * buffer.
242  * \param[in] buffer the buffer
243  * \param[in] count the count to use
244  */
245 INLINE void
246 sldns_buffer_skip(sldns_buffer *buffer, ssize_t count)
247 {
248 	assert(buffer->_position + count <= buffer->_limit);
249 	buffer->_position += count;
250 }
251 
252 /**
253  * returns the maximum size of the buffer
254  * \param[in] buffer
255  * \return the size
256  */
257 INLINE size_t
258 sldns_buffer_limit(sldns_buffer *buffer)
259 {
260 	return buffer->_limit;
261 }
262 
263 /**
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
268  */
269 INLINE void
270 sldns_buffer_set_limit(sldns_buffer *buffer, size_t limit)
271 {
272 	assert(limit <= buffer->_capacity);
273 	buffer->_limit = limit;
274 	if (buffer->_position > buffer->_limit)
275 		buffer->_position = buffer->_limit;
276 }
277 
278 /**
279  * returns the number of bytes the buffer can hold.
280  * \param[in] buffer the buffer
281  * \return the number of bytes
282  */
283 INLINE size_t
284 sldns_buffer_capacity(sldns_buffer *buffer)
285 {
286 	return buffer->_capacity;
287 }
288 
289 /**
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
296  */
297 int sldns_buffer_set_capacity(sldns_buffer *buffer, size_t capacity);
298 
299 /**
300  * ensures BUFFER can contain at least AMOUNT more bytes.  The buffer's
301  * capacity is increased if necessary using buffer_set_capacity().
302  *
303  * The buffer's limit is always set to the (possibly increased)
304  * capacity.
305  * \param[in] buffer the buffer
306  * \param[in] amount amount to use
307  * \return whether this failed or succeeded
308  */
309 int sldns_buffer_reserve(sldns_buffer *buffer, size_t amount);
310 
311 /**
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
316  */
317 INLINE uint8_t *
318 sldns_buffer_at(const sldns_buffer *buffer, size_t at)
319 {
320 	assert(at <= buffer->_limit);
321 	return buffer->_data + at;
322 }
323 
324 /**
325  * returns a pointer to the beginning of the buffer (the data at
326  * position 0).
327  * \param[in] buffer the buffer
328  * \return the pointer
329  */
330 INLINE uint8_t *
331 sldns_buffer_begin(const sldns_buffer *buffer)
332 {
333 	return sldns_buffer_at(buffer, 0);
334 }
335 
336 /**
337  * returns a pointer to the end of the buffer (the data at the buffer's
338  * limit).
339  * \param[in] buffer the buffer
340  * \return the pointer
341  */
342 INLINE uint8_t *
343 sldns_buffer_end(sldns_buffer *buffer)
344 {
345 	return sldns_buffer_at(buffer, buffer->_limit);
346 }
347 
348 /**
349  * returns a pointer to the data at the buffer's current position.
350  * \param[in] buffer the buffer
351  * \return the pointer
352  */
353 INLINE uint8_t *
354 sldns_buffer_current(sldns_buffer *buffer)
355 {
356 	return sldns_buffer_at(buffer, buffer->_position);
357 }
358 
359 /**
360  * returns the number of bytes remaining between the indicated position and
361  * the limit.
362  * \param[in] buffer the buffer
363  * \param[in] at indicated position
364  * \return number of bytes
365  */
366 INLINE size_t
367 sldns_buffer_remaining_at(sldns_buffer *buffer, size_t at)
368 {
369 	sldns_buffer_invariant(buffer);
370 	assert(at <= buffer->_limit);
371 	return buffer->_limit - at;
372 }
373 
374 /**
375  * returns the number of bytes remaining between the buffer's position and
376  * limit.
377  * \param[in] buffer the buffer
378  * \return the number of bytes
379  */
380 INLINE size_t
381 sldns_buffer_remaining(sldns_buffer *buffer)
382 {
383 	return sldns_buffer_remaining_at(buffer, buffer->_position);
384 }
385 
386 /**
387  * checks if the buffer has at least COUNT more bytes available.
388  * Before reading or writing the caller needs to ensure enough space
389  * is available!
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?)
394  */
395 INLINE int
396 sldns_buffer_available_at(sldns_buffer *buffer, size_t at, size_t count)
397 {
398 	return count <= sldns_buffer_remaining_at(buffer, at);
399 }
400 
401 /**
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?)
406  */
407 INLINE int
408 sldns_buffer_available(sldns_buffer *buffer, size_t count)
409 {
410 	return sldns_buffer_available_at(buffer, buffer->_position, count);
411 }
412 
413 /**
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
419  */
420 INLINE void
421 sldns_buffer_write_at(sldns_buffer *buffer, size_t at, const void *data, size_t count)
422 {
423 	assert(sldns_buffer_available_at(buffer, at, count));
424 	memcpy(buffer->_data + at, data, count);
425 }
426 
427 /**
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
432  */
433 INLINE void
434 sldns_buffer_write(sldns_buffer *buffer, const void *data, size_t count)
435 {
436 	sldns_buffer_write_at(buffer, buffer->_position, data, count);
437 	buffer->_position += count;
438 }
439 
440 /**
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
445  */
446 INLINE void
447 sldns_buffer_write_string_at(sldns_buffer *buffer, size_t at, const char *str)
448 {
449 	sldns_buffer_write_at(buffer, at, str, strlen(str));
450 }
451 
452 /**
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
456  */
457 INLINE void
458 sldns_buffer_write_string(sldns_buffer *buffer, const char *str)
459 {
460 	sldns_buffer_write(buffer, str, strlen(str));
461 }
462 
463 /**
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
468  */
469 INLINE void
470 sldns_buffer_write_u8_at(sldns_buffer *buffer, size_t at, uint8_t data)
471 {
472 	assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
473 	buffer->_data[at] = data;
474 }
475 
476 /**
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
480  */
481 INLINE void
482 sldns_buffer_write_u8(sldns_buffer *buffer, uint8_t data)
483 {
484 	sldns_buffer_write_u8_at(buffer, buffer->_position, data);
485 	buffer->_position += sizeof(data);
486 }
487 
488 /**
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
493  */
494 INLINE void
495 sldns_buffer_write_u16_at(sldns_buffer *buffer, size_t at, uint16_t data)
496 {
497 	assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
498 	sldns_write_uint16(buffer->_data + at, data);
499 }
500 
501 /**
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
505  */
506 INLINE void
507 sldns_buffer_write_u16(sldns_buffer *buffer, uint16_t data)
508 {
509 	sldns_buffer_write_u16_at(buffer, buffer->_position, data);
510 	buffer->_position += sizeof(data);
511 }
512 
513 /**
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
518  */
519 INLINE void
520 sldns_buffer_write_u32_at(sldns_buffer *buffer, size_t at, uint32_t data)
521 {
522 	assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
523 	sldns_write_uint32(buffer->_data + at, data);
524 }
525 
526 /**
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
530  */
531 INLINE void
532 sldns_buffer_write_u32(sldns_buffer *buffer, uint32_t data)
533 {
534 	sldns_buffer_write_u32_at(buffer, buffer->_position, data);
535 	buffer->_position += sizeof(data);
536 }
537 
538 /**
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
544  */
545 INLINE void
546 sldns_buffer_read_at(sldns_buffer *buffer, size_t at, void *data, size_t count)
547 {
548 	assert(sldns_buffer_available_at(buffer, at, count));
549 	memcpy(data, buffer->_data + at, count);
550 }
551 
552 /**
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
557  */
558 INLINE void
559 sldns_buffer_read(sldns_buffer *buffer, void *data, size_t count)
560 {
561 	sldns_buffer_read_at(buffer, buffer->_position, data, count);
562 	buffer->_position += count;
563 }
564 
565 /**
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
570  */
571 INLINE uint8_t
572 sldns_buffer_read_u8_at(sldns_buffer *buffer, size_t at)
573 {
574 	assert(sldns_buffer_available_at(buffer, at, sizeof(uint8_t)));
575 	return buffer->_data[at];
576 }
577 
578 /**
579  * returns the byte value at the current position in the buffer
580  * \param[in] buffer the buffer
581  * \return 1 byte integer
582  */
583 INLINE uint8_t
584 sldns_buffer_read_u8(sldns_buffer *buffer)
585 {
586 	uint8_t result = sldns_buffer_read_u8_at(buffer, buffer->_position);
587 	buffer->_position += sizeof(uint8_t);
588 	return result;
589 }
590 
591 /**
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
596  */
597 INLINE uint16_t
598 sldns_buffer_read_u16_at(sldns_buffer *buffer, size_t at)
599 {
600 	assert(sldns_buffer_available_at(buffer, at, sizeof(uint16_t)));
601 	return sldns_read_uint16(buffer->_data + at);
602 }
603 
604 /**
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
608  */
609 INLINE uint16_t
610 sldns_buffer_read_u16(sldns_buffer *buffer)
611 {
612 	uint16_t result = sldns_buffer_read_u16_at(buffer, buffer->_position);
613 	buffer->_position += sizeof(uint16_t);
614 	return result;
615 }
616 
617 /**
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
622  */
623 INLINE uint32_t
624 sldns_buffer_read_u32_at(sldns_buffer *buffer, size_t at)
625 {
626 	assert(sldns_buffer_available_at(buffer, at, sizeof(uint32_t)));
627 	return sldns_read_uint32(buffer->_data + at);
628 }
629 
630 /**
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
634  */
635 INLINE uint32_t
636 sldns_buffer_read_u32(sldns_buffer *buffer)
637 {
638 	uint32_t result = sldns_buffer_read_u32_at(buffer, buffer->_position);
639 	buffer->_position += sizeof(uint32_t);
640 	return result;
641 }
642 
643 /**
644  * returns the status of the buffer
645  * \param[in] buffer
646  * \return the status
647  */
648 INLINE int
649 sldns_buffer_status(sldns_buffer *buffer)
650 {
651 	return (int)buffer->_status_err;
652 }
653 
654 /**
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
658  */
659 INLINE int
660 sldns_buffer_status_ok(sldns_buffer *buffer)
661 {
662 	if (buffer) {
663 		return sldns_buffer_status(buffer) == 0;
664 	} else {
665 		return 0;
666 	}
667 }
668 
669 /**
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.
674  */
675 int sldns_buffer_printf(sldns_buffer *buffer, const char *format, ...)
676 	ATTR_FORMAT(printf, 2, 3);
677 
678 /**
679  * frees the buffer.
680  * \param[in] *buffer the buffer to be freed
681  * \return void
682  */
683 void sldns_buffer_free(sldns_buffer *buffer);
684 
685 /**
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
689  * \return void
690  */
691 void *sldns_buffer_export(sldns_buffer *buffer);
692 
693 /**
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
696  * too small.
697  * \param[out] *result resulting buffer which is copied to.
698  * \param[in] *from what to copy to result.
699  */
700 void sldns_buffer_copy(sldns_buffer* result, sldns_buffer* from);
701 
702 #ifdef __cplusplus
703 }
704 #endif
705 
706 #endif /* LDNS_SBUFFER_H */
707