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
17extern "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 */
34INLINE uint16_t
35sldns_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
45INLINE uint32_t
46sldns_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 */
63INLINE void
64sldns_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
75INLINE void
76sldns_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 */
103struct 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};
125typedef struct sldns_buffer sldns_buffer;
126
127#ifdef NDEBUG
128INLINE void
129sldns_buffer_invariant(sldns_buffer *ATTR_UNUSED(buffer))
130{
131}
132#else
133INLINE void
134sldns_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 */
149sldns_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 */
160void 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 */
169void 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 */
176INLINE 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 */
194INLINE 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 */
207INLINE 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 */
219INLINE size_t
220sldns_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 */
231INLINE void
232sldns_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 */
245INLINE void
246sldns_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 */
257INLINE size_t
258sldns_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 */
269INLINE void
270sldns_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 */
283INLINE size_t
284sldns_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 */
297int 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 */
309int 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 */
317INLINE uint8_t *
318sldns_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 */
330INLINE uint8_t *
331sldns_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 */
342INLINE uint8_t *
343sldns_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 */
353INLINE uint8_t *
354sldns_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 */
366INLINE size_t
367sldns_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 */
380INLINE size_t
381sldns_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 */
395INLINE int
396sldns_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 */
407INLINE int
408sldns_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 */
420INLINE void
421sldns_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 */
433INLINE void
434sldns_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 */
446INLINE void
447sldns_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 */
457INLINE void
458sldns_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 */
469INLINE void
470sldns_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 */
481INLINE void
482sldns_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 */
494INLINE void
495sldns_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 */
506INLINE void
507sldns_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 */
519INLINE void
520sldns_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 */
531INLINE void
532sldns_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 */
545INLINE void
546sldns_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 */
558INLINE void
559sldns_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 */
571INLINE uint8_t
572sldns_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 */
583INLINE uint8_t
584sldns_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 */
597INLINE uint16_t
598sldns_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 */
609INLINE uint16_t
610sldns_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 */
623INLINE uint32_t
624sldns_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 */
635INLINE uint32_t
636sldns_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 */
648INLINE int
649sldns_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 */
659INLINE int
660sldns_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 */
675int 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 */
683void 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 */
691void *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 */
700void sldns_buffer_copy(sldns_buffer* result, sldns_buffer* from);
701
702#ifdef __cplusplus
703}
704#endif
705
706#endif /* LDNS_SBUFFER_H */
707