]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/unbound/sldns/sbuffer.h
MFV: xz 5.4.4.
[FreeBSD/FreeBSD.git] / contrib / unbound / sldns / sbuffer.h
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 INLINE void
91 sldns_write_uint48(void *dst, uint64_t data)
92 {
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);
100 }
101
102
103 /**
104  * \file sbuffer.h
105  *
106  * This file contains the definition of sldns_buffer, and functions to manipulate those.
107  */
108
109 /** 
110  * implementation of buffers to ease operations
111  *
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.
115  */
116 struct sldns_buffer
117 {
118         /** The current position used for reading/writing */ 
119         size_t   _position;
120
121         /** The read/write limit */
122         size_t   _limit;
123
124         /** The amount of data the buffer can contain */
125         size_t   _capacity;
126
127         /** The data contained in the buffer */
128         uint8_t *_data;
129
130         /** If the buffer is fixed it cannot be resized */
131         unsigned _fixed : 1;
132
133         /** The current state of the buffer. If writing to the buffer fails
134          * for any reason, this value is changed. This way, you can perform
135          * multiple writes in sequence and check for success afterwards. */
136         unsigned _status_err : 1;
137 };
138 typedef struct sldns_buffer sldns_buffer;
139
140 #ifdef NDEBUG
141 INLINE void
142 sldns_buffer_invariant(sldns_buffer *ATTR_UNUSED(buffer))
143 {
144 }
145 #else
146 INLINE void
147 sldns_buffer_invariant(sldns_buffer *buffer)
148 {
149         assert(buffer != NULL);
150         assert(buffer->_position <= buffer->_limit);
151         assert(buffer->_limit <= buffer->_capacity);
152         assert(buffer->_data != NULL);
153 }
154 #endif
155
156 /**
157  * creates a new buffer with the specified capacity.
158  *
159  * \param[in] capacity the size (in bytes) to allocate for the buffer
160  * \return the created buffer
161  */
162 sldns_buffer *sldns_buffer_new(size_t capacity);
163
164 /**
165  * creates a buffer with the specified data.  The data IS copied
166  * and MEMORY allocations are done.  The buffer is not fixed and can
167  * be resized using buffer_reserve().
168  *
169  * \param[in] buffer pointer to the buffer to put the data in
170  * \param[in] data the data to encapsulate in the buffer
171  * \param[in] size the size of the data
172  */
173 void sldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size);
174
175 /**
176  * Setup a buffer with the data pointed to. No data copied, no memory allocs.
177  * The buffer is fixed.
178  * \param[in] buffer pointer to the buffer to put the data in
179  * \param[in] data the data to encapsulate in the buffer
180  * \param[in] size the size of the data
181  */
182 void sldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size);
183
184 /**
185  * clears the buffer and make it ready for writing.  The buffer's limit
186  * is set to the capacity and the position is set to 0.
187  * \param[in] buffer the buffer to clear
188  */
189 INLINE void sldns_buffer_clear(sldns_buffer *buffer)
190 {
191         sldns_buffer_invariant(buffer);
192
193         /* reset status here? */
194
195         buffer->_position = 0;
196         buffer->_limit = buffer->_capacity;
197 }
198
199 /**
200  * makes the buffer ready for reading the data that has been written to
201  * the buffer.  The buffer's limit is set to the current position and
202  * the position is set to 0.
203  *
204  * \param[in] buffer the buffer to flip
205  */
206 INLINE void sldns_buffer_flip(sldns_buffer *buffer)
207 {
208         sldns_buffer_invariant(buffer);
209
210         buffer->_limit = buffer->_position;
211         buffer->_position = 0;
212 }
213
214 /**
215  * make the buffer ready for re-reading the data.  The buffer's
216  * position is reset to 0.
217  * \param[in] buffer the buffer to rewind
218  */
219 INLINE void sldns_buffer_rewind(sldns_buffer *buffer)
220 {
221         sldns_buffer_invariant(buffer);
222
223         buffer->_position = 0;
224 }
225
226 /**
227  * returns the current position in the buffer (as a number of bytes)
228  * \param[in] buffer the buffer
229  * \return the current position
230  */
231 INLINE size_t
232 sldns_buffer_position(sldns_buffer *buffer)
233 {
234         return buffer->_position;
235 }
236
237 /**
238  * sets the buffer's position to MARK.  The position must be less than
239  * or equal to the buffer's limit.
240  * \param[in] buffer the buffer
241  * \param[in] mark the mark to use
242  */
243 INLINE void
244 sldns_buffer_set_position(sldns_buffer *buffer, size_t mark)
245 {
246         assert(mark <= buffer->_limit);
247         buffer->_position = mark;
248 }
249
250 /**
251  * changes the buffer's position by COUNT bytes.  The position must not
252  * be moved behind the buffer's limit or before the beginning of the
253  * buffer.
254  * \param[in] buffer the buffer
255  * \param[in] count the count to use
256  */
257 INLINE void
258 sldns_buffer_skip(sldns_buffer *buffer, ssize_t count)
259 {
260         assert(buffer->_position + count <= buffer->_limit);
261         buffer->_position += count;
262 }
263
264 /**
265  * returns the maximum size of the buffer
266  * \param[in] buffer
267  * \return the size
268  */
269 INLINE size_t
270 sldns_buffer_limit(sldns_buffer *buffer)
271 {
272         return buffer->_limit;
273 }
274
275 /**
276  * changes the buffer's limit.  If the buffer's position is greater
277  * than the new limit the position is set to the limit.
278  * \param[in] buffer the buffer
279  * \param[in] limit the new limit
280  */
281 INLINE void
282 sldns_buffer_set_limit(sldns_buffer *buffer, size_t limit)
283 {
284         assert(limit <= buffer->_capacity);
285         buffer->_limit = limit;
286         if (buffer->_position > buffer->_limit)
287                 buffer->_position = buffer->_limit;
288 }
289
290 /**
291  * returns the number of bytes the buffer can hold.
292  * \param[in] buffer the buffer
293  * \return the number of bytes
294  */
295 INLINE size_t
296 sldns_buffer_capacity(sldns_buffer *buffer)
297 {
298         return buffer->_capacity;
299 }
300
301 /**
302  * changes the buffer's capacity.  The data is reallocated so any
303  * pointers to the data may become invalid.  The buffer's limit is set
304  * to the buffer's new capacity.
305  * \param[in] buffer the buffer
306  * \param[in] capacity the capacity to use
307  * \return whether this failed or succeeded
308  */
309 int sldns_buffer_set_capacity(sldns_buffer *buffer, size_t capacity);
310
311 /**
312  * ensures BUFFER can contain at least AMOUNT more bytes.  The buffer's
313  * capacity is increased if necessary using buffer_set_capacity().
314  *
315  * The buffer's limit is always set to the (possibly increased)
316  * capacity.
317  * \param[in] buffer the buffer
318  * \param[in] amount amount to use
319  * \return whether this failed or succeeded
320  */
321 int sldns_buffer_reserve(sldns_buffer *buffer, size_t amount);
322
323 /**
324  * returns a pointer to the data at the indicated position.
325  * \param[in] buffer the buffer
326  * \param[in] at position
327  * \return the pointer to the data
328  */
329 INLINE uint8_t *
330 sldns_buffer_at(const sldns_buffer *buffer, size_t at)
331 {
332         assert(at <= buffer->_limit);
333         return buffer->_data + at;
334 }
335
336 /**
337  * returns a pointer to the beginning of the buffer (the data at
338  * position 0).
339  * \param[in] buffer the buffer
340  * \return the pointer
341  */
342 INLINE uint8_t *
343 sldns_buffer_begin(const sldns_buffer *buffer)
344 {
345         return sldns_buffer_at(buffer, 0);
346 }
347
348 /**
349  * returns a pointer to the end of the buffer (the data at the buffer's
350  * limit).
351  * \param[in] buffer the buffer
352  * \return the pointer
353  */
354 INLINE uint8_t *
355 sldns_buffer_end(sldns_buffer *buffer)
356 {
357         return sldns_buffer_at(buffer, buffer->_limit);
358 }
359
360 /**
361  * returns a pointer to the data at the buffer's current position.
362  * \param[in] buffer the buffer
363  * \return the pointer
364  */
365 INLINE uint8_t *
366 sldns_buffer_current(sldns_buffer *buffer)
367 {
368         return sldns_buffer_at(buffer, buffer->_position);
369 }
370
371 /**
372  * returns the number of bytes remaining between the indicated position and
373  * the limit.
374  * \param[in] buffer the buffer
375  * \param[in] at indicated position
376  * \return number of bytes
377  */
378 INLINE size_t
379 sldns_buffer_remaining_at(sldns_buffer *buffer, size_t at)
380 {
381         sldns_buffer_invariant(buffer);
382         assert(at <= buffer->_limit);
383         return at < buffer->_limit ? buffer->_limit - at : 0;
384 }
385
386 /**
387  * returns the number of bytes remaining between the buffer's position and
388  * limit.
389  * \param[in] buffer the buffer
390  * \return the number of bytes
391  */
392 INLINE size_t
393 sldns_buffer_remaining(sldns_buffer *buffer)
394 {
395         return sldns_buffer_remaining_at(buffer, buffer->_position);
396 }
397
398 /**
399  * checks if the buffer has at least COUNT more bytes available.
400  * Before reading or writing the caller needs to ensure enough space
401  * is available!
402  * \param[in] buffer the buffer
403  * \param[in] at indicated position
404  * \param[in] count how much is available
405  * \return true or false (as int?)
406  */
407 INLINE int
408 sldns_buffer_available_at(sldns_buffer *buffer, size_t at, size_t count)
409 {
410         return count <= sldns_buffer_remaining_at(buffer, at);
411 }
412
413 /**
414  * checks if the buffer has count bytes available at the current position
415  * \param[in] buffer the buffer
416  * \param[in] count how much is available
417  * \return true or false (as int?)
418  */
419 INLINE int
420 sldns_buffer_available(sldns_buffer *buffer, size_t count)
421 {
422         return sldns_buffer_available_at(buffer, buffer->_position, count);
423 }
424
425 /**
426  * writes the given data to the buffer at the specified position
427  * \param[in] buffer the buffer
428  * \param[in] at the position (in number of bytes) to write the data at
429  * \param[in] data pointer to the data to write to the buffer
430  * \param[in] count the number of bytes of data to write
431  */
432 INLINE void
433 sldns_buffer_write_at(sldns_buffer *buffer, size_t at, const void *data, size_t count)
434 {
435         assert(sldns_buffer_available_at(buffer, at, count));
436         memcpy(buffer->_data + at, data, count);
437 }
438
439 /**
440  * set the given byte to the buffer at the specified position
441  * \param[in] buffer the buffer
442  * \param[in] at the position (in number of bytes) to write the data at
443  * \param[in] c the byte to set to the buffer
444  * \param[in] count the number of bytes of bytes to write
445  */
446
447 INLINE void
448 sldns_buffer_set_at(sldns_buffer *buffer, size_t at, int c, size_t count)
449 {
450         assert(sldns_buffer_available_at(buffer, at, count));
451         memset(buffer->_data + at, c, count);
452 }
453
454
455 /**
456  * writes count bytes of data to the current position of the buffer
457  * \param[in] buffer the buffer
458  * \param[in] data the data to write
459  * \param[in] count the length of the data to write
460  */
461 INLINE void
462 sldns_buffer_write(sldns_buffer *buffer, const void *data, size_t count)
463 {
464         sldns_buffer_write_at(buffer, buffer->_position, data, count);
465         buffer->_position += count;
466 }
467
468 /**
469  * copies the given (null-delimited) string to the specified position at the buffer
470  * \param[in] buffer the buffer
471  * \param[in] at the position in the buffer
472  * \param[in] str the string to write
473  */
474 INLINE void
475 sldns_buffer_write_string_at(sldns_buffer *buffer, size_t at, const char *str)
476 {
477         sldns_buffer_write_at(buffer, at, str, strlen(str));
478 }
479
480 /**
481  * copies the given (null-delimited) string to the current position at the buffer
482  * \param[in] buffer the buffer
483  * \param[in] str the string to write
484  */
485 INLINE void
486 sldns_buffer_write_string(sldns_buffer *buffer, const char *str)
487 {
488         sldns_buffer_write(buffer, str, strlen(str));
489 }
490
491 /**
492  * writes the given byte of data at the given position in the buffer
493  * \param[in] buffer the buffer
494  * \param[in] at the position in the buffer
495  * \param[in] data the 8 bits to write
496  */
497 INLINE void
498 sldns_buffer_write_u8_at(sldns_buffer *buffer, size_t at, uint8_t data)
499 {
500         assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
501         buffer->_data[at] = data;
502 }
503
504 /**
505  * writes the given byte of data at the current position in the buffer
506  * \param[in] buffer the buffer
507  * \param[in] data the 8 bits to write
508  */
509 INLINE void
510 sldns_buffer_write_u8(sldns_buffer *buffer, uint8_t data)
511 {
512         sldns_buffer_write_u8_at(buffer, buffer->_position, data);
513         buffer->_position += sizeof(data);
514 }
515
516 /**
517  * writes the given 2 byte integer at the given position in the buffer
518  * \param[in] buffer the buffer
519  * \param[in] at the position in the buffer
520  * \param[in] data the 16 bits to write
521  */
522 INLINE void
523 sldns_buffer_write_u16_at(sldns_buffer *buffer, size_t at, uint16_t data)
524 {
525         assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
526         sldns_write_uint16(buffer->_data + at, data);
527 }
528
529 /**
530  * writes the given 2 byte integer at the current position in the buffer
531  * \param[in] buffer the buffer
532  * \param[in] data the 16 bits to write
533  */
534 INLINE void
535 sldns_buffer_write_u16(sldns_buffer *buffer, uint16_t data)
536 {
537         sldns_buffer_write_u16_at(buffer, buffer->_position, data);
538         buffer->_position += sizeof(data);
539 }
540
541 /**
542  * writes the given 4 byte integer at the given position in the buffer
543  * \param[in] buffer the buffer
544  * \param[in] at the position in the buffer
545  * \param[in] data the 32 bits to write
546  */
547 INLINE void
548 sldns_buffer_write_u32_at(sldns_buffer *buffer, size_t at, uint32_t data)
549 {
550         assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
551         sldns_write_uint32(buffer->_data + at, data);
552 }
553
554 /**
555  * writes the given 6 byte integer at the given position in the buffer
556  * \param[in] buffer the buffer
557  * \param[in] at the position in the buffer
558  * \param[in] data the (lower) 48 bits to write
559  */
560 INLINE void
561 sldns_buffer_write_u48_at(sldns_buffer *buffer, size_t at, uint64_t data)
562 {
563         assert(sldns_buffer_available_at(buffer, at, 6));
564         sldns_write_uint48(buffer->_data + at, data);
565 }
566
567 /**
568  * writes the given 4 byte integer at the current position in the buffer
569  * \param[in] buffer the buffer
570  * \param[in] data the 32 bits to write
571  */
572 INLINE void
573 sldns_buffer_write_u32(sldns_buffer *buffer, uint32_t data)
574 {
575         sldns_buffer_write_u32_at(buffer, buffer->_position, data);
576         buffer->_position += sizeof(data);
577 }
578
579 /**
580  * writes the given 6 byte integer at the current position in the buffer
581  * \param[in] buffer the buffer
582  * \param[in] data the 48 bits to write
583  */
584 INLINE void
585 sldns_buffer_write_u48(sldns_buffer *buffer, uint64_t data)
586 {
587         sldns_buffer_write_u48_at(buffer, buffer->_position, data);
588         buffer->_position += 6;
589 }
590
591 /**
592  * copies count bytes of data at the given position to the given data-array
593  * \param[in] buffer the buffer
594  * \param[in] at the position in the buffer to start
595  * \param[out] data buffer to copy to
596  * \param[in] count the length of the data to copy
597  */
598 INLINE void
599 sldns_buffer_read_at(sldns_buffer *buffer, size_t at, void *data, size_t count)
600 {
601         assert(sldns_buffer_available_at(buffer, at, count));
602         memcpy(data, buffer->_data + at, count);
603 }
604
605 /**
606  * copies count bytes of data at the current position to the given data-array
607  * \param[in] buffer the buffer
608  * \param[out] data buffer to copy to
609  * \param[in] count the length of the data to copy
610  */
611 INLINE void
612 sldns_buffer_read(sldns_buffer *buffer, void *data, size_t count)
613 {
614         sldns_buffer_read_at(buffer, buffer->_position, data, count);
615         buffer->_position += count;
616 }
617
618 /**
619  * returns the byte value at the given position in the buffer
620  * \param[in] buffer the buffer
621  * \param[in] at the position in the buffer
622  * \return 1 byte integer
623  */
624 INLINE uint8_t
625 sldns_buffer_read_u8_at(sldns_buffer *buffer, size_t at)
626 {
627         assert(sldns_buffer_available_at(buffer, at, sizeof(uint8_t)));
628         return buffer->_data[at];
629 }
630
631 /**
632  * returns the byte value at the current position in the buffer
633  * \param[in] buffer the buffer
634  * \return 1 byte integer
635  */
636 INLINE uint8_t
637 sldns_buffer_read_u8(sldns_buffer *buffer)
638 {
639         uint8_t result = sldns_buffer_read_u8_at(buffer, buffer->_position);
640         buffer->_position += sizeof(uint8_t);
641         return result;
642 }
643
644 /**
645  * returns the 2-byte integer value at the given position in the buffer
646  * \param[in] buffer the buffer
647  * \param[in] at position in the buffer
648  * \return 2 byte integer
649  */
650 INLINE uint16_t
651 sldns_buffer_read_u16_at(sldns_buffer *buffer, size_t at)
652 {
653         assert(sldns_buffer_available_at(buffer, at, sizeof(uint16_t)));
654         return sldns_read_uint16(buffer->_data + at);
655 }
656
657 /**
658  * returns the 2-byte integer value at the current position in the buffer
659  * \param[in] buffer the buffer
660  * \return 2 byte integer
661  */
662 INLINE uint16_t
663 sldns_buffer_read_u16(sldns_buffer *buffer)
664 {
665         uint16_t result = sldns_buffer_read_u16_at(buffer, buffer->_position);
666         buffer->_position += sizeof(uint16_t);
667         return result;
668 }
669
670 /**
671  * returns the 4-byte integer value at the given position in the buffer
672  * \param[in] buffer the buffer
673  * \param[in] at position in the buffer
674  * \return 4 byte integer
675  */
676 INLINE uint32_t
677 sldns_buffer_read_u32_at(sldns_buffer *buffer, size_t at)
678 {
679         assert(sldns_buffer_available_at(buffer, at, sizeof(uint32_t)));
680         return sldns_read_uint32(buffer->_data + at);
681 }
682
683 /**
684  * returns the 4-byte integer value at the current position in the buffer
685  * \param[in] buffer the buffer
686  * \return 4 byte integer
687  */
688 INLINE uint32_t
689 sldns_buffer_read_u32(sldns_buffer *buffer)
690 {
691         uint32_t result = sldns_buffer_read_u32_at(buffer, buffer->_position);
692         buffer->_position += sizeof(uint32_t);
693         return result;
694 }
695
696 /**
697  * returns the status of the buffer
698  * \param[in] buffer
699  * \return the status
700  */
701 INLINE int
702 sldns_buffer_status(sldns_buffer *buffer)
703 {
704         return (int)buffer->_status_err;
705 }
706
707 /**
708  * returns true if the status of the buffer is LDNS_STATUS_OK, false otherwise
709  * \param[in] buffer the buffer
710  * \return true or false
711  */
712 INLINE int
713 sldns_buffer_status_ok(sldns_buffer *buffer)
714 {
715         if (buffer) {
716                 return sldns_buffer_status(buffer) == 0;
717         } else {
718                 return 0;
719         }
720 }
721
722 /**
723  * prints to the buffer, increasing the capacity if required using
724  * buffer_reserve(). The buffer's position is set to the terminating '\\0'
725  * Returns the number of characters written (not including the
726  * terminating '\\0') or -1 on failure.
727  */
728 int sldns_buffer_printf(sldns_buffer *buffer, const char *format, ...)
729         ATTR_FORMAT(printf, 2, 3);
730
731 /**
732  * frees the buffer.
733  * \param[in] *buffer the buffer to be freed
734  */
735 void sldns_buffer_free(sldns_buffer *buffer);
736
737 /**
738  * Copy contents of the from buffer to the result buffer and then flips 
739  * the result buffer. Data will be silently truncated if the result buffer is
740  * too small.
741  * \param[out] *result resulting buffer which is copied to.
742  * \param[in] *from what to copy to result.
743  */
744 void sldns_buffer_copy(sldns_buffer* result, sldns_buffer* from);
745
746 #ifdef __cplusplus
747 }
748 #endif
749
750 #endif /* LDNS_SBUFFER_H */