1266077Sdes/*
2266077Sdes * buffer.h -- generic memory buffer.
3266077Sdes *
4266077Sdes * Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
5266077Sdes *
6266077Sdes * See LICENSE for the license.
7266077Sdes *
8266077Sdes *
9266077Sdes * The buffer module implements a generic buffer.  The API is based on
10266077Sdes * the java.nio.Buffer interface.
11266077Sdes */
12266077Sdes
13266077Sdes#ifndef LDNS_SBUFFER_H
14266077Sdes#define LDNS_SBUFFER_H
15266077Sdes
16266077Sdes#ifdef __cplusplus
17266077Sdesextern "C" {
18266077Sdes#endif
19266077Sdes
20266077Sdes#ifdef S_SPLINT_S
21266077Sdes#  define INLINE
22266077Sdes#else
23266077Sdes#  ifdef SWIG
24266077Sdes#    define INLINE static
25266077Sdes#  else
26266077Sdes#    define INLINE static inline
27266077Sdes#  endif
28266077Sdes#endif
29266077Sdes
30266077Sdes/*
31266077Sdes * Copy data allowing for unaligned accesses in network byte order
32266077Sdes * (big endian).
33266077Sdes */
34266077SdesINLINE uint16_t
35266077Sdessldns_read_uint16(const void *src)
36266077Sdes{
37266077Sdes#ifdef ALLOW_UNALIGNED_ACCESSES
38276541Sdes        return ntohs(*(const uint16_t *) src);
39266077Sdes#else
40276541Sdes        const uint8_t *p = (const uint8_t *) src;
41266077Sdes        return ((uint16_t) p[0] << 8) | (uint16_t) p[1];
42266077Sdes#endif
43266077Sdes}
44266077Sdes
45266077SdesINLINE uint32_t
46266077Sdessldns_read_uint32(const void *src)
47266077Sdes{
48266077Sdes#ifdef ALLOW_UNALIGNED_ACCESSES
49276541Sdes        return ntohl(*(const uint32_t *) src);
50266077Sdes#else
51276541Sdes        const uint8_t *p = (const uint8_t *) src;
52266077Sdes        return (  ((uint32_t) p[0] << 24)
53266077Sdes                | ((uint32_t) p[1] << 16)
54266077Sdes                | ((uint32_t) p[2] << 8)
55266077Sdes                |  (uint32_t) p[3]);
56266077Sdes#endif
57266077Sdes}
58266077Sdes
59266077Sdes/*
60266077Sdes * Copy data allowing for unaligned accesses in network byte order
61266077Sdes * (big endian).
62266077Sdes */
63266077SdesINLINE void
64266077Sdessldns_write_uint16(void *dst, uint16_t data)
65266077Sdes{
66266077Sdes#ifdef ALLOW_UNALIGNED_ACCESSES
67266077Sdes        * (uint16_t *) dst = htons(data);
68266077Sdes#else
69266077Sdes        uint8_t *p = (uint8_t *) dst;
70266077Sdes        p[0] = (uint8_t) ((data >> 8) & 0xff);
71266077Sdes        p[1] = (uint8_t) (data & 0xff);
72266077Sdes#endif
73266077Sdes}
74266077Sdes
75266077SdesINLINE void
76266077Sdessldns_write_uint32(void *dst, uint32_t data)
77266077Sdes{
78266077Sdes#ifdef ALLOW_UNALIGNED_ACCESSES
79266077Sdes        * (uint32_t *) dst = htonl(data);
80266077Sdes#else
81266077Sdes        uint8_t *p = (uint8_t *) dst;
82266077Sdes        p[0] = (uint8_t) ((data >> 24) & 0xff);
83266077Sdes        p[1] = (uint8_t) ((data >> 16) & 0xff);
84266077Sdes        p[2] = (uint8_t) ((data >> 8) & 0xff);
85266077Sdes        p[3] = (uint8_t) (data & 0xff);
86266077Sdes#endif
87266077Sdes}
88266077Sdes
89266077Sdes
90266077Sdes/**
91266077Sdes * \file sbuffer.h
92266077Sdes *
93266077Sdes * This file contains the definition of sldns_buffer, and functions to manipulate those.
94266077Sdes */
95266077Sdes
96266077Sdes/**
97266077Sdes * implementation of buffers to ease operations
98266077Sdes *
99266077Sdes * sldns_buffers can contain arbitrary information, per octet. You can write
100266077Sdes * to the current end of a buffer, read from the current position, and
101266077Sdes * access any data within it.
102266077Sdes */
103266077Sdesstruct sldns_buffer
104266077Sdes{
105266077Sdes	/** The current position used for reading/writing */
106266077Sdes	size_t   _position;
107266077Sdes
108266077Sdes	/** The read/write limit */
109266077Sdes	size_t   _limit;
110266077Sdes
111266077Sdes	/** The amount of data the buffer can contain */
112266077Sdes	size_t   _capacity;
113266077Sdes
114266077Sdes	/** The data contained in the buffer */
115266077Sdes	uint8_t *_data;
116266077Sdes
117266077Sdes	/** If the buffer is fixed it cannot be resized */
118266077Sdes	unsigned _fixed : 1;
119266077Sdes
120266077Sdes	/** The current state of the buffer. If writing to the buffer fails
121266077Sdes	 * for any reason, this value is changed. This way, you can perform
122266077Sdes	 * multiple writes in sequence and check for success afterwards. */
123266077Sdes	unsigned _status_err : 1;
124266077Sdes};
125266077Sdestypedef struct sldns_buffer sldns_buffer;
126266077Sdes
127266077Sdes#ifdef NDEBUG
128266077SdesINLINE void
129266077Sdessldns_buffer_invariant(sldns_buffer *ATTR_UNUSED(buffer))
130266077Sdes{
131266077Sdes}
132266077Sdes#else
133266077SdesINLINE void
134266077Sdessldns_buffer_invariant(sldns_buffer *buffer)
135266077Sdes{
136266077Sdes	assert(buffer != NULL);
137266077Sdes	assert(buffer->_position <= buffer->_limit);
138266077Sdes	assert(buffer->_limit <= buffer->_capacity);
139266077Sdes	assert(buffer->_data != NULL);
140266077Sdes}
141266077Sdes#endif
142266077Sdes
143266077Sdes/**
144266077Sdes * creates a new buffer with the specified capacity.
145266077Sdes *
146266077Sdes * \param[in] capacity the size (in bytes) to allocate for the buffer
147266077Sdes * \return the created buffer
148266077Sdes */
149266077Sdessldns_buffer *sldns_buffer_new(size_t capacity);
150266077Sdes
151266077Sdes/**
152266077Sdes * creates a buffer with the specified data.  The data IS copied
153266077Sdes * and MEMORY allocations are done.  The buffer is not fixed and can
154266077Sdes * be resized using buffer_reserve().
155266077Sdes *
156266077Sdes * \param[in] buffer pointer to the buffer to put the data in
157266077Sdes * \param[in] data the data to encapsulate in the buffer
158266077Sdes * \param[in] size the size of the data
159266077Sdes */
160266077Sdesvoid sldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size);
161266077Sdes
162266077Sdes/**
163266077Sdes * Setup a buffer with the data pointed to. No data copied, no memory allocs.
164266077Sdes * The buffer is fixed.
165266077Sdes * \param[in] buffer pointer to the buffer to put the data in
166266077Sdes * \param[in] data the data to encapsulate in the buffer
167266077Sdes * \param[in] size the size of the data
168266077Sdes */
169266077Sdesvoid sldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size);
170266077Sdes
171266077Sdes/**
172266077Sdes * clears the buffer and make it ready for writing.  The buffer's limit
173266077Sdes * is set to the capacity and the position is set to 0.
174266077Sdes * \param[in] buffer the buffer to clear
175266077Sdes */
176266077SdesINLINE void sldns_buffer_clear(sldns_buffer *buffer)
177266077Sdes{
178266077Sdes	sldns_buffer_invariant(buffer);
179266077Sdes
180266077Sdes	/* reset status here? */
181266077Sdes
182266077Sdes	buffer->_position = 0;
183266077Sdes	buffer->_limit = buffer->_capacity;
184266077Sdes}
185266077Sdes
186266077Sdes/**
187266077Sdes * makes the buffer ready for reading the data that has been written to
188266077Sdes * the buffer.  The buffer's limit is set to the current position and
189266077Sdes * the position is set to 0.
190266077Sdes *
191266077Sdes * \param[in] buffer the buffer to flip
192266077Sdes * \return void
193266077Sdes */
194266077SdesINLINE void sldns_buffer_flip(sldns_buffer *buffer)
195266077Sdes{
196266077Sdes	sldns_buffer_invariant(buffer);
197266077Sdes
198266077Sdes	buffer->_limit = buffer->_position;
199266077Sdes	buffer->_position = 0;
200266077Sdes}
201266077Sdes
202266077Sdes/**
203266077Sdes * make the buffer ready for re-reading the data.  The buffer's
204266077Sdes * position is reset to 0.
205266077Sdes * \param[in] buffer the buffer to rewind
206266077Sdes */
207266077SdesINLINE void sldns_buffer_rewind(sldns_buffer *buffer)
208266077Sdes{
209266077Sdes	sldns_buffer_invariant(buffer);
210266077Sdes
211266077Sdes	buffer->_position = 0;
212266077Sdes}
213266077Sdes
214266077Sdes/**
215266077Sdes * returns the current position in the buffer (as a number of bytes)
216266077Sdes * \param[in] buffer the buffer
217266077Sdes * \return the current position
218266077Sdes */
219266077SdesINLINE size_t
220266077Sdessldns_buffer_position(sldns_buffer *buffer)
221266077Sdes{
222266077Sdes	return buffer->_position;
223266077Sdes}
224266077Sdes
225266077Sdes/**
226266077Sdes * sets the buffer's position to MARK.  The position must be less than
227266077Sdes * or equal to the buffer's limit.
228266077Sdes * \param[in] buffer the buffer
229266077Sdes * \param[in] mark the mark to use
230266077Sdes */
231266077SdesINLINE void
232266077Sdessldns_buffer_set_position(sldns_buffer *buffer, size_t mark)
233266077Sdes{
234266077Sdes	assert(mark <= buffer->_limit);
235266077Sdes	buffer->_position = mark;
236266077Sdes}
237266077Sdes
238266077Sdes/**
239266077Sdes * changes the buffer's position by COUNT bytes.  The position must not
240266077Sdes * be moved behind the buffer's limit or before the beginning of the
241266077Sdes * buffer.
242266077Sdes * \param[in] buffer the buffer
243266077Sdes * \param[in] count the count to use
244266077Sdes */
245266077SdesINLINE void
246266077Sdessldns_buffer_skip(sldns_buffer *buffer, ssize_t count)
247266077Sdes{
248266077Sdes	assert(buffer->_position + count <= buffer->_limit);
249266077Sdes	buffer->_position += count;
250266077Sdes}
251266077Sdes
252266077Sdes/**
253266077Sdes * returns the maximum size of the buffer
254266077Sdes * \param[in] buffer
255266077Sdes * \return the size
256266077Sdes */
257266077SdesINLINE size_t
258266077Sdessldns_buffer_limit(sldns_buffer *buffer)
259266077Sdes{
260266077Sdes	return buffer->_limit;
261266077Sdes}
262266077Sdes
263266077Sdes/**
264266077Sdes * changes the buffer's limit.  If the buffer's position is greater
265266077Sdes * than the new limit the position is set to the limit.
266266077Sdes * \param[in] buffer the buffer
267266077Sdes * \param[in] limit the new limit
268266077Sdes */
269266077SdesINLINE void
270266077Sdessldns_buffer_set_limit(sldns_buffer *buffer, size_t limit)
271266077Sdes{
272266077Sdes	assert(limit <= buffer->_capacity);
273266077Sdes	buffer->_limit = limit;
274266077Sdes	if (buffer->_position > buffer->_limit)
275266077Sdes		buffer->_position = buffer->_limit;
276266077Sdes}
277266077Sdes
278266077Sdes/**
279266077Sdes * returns the number of bytes the buffer can hold.
280266077Sdes * \param[in] buffer the buffer
281266077Sdes * \return the number of bytes
282266077Sdes */
283266077SdesINLINE size_t
284266077Sdessldns_buffer_capacity(sldns_buffer *buffer)
285266077Sdes{
286266077Sdes	return buffer->_capacity;
287266077Sdes}
288266077Sdes
289266077Sdes/**
290266077Sdes * changes the buffer's capacity.  The data is reallocated so any
291266077Sdes * pointers to the data may become invalid.  The buffer's limit is set
292266077Sdes * to the buffer's new capacity.
293266077Sdes * \param[in] buffer the buffer
294266077Sdes * \param[in] capacity the capacity to use
295266077Sdes * \return whether this failed or succeeded
296266077Sdes */
297266077Sdesint sldns_buffer_set_capacity(sldns_buffer *buffer, size_t capacity);
298266077Sdes
299266077Sdes/**
300266077Sdes * ensures BUFFER can contain at least AMOUNT more bytes.  The buffer's
301266077Sdes * capacity is increased if necessary using buffer_set_capacity().
302266077Sdes *
303266077Sdes * The buffer's limit is always set to the (possibly increased)
304266077Sdes * capacity.
305266077Sdes * \param[in] buffer the buffer
306266077Sdes * \param[in] amount amount to use
307266077Sdes * \return whether this failed or succeeded
308266077Sdes */
309266077Sdesint sldns_buffer_reserve(sldns_buffer *buffer, size_t amount);
310266077Sdes
311266077Sdes/**
312266077Sdes * returns a pointer to the data at the indicated position.
313266077Sdes * \param[in] buffer the buffer
314266077Sdes * \param[in] at position
315266077Sdes * \return the pointer to the data
316266077Sdes */
317266077SdesINLINE uint8_t *
318266077Sdessldns_buffer_at(const sldns_buffer *buffer, size_t at)
319266077Sdes{
320266077Sdes	assert(at <= buffer->_limit);
321266077Sdes	return buffer->_data + at;
322266077Sdes}
323266077Sdes
324266077Sdes/**
325266077Sdes * returns a pointer to the beginning of the buffer (the data at
326266077Sdes * position 0).
327266077Sdes * \param[in] buffer the buffer
328266077Sdes * \return the pointer
329266077Sdes */
330266077SdesINLINE uint8_t *
331266077Sdessldns_buffer_begin(const sldns_buffer *buffer)
332266077Sdes{
333266077Sdes	return sldns_buffer_at(buffer, 0);
334266077Sdes}
335266077Sdes
336266077Sdes/**
337266077Sdes * returns a pointer to the end of the buffer (the data at the buffer's
338266077Sdes * limit).
339266077Sdes * \param[in] buffer the buffer
340266077Sdes * \return the pointer
341266077Sdes */
342266077SdesINLINE uint8_t *
343266077Sdessldns_buffer_end(sldns_buffer *buffer)
344266077Sdes{
345266077Sdes	return sldns_buffer_at(buffer, buffer->_limit);
346266077Sdes}
347266077Sdes
348266077Sdes/**
349266077Sdes * returns a pointer to the data at the buffer's current position.
350266077Sdes * \param[in] buffer the buffer
351266077Sdes * \return the pointer
352266077Sdes */
353266077SdesINLINE uint8_t *
354266077Sdessldns_buffer_current(sldns_buffer *buffer)
355266077Sdes{
356266077Sdes	return sldns_buffer_at(buffer, buffer->_position);
357266077Sdes}
358266077Sdes
359266077Sdes/**
360266077Sdes * returns the number of bytes remaining between the indicated position and
361266077Sdes * the limit.
362266077Sdes * \param[in] buffer the buffer
363266077Sdes * \param[in] at indicated position
364266077Sdes * \return number of bytes
365266077Sdes */
366266077SdesINLINE size_t
367266077Sdessldns_buffer_remaining_at(sldns_buffer *buffer, size_t at)
368266077Sdes{
369266077Sdes	sldns_buffer_invariant(buffer);
370266077Sdes	assert(at <= buffer->_limit);
371266077Sdes	return buffer->_limit - at;
372266077Sdes}
373266077Sdes
374266077Sdes/**
375266077Sdes * returns the number of bytes remaining between the buffer's position and
376266077Sdes * limit.
377266077Sdes * \param[in] buffer the buffer
378266077Sdes * \return the number of bytes
379266077Sdes */
380266077SdesINLINE size_t
381266077Sdessldns_buffer_remaining(sldns_buffer *buffer)
382266077Sdes{
383266077Sdes	return sldns_buffer_remaining_at(buffer, buffer->_position);
384266077Sdes}
385266077Sdes
386266077Sdes/**
387266077Sdes * checks if the buffer has at least COUNT more bytes available.
388266077Sdes * Before reading or writing the caller needs to ensure enough space
389266077Sdes * is available!
390266077Sdes * \param[in] buffer the buffer
391266077Sdes * \param[in] at indicated position
392266077Sdes * \param[in] count how much is available
393266077Sdes * \return true or false (as int?)
394266077Sdes */
395266077SdesINLINE int
396266077Sdessldns_buffer_available_at(sldns_buffer *buffer, size_t at, size_t count)
397266077Sdes{
398266077Sdes	return count <= sldns_buffer_remaining_at(buffer, at);
399266077Sdes}
400266077Sdes
401266077Sdes/**
402266077Sdes * checks if the buffer has count bytes available at the current position
403266077Sdes * \param[in] buffer the buffer
404266077Sdes * \param[in] count how much is available
405266077Sdes * \return true or false (as int?)
406266077Sdes */
407266077SdesINLINE int
408266077Sdessldns_buffer_available(sldns_buffer *buffer, size_t count)
409266077Sdes{
410266077Sdes	return sldns_buffer_available_at(buffer, buffer->_position, count);
411266077Sdes}
412266077Sdes
413266077Sdes/**
414266077Sdes * writes the given data to the buffer at the specified position
415266077Sdes * \param[in] buffer the buffer
416266077Sdes * \param[in] at the position (in number of bytes) to write the data at
417266077Sdes * \param[in] data pointer to the data to write to the buffer
418266077Sdes * \param[in] count the number of bytes of data to write
419266077Sdes */
420266077SdesINLINE void
421266077Sdessldns_buffer_write_at(sldns_buffer *buffer, size_t at, const void *data, size_t count)
422266077Sdes{
423266077Sdes	assert(sldns_buffer_available_at(buffer, at, count));
424266077Sdes	memcpy(buffer->_data + at, data, count);
425266077Sdes}
426266077Sdes
427266077Sdes/**
428266077Sdes * writes count bytes of data to the current position of the buffer
429266077Sdes * \param[in] buffer the buffer
430266077Sdes * \param[in] data the data to write
431266077Sdes * \param[in] count the lenght of the data to write
432266077Sdes */
433266077SdesINLINE void
434266077Sdessldns_buffer_write(sldns_buffer *buffer, const void *data, size_t count)
435266077Sdes{
436266077Sdes	sldns_buffer_write_at(buffer, buffer->_position, data, count);
437266077Sdes	buffer->_position += count;
438266077Sdes}
439266077Sdes
440266077Sdes/**
441266077Sdes * copies the given (null-delimited) string to the specified position at the buffer
442266077Sdes * \param[in] buffer the buffer
443266077Sdes * \param[in] at the position in the buffer
444266077Sdes * \param[in] str the string to write
445266077Sdes */
446266077SdesINLINE void
447266077Sdessldns_buffer_write_string_at(sldns_buffer *buffer, size_t at, const char *str)
448266077Sdes{
449266077Sdes	sldns_buffer_write_at(buffer, at, str, strlen(str));
450266077Sdes}
451266077Sdes
452266077Sdes/**
453266077Sdes * copies the given (null-delimited) string to the current position at the buffer
454266077Sdes * \param[in] buffer the buffer
455266077Sdes * \param[in] str the string to write
456266077Sdes */
457266077SdesINLINE void
458266077Sdessldns_buffer_write_string(sldns_buffer *buffer, const char *str)
459266077Sdes{
460266077Sdes	sldns_buffer_write(buffer, str, strlen(str));
461266077Sdes}
462266077Sdes
463266077Sdes/**
464266077Sdes * writes the given byte of data at the given position in the buffer
465266077Sdes * \param[in] buffer the buffer
466266077Sdes * \param[in] at the position in the buffer
467266077Sdes * \param[in] data the 8 bits to write
468266077Sdes */
469266077SdesINLINE void
470266077Sdessldns_buffer_write_u8_at(sldns_buffer *buffer, size_t at, uint8_t data)
471266077Sdes{
472266077Sdes	assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
473266077Sdes	buffer->_data[at] = data;
474266077Sdes}
475266077Sdes
476266077Sdes/**
477266077Sdes * writes the given byte of data at the current position in the buffer
478266077Sdes * \param[in] buffer the buffer
479266077Sdes * \param[in] data the 8 bits to write
480266077Sdes */
481266077SdesINLINE void
482266077Sdessldns_buffer_write_u8(sldns_buffer *buffer, uint8_t data)
483266077Sdes{
484266077Sdes	sldns_buffer_write_u8_at(buffer, buffer->_position, data);
485266077Sdes	buffer->_position += sizeof(data);
486266077Sdes}
487266077Sdes
488266077Sdes/**
489266077Sdes * writes the given 2 byte integer at the given position in the buffer
490266077Sdes * \param[in] buffer the buffer
491266077Sdes * \param[in] at the position in the buffer
492266077Sdes * \param[in] data the 16 bits to write
493266077Sdes */
494266077SdesINLINE void
495266077Sdessldns_buffer_write_u16_at(sldns_buffer *buffer, size_t at, uint16_t data)
496266077Sdes{
497266077Sdes	assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
498266077Sdes	sldns_write_uint16(buffer->_data + at, data);
499266077Sdes}
500266077Sdes
501266077Sdes/**
502266077Sdes * writes the given 2 byte integer at the current position in the buffer
503266077Sdes * \param[in] buffer the buffer
504266077Sdes * \param[in] data the 16 bits to write
505266077Sdes */
506266077SdesINLINE void
507266077Sdessldns_buffer_write_u16(sldns_buffer *buffer, uint16_t data)
508266077Sdes{
509266077Sdes	sldns_buffer_write_u16_at(buffer, buffer->_position, data);
510266077Sdes	buffer->_position += sizeof(data);
511266077Sdes}
512266077Sdes
513266077Sdes/**
514266077Sdes * writes the given 4 byte integer at the given position in the buffer
515266077Sdes * \param[in] buffer the buffer
516266077Sdes * \param[in] at the position in the buffer
517266077Sdes * \param[in] data the 32 bits to write
518266077Sdes */
519266077SdesINLINE void
520266077Sdessldns_buffer_write_u32_at(sldns_buffer *buffer, size_t at, uint32_t data)
521266077Sdes{
522266077Sdes	assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
523266077Sdes	sldns_write_uint32(buffer->_data + at, data);
524266077Sdes}
525266077Sdes
526266077Sdes/**
527266077Sdes * writes the given 4 byte integer at the current position in the buffer
528266077Sdes * \param[in] buffer the buffer
529266077Sdes * \param[in] data the 32 bits to write
530266077Sdes */
531266077SdesINLINE void
532266077Sdessldns_buffer_write_u32(sldns_buffer *buffer, uint32_t data)
533266077Sdes{
534266077Sdes	sldns_buffer_write_u32_at(buffer, buffer->_position, data);
535266077Sdes	buffer->_position += sizeof(data);
536266077Sdes}
537266077Sdes
538266077Sdes/**
539266077Sdes * copies count bytes of data at the given position to the given data-array
540266077Sdes * \param[in] buffer the buffer
541266077Sdes * \param[in] at the position in the buffer to start
542266077Sdes * \param[out] data buffer to copy to
543266077Sdes * \param[in] count the length of the data to copy
544266077Sdes */
545266077SdesINLINE void
546266077Sdessldns_buffer_read_at(sldns_buffer *buffer, size_t at, void *data, size_t count)
547266077Sdes{
548266077Sdes	assert(sldns_buffer_available_at(buffer, at, count));
549266077Sdes	memcpy(data, buffer->_data + at, count);
550266077Sdes}
551266077Sdes
552266077Sdes/**
553266077Sdes * copies count bytes of data at the current position to the given data-array
554266077Sdes * \param[in] buffer the buffer
555266077Sdes * \param[out] data buffer to copy to
556266077Sdes * \param[in] count the length of the data to copy
557266077Sdes */
558266077SdesINLINE void
559266077Sdessldns_buffer_read(sldns_buffer *buffer, void *data, size_t count)
560266077Sdes{
561266077Sdes	sldns_buffer_read_at(buffer, buffer->_position, data, count);
562266077Sdes	buffer->_position += count;
563266077Sdes}
564266077Sdes
565266077Sdes/**
566266077Sdes * returns the byte value at the given position in the buffer
567266077Sdes * \param[in] buffer the buffer
568266077Sdes * \param[in] at the position in the buffer
569266077Sdes * \return 1 byte integer
570266077Sdes */
571266077SdesINLINE uint8_t
572266077Sdessldns_buffer_read_u8_at(sldns_buffer *buffer, size_t at)
573266077Sdes{
574266077Sdes	assert(sldns_buffer_available_at(buffer, at, sizeof(uint8_t)));
575266077Sdes	return buffer->_data[at];
576266077Sdes}
577266077Sdes
578266077Sdes/**
579266077Sdes * returns the byte value at the current position in the buffer
580266077Sdes * \param[in] buffer the buffer
581266077Sdes * \return 1 byte integer
582266077Sdes */
583266077SdesINLINE uint8_t
584266077Sdessldns_buffer_read_u8(sldns_buffer *buffer)
585266077Sdes{
586266077Sdes	uint8_t result = sldns_buffer_read_u8_at(buffer, buffer->_position);
587266077Sdes	buffer->_position += sizeof(uint8_t);
588266077Sdes	return result;
589266077Sdes}
590266077Sdes
591266077Sdes/**
592266077Sdes * returns the 2-byte integer value at the given position in the buffer
593266077Sdes * \param[in] buffer the buffer
594266077Sdes * \param[in] at position in the buffer
595266077Sdes * \return 2 byte integer
596266077Sdes */
597266077SdesINLINE uint16_t
598266077Sdessldns_buffer_read_u16_at(sldns_buffer *buffer, size_t at)
599266077Sdes{
600266077Sdes	assert(sldns_buffer_available_at(buffer, at, sizeof(uint16_t)));
601266077Sdes	return sldns_read_uint16(buffer->_data + at);
602266077Sdes}
603266077Sdes
604266077Sdes/**
605266077Sdes * returns the 2-byte integer value at the current position in the buffer
606266077Sdes * \param[in] buffer the buffer
607266077Sdes * \return 2 byte integer
608266077Sdes */
609266077SdesINLINE uint16_t
610266077Sdessldns_buffer_read_u16(sldns_buffer *buffer)
611266077Sdes{
612266077Sdes	uint16_t result = sldns_buffer_read_u16_at(buffer, buffer->_position);
613266077Sdes	buffer->_position += sizeof(uint16_t);
614266077Sdes	return result;
615266077Sdes}
616266077Sdes
617266077Sdes/**
618266077Sdes * returns the 4-byte integer value at the given position in the buffer
619266077Sdes * \param[in] buffer the buffer
620266077Sdes * \param[in] at position in the buffer
621266077Sdes * \return 4 byte integer
622266077Sdes */
623266077SdesINLINE uint32_t
624266077Sdessldns_buffer_read_u32_at(sldns_buffer *buffer, size_t at)
625266077Sdes{
626266077Sdes	assert(sldns_buffer_available_at(buffer, at, sizeof(uint32_t)));
627266077Sdes	return sldns_read_uint32(buffer->_data + at);
628266077Sdes}
629266077Sdes
630266077Sdes/**
631266077Sdes * returns the 4-byte integer value at the current position in the buffer
632266077Sdes * \param[in] buffer the buffer
633266077Sdes * \return 4 byte integer
634266077Sdes */
635266077SdesINLINE uint32_t
636266077Sdessldns_buffer_read_u32(sldns_buffer *buffer)
637266077Sdes{
638266077Sdes	uint32_t result = sldns_buffer_read_u32_at(buffer, buffer->_position);
639266077Sdes	buffer->_position += sizeof(uint32_t);
640266077Sdes	return result;
641266077Sdes}
642266077Sdes
643266077Sdes/**
644266077Sdes * returns the status of the buffer
645266077Sdes * \param[in] buffer
646266077Sdes * \return the status
647266077Sdes */
648266077SdesINLINE int
649266077Sdessldns_buffer_status(sldns_buffer *buffer)
650266077Sdes{
651266077Sdes	return (int)buffer->_status_err;
652266077Sdes}
653266077Sdes
654266077Sdes/**
655266077Sdes * returns true if the status of the buffer is LDNS_STATUS_OK, false otherwise
656266077Sdes * \param[in] buffer the buffer
657266077Sdes * \return true or false
658266077Sdes */
659266077SdesINLINE int
660266077Sdessldns_buffer_status_ok(sldns_buffer *buffer)
661266077Sdes{
662266077Sdes	if (buffer) {
663266077Sdes		return sldns_buffer_status(buffer) == 0;
664266077Sdes	} else {
665266077Sdes		return 0;
666266077Sdes	}
667266077Sdes}
668266077Sdes
669266077Sdes/**
670266077Sdes * prints to the buffer, increasing the capacity if required using
671266077Sdes * buffer_reserve(). The buffer's position is set to the terminating '\\0'
672266077Sdes * Returns the number of characters written (not including the
673266077Sdes * terminating '\\0') or -1 on failure.
674266077Sdes */
675266077Sdesint sldns_buffer_printf(sldns_buffer *buffer, const char *format, ...)
676266077Sdes	ATTR_FORMAT(printf, 2, 3);
677266077Sdes
678266077Sdes/**
679266077Sdes * frees the buffer.
680266077Sdes * \param[in] *buffer the buffer to be freed
681266077Sdes * \return void
682266077Sdes */
683266077Sdesvoid sldns_buffer_free(sldns_buffer *buffer);
684266077Sdes
685266077Sdes/**
686266077Sdes * Makes the buffer fixed and returns a pointer to the data.  The
687266077Sdes * caller is responsible for free'ing the result.
688266077Sdes * \param[in] *buffer the buffer to be exported
689266077Sdes * \return void
690266077Sdes */
691266077Sdesvoid *sldns_buffer_export(sldns_buffer *buffer);
692266077Sdes
693266077Sdes/**
694266077Sdes * Copy contents of the from buffer to the result buffer and then flips
695266077Sdes * the result buffer. Data will be silently truncated if the result buffer is
696266077Sdes * too small.
697266077Sdes * \param[out] *result resulting buffer which is copied to.
698266077Sdes * \param[in] *from what to copy to result.
699266077Sdes */
700266077Sdesvoid sldns_buffer_copy(sldns_buffer* result, sldns_buffer* from);
701266077Sdes
702266077Sdes#ifdef __cplusplus
703266077Sdes}
704266077Sdes#endif
705266077Sdes
706266077Sdes#endif /* LDNS_SBUFFER_H */
707