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
90356345ScyINLINE void
91356345Scysldns_write_uint48(void *dst, uint64_t data)
92356345Scy{
93356345Scy        uint8_t *p = (uint8_t *) dst;
94356345Scy        p[0] = (uint8_t) ((data >> 40) & 0xff);
95356345Scy        p[1] = (uint8_t) ((data >> 32) & 0xff);
96356345Scy        p[2] = (uint8_t) ((data >> 24) & 0xff);
97356345Scy        p[3] = (uint8_t) ((data >> 16) & 0xff);
98356345Scy        p[4] = (uint8_t) ((data >> 8) & 0xff);
99356345Scy        p[5] = (uint8_t) (data & 0xff);
100356345Scy}
101356345Scy
102356345Scy
103266077Sdes/**
104266077Sdes * \file sbuffer.h
105266077Sdes *
106266077Sdes * This file contains the definition of sldns_buffer, and functions to manipulate those.
107266077Sdes */
108266077Sdes
109266077Sdes/**
110266077Sdes * implementation of buffers to ease operations
111266077Sdes *
112266077Sdes * sldns_buffers can contain arbitrary information, per octet. You can write
113266077Sdes * to the current end of a buffer, read from the current position, and
114266077Sdes * access any data within it.
115266077Sdes */
116266077Sdesstruct sldns_buffer
117266077Sdes{
118266077Sdes	/** The current position used for reading/writing */
119266077Sdes	size_t   _position;
120266077Sdes
121266077Sdes	/** The read/write limit */
122266077Sdes	size_t   _limit;
123266077Sdes
124266077Sdes	/** The amount of data the buffer can contain */
125266077Sdes	size_t   _capacity;
126266077Sdes
127266077Sdes	/** The data contained in the buffer */
128266077Sdes	uint8_t *_data;
129266077Sdes
130266077Sdes	/** If the buffer is fixed it cannot be resized */
131266077Sdes	unsigned _fixed : 1;
132266077Sdes
133266077Sdes	/** The current state of the buffer. If writing to the buffer fails
134266077Sdes	 * for any reason, this value is changed. This way, you can perform
135266077Sdes	 * multiple writes in sequence and check for success afterwards. */
136266077Sdes	unsigned _status_err : 1;
137266077Sdes};
138266077Sdestypedef struct sldns_buffer sldns_buffer;
139266077Sdes
140266077Sdes#ifdef NDEBUG
141266077SdesINLINE void
142266077Sdessldns_buffer_invariant(sldns_buffer *ATTR_UNUSED(buffer))
143266077Sdes{
144266077Sdes}
145266077Sdes#else
146266077SdesINLINE void
147266077Sdessldns_buffer_invariant(sldns_buffer *buffer)
148266077Sdes{
149266077Sdes	assert(buffer != NULL);
150266077Sdes	assert(buffer->_position <= buffer->_limit);
151266077Sdes	assert(buffer->_limit <= buffer->_capacity);
152266077Sdes	assert(buffer->_data != NULL);
153266077Sdes}
154266077Sdes#endif
155266077Sdes
156266077Sdes/**
157266077Sdes * creates a new buffer with the specified capacity.
158266077Sdes *
159266077Sdes * \param[in] capacity the size (in bytes) to allocate for the buffer
160266077Sdes * \return the created buffer
161266077Sdes */
162266077Sdessldns_buffer *sldns_buffer_new(size_t capacity);
163266077Sdes
164266077Sdes/**
165266077Sdes * creates a buffer with the specified data.  The data IS copied
166266077Sdes * and MEMORY allocations are done.  The buffer is not fixed and can
167266077Sdes * be resized using buffer_reserve().
168266077Sdes *
169266077Sdes * \param[in] buffer pointer to the buffer to put the data in
170266077Sdes * \param[in] data the data to encapsulate in the buffer
171266077Sdes * \param[in] size the size of the data
172266077Sdes */
173266077Sdesvoid sldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size);
174266077Sdes
175266077Sdes/**
176266077Sdes * Setup a buffer with the data pointed to. No data copied, no memory allocs.
177266077Sdes * The buffer is fixed.
178266077Sdes * \param[in] buffer pointer to the buffer to put the data in
179266077Sdes * \param[in] data the data to encapsulate in the buffer
180266077Sdes * \param[in] size the size of the data
181266077Sdes */
182266077Sdesvoid sldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size);
183266077Sdes
184266077Sdes/**
185266077Sdes * clears the buffer and make it ready for writing.  The buffer's limit
186266077Sdes * is set to the capacity and the position is set to 0.
187266077Sdes * \param[in] buffer the buffer to clear
188266077Sdes */
189266077SdesINLINE void sldns_buffer_clear(sldns_buffer *buffer)
190266077Sdes{
191266077Sdes	sldns_buffer_invariant(buffer);
192266077Sdes
193266077Sdes	/* reset status here? */
194266077Sdes
195266077Sdes	buffer->_position = 0;
196266077Sdes	buffer->_limit = buffer->_capacity;
197266077Sdes}
198266077Sdes
199266077Sdes/**
200266077Sdes * makes the buffer ready for reading the data that has been written to
201266077Sdes * the buffer.  The buffer's limit is set to the current position and
202266077Sdes * the position is set to 0.
203266077Sdes *
204266077Sdes * \param[in] buffer the buffer to flip
205266077Sdes * \return void
206266077Sdes */
207266077SdesINLINE void sldns_buffer_flip(sldns_buffer *buffer)
208266077Sdes{
209266077Sdes	sldns_buffer_invariant(buffer);
210266077Sdes
211266077Sdes	buffer->_limit = buffer->_position;
212266077Sdes	buffer->_position = 0;
213266077Sdes}
214266077Sdes
215266077Sdes/**
216266077Sdes * make the buffer ready for re-reading the data.  The buffer's
217266077Sdes * position is reset to 0.
218266077Sdes * \param[in] buffer the buffer to rewind
219266077Sdes */
220266077SdesINLINE void sldns_buffer_rewind(sldns_buffer *buffer)
221266077Sdes{
222266077Sdes	sldns_buffer_invariant(buffer);
223266077Sdes
224266077Sdes	buffer->_position = 0;
225266077Sdes}
226266077Sdes
227266077Sdes/**
228266077Sdes * returns the current position in the buffer (as a number of bytes)
229266077Sdes * \param[in] buffer the buffer
230266077Sdes * \return the current position
231266077Sdes */
232266077SdesINLINE size_t
233266077Sdessldns_buffer_position(sldns_buffer *buffer)
234266077Sdes{
235266077Sdes	return buffer->_position;
236266077Sdes}
237266077Sdes
238266077Sdes/**
239266077Sdes * sets the buffer's position to MARK.  The position must be less than
240266077Sdes * or equal to the buffer's limit.
241266077Sdes * \param[in] buffer the buffer
242266077Sdes * \param[in] mark the mark to use
243266077Sdes */
244266077SdesINLINE void
245266077Sdessldns_buffer_set_position(sldns_buffer *buffer, size_t mark)
246266077Sdes{
247266077Sdes	assert(mark <= buffer->_limit);
248266077Sdes	buffer->_position = mark;
249266077Sdes}
250266077Sdes
251266077Sdes/**
252266077Sdes * changes the buffer's position by COUNT bytes.  The position must not
253266077Sdes * be moved behind the buffer's limit or before the beginning of the
254266077Sdes * buffer.
255266077Sdes * \param[in] buffer the buffer
256266077Sdes * \param[in] count the count to use
257266077Sdes */
258266077SdesINLINE void
259266077Sdessldns_buffer_skip(sldns_buffer *buffer, ssize_t count)
260266077Sdes{
261266077Sdes	assert(buffer->_position + count <= buffer->_limit);
262266077Sdes	buffer->_position += count;
263266077Sdes}
264266077Sdes
265266077Sdes/**
266266077Sdes * returns the maximum size of the buffer
267266077Sdes * \param[in] buffer
268266077Sdes * \return the size
269266077Sdes */
270266077SdesINLINE size_t
271266077Sdessldns_buffer_limit(sldns_buffer *buffer)
272266077Sdes{
273266077Sdes	return buffer->_limit;
274266077Sdes}
275266077Sdes
276266077Sdes/**
277266077Sdes * changes the buffer's limit.  If the buffer's position is greater
278266077Sdes * than the new limit the position is set to the limit.
279266077Sdes * \param[in] buffer the buffer
280266077Sdes * \param[in] limit the new limit
281266077Sdes */
282266077SdesINLINE void
283266077Sdessldns_buffer_set_limit(sldns_buffer *buffer, size_t limit)
284266077Sdes{
285266077Sdes	assert(limit <= buffer->_capacity);
286266077Sdes	buffer->_limit = limit;
287266077Sdes	if (buffer->_position > buffer->_limit)
288266077Sdes		buffer->_position = buffer->_limit;
289266077Sdes}
290266077Sdes
291266077Sdes/**
292266077Sdes * returns the number of bytes the buffer can hold.
293266077Sdes * \param[in] buffer the buffer
294266077Sdes * \return the number of bytes
295266077Sdes */
296266077SdesINLINE size_t
297266077Sdessldns_buffer_capacity(sldns_buffer *buffer)
298266077Sdes{
299266077Sdes	return buffer->_capacity;
300266077Sdes}
301266077Sdes
302266077Sdes/**
303266077Sdes * changes the buffer's capacity.  The data is reallocated so any
304266077Sdes * pointers to the data may become invalid.  The buffer's limit is set
305266077Sdes * to the buffer's new capacity.
306266077Sdes * \param[in] buffer the buffer
307266077Sdes * \param[in] capacity the capacity to use
308266077Sdes * \return whether this failed or succeeded
309266077Sdes */
310266077Sdesint sldns_buffer_set_capacity(sldns_buffer *buffer, size_t capacity);
311266077Sdes
312266077Sdes/**
313266077Sdes * ensures BUFFER can contain at least AMOUNT more bytes.  The buffer's
314266077Sdes * capacity is increased if necessary using buffer_set_capacity().
315266077Sdes *
316266077Sdes * The buffer's limit is always set to the (possibly increased)
317266077Sdes * capacity.
318266077Sdes * \param[in] buffer the buffer
319266077Sdes * \param[in] amount amount to use
320266077Sdes * \return whether this failed or succeeded
321266077Sdes */
322266077Sdesint sldns_buffer_reserve(sldns_buffer *buffer, size_t amount);
323266077Sdes
324266077Sdes/**
325266077Sdes * returns a pointer to the data at the indicated position.
326266077Sdes * \param[in] buffer the buffer
327266077Sdes * \param[in] at position
328266077Sdes * \return the pointer to the data
329266077Sdes */
330266077SdesINLINE uint8_t *
331266077Sdessldns_buffer_at(const sldns_buffer *buffer, size_t at)
332266077Sdes{
333266077Sdes	assert(at <= buffer->_limit);
334266077Sdes	return buffer->_data + at;
335266077Sdes}
336266077Sdes
337266077Sdes/**
338266077Sdes * returns a pointer to the beginning of the buffer (the data at
339266077Sdes * position 0).
340266077Sdes * \param[in] buffer the buffer
341266077Sdes * \return the pointer
342266077Sdes */
343266077SdesINLINE uint8_t *
344266077Sdessldns_buffer_begin(const sldns_buffer *buffer)
345266077Sdes{
346266077Sdes	return sldns_buffer_at(buffer, 0);
347266077Sdes}
348266077Sdes
349266077Sdes/**
350266077Sdes * returns a pointer to the end of the buffer (the data at the buffer's
351266077Sdes * limit).
352266077Sdes * \param[in] buffer the buffer
353266077Sdes * \return the pointer
354266077Sdes */
355266077SdesINLINE uint8_t *
356266077Sdessldns_buffer_end(sldns_buffer *buffer)
357266077Sdes{
358266077Sdes	return sldns_buffer_at(buffer, buffer->_limit);
359266077Sdes}
360266077Sdes
361266077Sdes/**
362266077Sdes * returns a pointer to the data at the buffer's current position.
363266077Sdes * \param[in] buffer the buffer
364266077Sdes * \return the pointer
365266077Sdes */
366266077SdesINLINE uint8_t *
367266077Sdessldns_buffer_current(sldns_buffer *buffer)
368266077Sdes{
369266077Sdes	return sldns_buffer_at(buffer, buffer->_position);
370266077Sdes}
371266077Sdes
372266077Sdes/**
373266077Sdes * returns the number of bytes remaining between the indicated position and
374266077Sdes * the limit.
375266077Sdes * \param[in] buffer the buffer
376266077Sdes * \param[in] at indicated position
377266077Sdes * \return number of bytes
378266077Sdes */
379266077SdesINLINE size_t
380266077Sdessldns_buffer_remaining_at(sldns_buffer *buffer, size_t at)
381266077Sdes{
382266077Sdes	sldns_buffer_invariant(buffer);
383266077Sdes	assert(at <= buffer->_limit);
384356345Scy	return at < buffer->_limit ? buffer->_limit - at : 0;
385266077Sdes}
386266077Sdes
387266077Sdes/**
388266077Sdes * returns the number of bytes remaining between the buffer's position and
389266077Sdes * limit.
390266077Sdes * \param[in] buffer the buffer
391266077Sdes * \return the number of bytes
392266077Sdes */
393266077SdesINLINE size_t
394266077Sdessldns_buffer_remaining(sldns_buffer *buffer)
395266077Sdes{
396266077Sdes	return sldns_buffer_remaining_at(buffer, buffer->_position);
397266077Sdes}
398266077Sdes
399266077Sdes/**
400266077Sdes * checks if the buffer has at least COUNT more bytes available.
401266077Sdes * Before reading or writing the caller needs to ensure enough space
402266077Sdes * is available!
403266077Sdes * \param[in] buffer the buffer
404266077Sdes * \param[in] at indicated position
405266077Sdes * \param[in] count how much is available
406266077Sdes * \return true or false (as int?)
407266077Sdes */
408266077SdesINLINE int
409266077Sdessldns_buffer_available_at(sldns_buffer *buffer, size_t at, size_t count)
410266077Sdes{
411266077Sdes	return count <= sldns_buffer_remaining_at(buffer, at);
412266077Sdes}
413266077Sdes
414266077Sdes/**
415266077Sdes * checks if the buffer has count bytes available at the current position
416266077Sdes * \param[in] buffer the buffer
417266077Sdes * \param[in] count how much is available
418266077Sdes * \return true or false (as int?)
419266077Sdes */
420266077SdesINLINE int
421266077Sdessldns_buffer_available(sldns_buffer *buffer, size_t count)
422266077Sdes{
423266077Sdes	return sldns_buffer_available_at(buffer, buffer->_position, count);
424266077Sdes}
425266077Sdes
426266077Sdes/**
427266077Sdes * writes the given data to the buffer at the specified position
428266077Sdes * \param[in] buffer the buffer
429266077Sdes * \param[in] at the position (in number of bytes) to write the data at
430266077Sdes * \param[in] data pointer to the data to write to the buffer
431266077Sdes * \param[in] count the number of bytes of data to write
432266077Sdes */
433266077SdesINLINE void
434266077Sdessldns_buffer_write_at(sldns_buffer *buffer, size_t at, const void *data, size_t count)
435266077Sdes{
436266077Sdes	assert(sldns_buffer_available_at(buffer, at, count));
437266077Sdes	memcpy(buffer->_data + at, data, count);
438266077Sdes}
439266077Sdes
440266077Sdes/**
441356345Scy * set the given byte to the buffer at the specified position
442356345Scy * \param[in] buffer the buffer
443356345Scy * \param[in] at the position (in number of bytes) to write the data at
444356345Scy * \param[in] c the byte to set to the buffer
445356345Scy * \param[in] count the number of bytes of bytes to write
446356345Scy */
447356345Scy
448356345ScyINLINE void
449356345Scysldns_buffer_set_at(sldns_buffer *buffer, size_t at, int c, size_t count)
450356345Scy{
451356345Scy	assert(sldns_buffer_available_at(buffer, at, count));
452356345Scy	memset(buffer->_data + at, c, count);
453356345Scy}
454356345Scy
455356345Scy
456356345Scy/**
457266077Sdes * writes count bytes of data to the current position of the buffer
458266077Sdes * \param[in] buffer the buffer
459266077Sdes * \param[in] data the data to write
460356345Scy * \param[in] count the length of the data to write
461266077Sdes */
462266077SdesINLINE void
463266077Sdessldns_buffer_write(sldns_buffer *buffer, const void *data, size_t count)
464266077Sdes{
465266077Sdes	sldns_buffer_write_at(buffer, buffer->_position, data, count);
466266077Sdes	buffer->_position += count;
467266077Sdes}
468266077Sdes
469266077Sdes/**
470266077Sdes * copies the given (null-delimited) string to the specified position at the buffer
471266077Sdes * \param[in] buffer the buffer
472266077Sdes * \param[in] at the position in the buffer
473266077Sdes * \param[in] str the string to write
474266077Sdes */
475266077SdesINLINE void
476266077Sdessldns_buffer_write_string_at(sldns_buffer *buffer, size_t at, const char *str)
477266077Sdes{
478266077Sdes	sldns_buffer_write_at(buffer, at, str, strlen(str));
479266077Sdes}
480266077Sdes
481266077Sdes/**
482266077Sdes * copies the given (null-delimited) string to the current position at the buffer
483266077Sdes * \param[in] buffer the buffer
484266077Sdes * \param[in] str the string to write
485266077Sdes */
486266077SdesINLINE void
487266077Sdessldns_buffer_write_string(sldns_buffer *buffer, const char *str)
488266077Sdes{
489266077Sdes	sldns_buffer_write(buffer, str, strlen(str));
490266077Sdes}
491266077Sdes
492266077Sdes/**
493266077Sdes * writes the given byte of data at the given position in the buffer
494266077Sdes * \param[in] buffer the buffer
495266077Sdes * \param[in] at the position in the buffer
496266077Sdes * \param[in] data the 8 bits to write
497266077Sdes */
498266077SdesINLINE void
499266077Sdessldns_buffer_write_u8_at(sldns_buffer *buffer, size_t at, uint8_t data)
500266077Sdes{
501266077Sdes	assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
502266077Sdes	buffer->_data[at] = data;
503266077Sdes}
504266077Sdes
505266077Sdes/**
506266077Sdes * writes the given byte of data at the current position in the buffer
507266077Sdes * \param[in] buffer the buffer
508266077Sdes * \param[in] data the 8 bits to write
509266077Sdes */
510266077SdesINLINE void
511266077Sdessldns_buffer_write_u8(sldns_buffer *buffer, uint8_t data)
512266077Sdes{
513266077Sdes	sldns_buffer_write_u8_at(buffer, buffer->_position, data);
514266077Sdes	buffer->_position += sizeof(data);
515266077Sdes}
516266077Sdes
517266077Sdes/**
518266077Sdes * writes the given 2 byte integer at the given position in the buffer
519266077Sdes * \param[in] buffer the buffer
520266077Sdes * \param[in] at the position in the buffer
521266077Sdes * \param[in] data the 16 bits to write
522266077Sdes */
523266077SdesINLINE void
524266077Sdessldns_buffer_write_u16_at(sldns_buffer *buffer, size_t at, uint16_t data)
525266077Sdes{
526266077Sdes	assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
527266077Sdes	sldns_write_uint16(buffer->_data + at, data);
528266077Sdes}
529266077Sdes
530266077Sdes/**
531266077Sdes * writes the given 2 byte integer at the current position in the buffer
532266077Sdes * \param[in] buffer the buffer
533266077Sdes * \param[in] data the 16 bits to write
534266077Sdes */
535266077SdesINLINE void
536266077Sdessldns_buffer_write_u16(sldns_buffer *buffer, uint16_t data)
537266077Sdes{
538266077Sdes	sldns_buffer_write_u16_at(buffer, buffer->_position, data);
539266077Sdes	buffer->_position += sizeof(data);
540266077Sdes}
541266077Sdes
542266077Sdes/**
543266077Sdes * writes the given 4 byte integer at the given position in the buffer
544266077Sdes * \param[in] buffer the buffer
545266077Sdes * \param[in] at the position in the buffer
546266077Sdes * \param[in] data the 32 bits to write
547266077Sdes */
548266077SdesINLINE void
549266077Sdessldns_buffer_write_u32_at(sldns_buffer *buffer, size_t at, uint32_t data)
550266077Sdes{
551266077Sdes	assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
552266077Sdes	sldns_write_uint32(buffer->_data + at, data);
553266077Sdes}
554266077Sdes
555266077Sdes/**
556356345Scy * writes the given 6 byte integer at the given position in the buffer
557356345Scy * \param[in] buffer the buffer
558356345Scy * \param[in] at the position in the buffer
559356345Scy * \param[in] data the (lower) 48 bits to write
560356345Scy */
561356345ScyINLINE void
562356345Scysldns_buffer_write_u48_at(sldns_buffer *buffer, size_t at, uint64_t data)
563356345Scy{
564356345Scy	assert(sldns_buffer_available_at(buffer, at, 6));
565356345Scy	sldns_write_uint48(buffer->_data + at, data);
566356345Scy}
567356345Scy
568356345Scy/**
569266077Sdes * writes the given 4 byte integer at the current position in the buffer
570266077Sdes * \param[in] buffer the buffer
571266077Sdes * \param[in] data the 32 bits to write
572266077Sdes */
573266077SdesINLINE void
574266077Sdessldns_buffer_write_u32(sldns_buffer *buffer, uint32_t data)
575266077Sdes{
576266077Sdes	sldns_buffer_write_u32_at(buffer, buffer->_position, data);
577266077Sdes	buffer->_position += sizeof(data);
578266077Sdes}
579266077Sdes
580266077Sdes/**
581356345Scy * writes the given 6 byte integer at the current position in the buffer
582356345Scy * \param[in] buffer the buffer
583356345Scy * \param[in] data the 48 bits to write
584356345Scy */
585356345ScyINLINE void
586356345Scysldns_buffer_write_u48(sldns_buffer *buffer, uint64_t data)
587356345Scy{
588356345Scy	sldns_buffer_write_u48_at(buffer, buffer->_position, data);
589356345Scy	buffer->_position += 6;
590356345Scy}
591356345Scy
592356345Scy/**
593266077Sdes * copies count bytes of data at the given position to the given data-array
594266077Sdes * \param[in] buffer the buffer
595266077Sdes * \param[in] at the position in the buffer to start
596266077Sdes * \param[out] data buffer to copy to
597266077Sdes * \param[in] count the length of the data to copy
598266077Sdes */
599266077SdesINLINE void
600266077Sdessldns_buffer_read_at(sldns_buffer *buffer, size_t at, void *data, size_t count)
601266077Sdes{
602266077Sdes	assert(sldns_buffer_available_at(buffer, at, count));
603266077Sdes	memcpy(data, buffer->_data + at, count);
604266077Sdes}
605266077Sdes
606266077Sdes/**
607266077Sdes * copies count bytes of data at the current position to the given data-array
608266077Sdes * \param[in] buffer the buffer
609266077Sdes * \param[out] data buffer to copy to
610266077Sdes * \param[in] count the length of the data to copy
611266077Sdes */
612266077SdesINLINE void
613266077Sdessldns_buffer_read(sldns_buffer *buffer, void *data, size_t count)
614266077Sdes{
615266077Sdes	sldns_buffer_read_at(buffer, buffer->_position, data, count);
616266077Sdes	buffer->_position += count;
617266077Sdes}
618266077Sdes
619266077Sdes/**
620266077Sdes * returns the byte value at the given position in the buffer
621266077Sdes * \param[in] buffer the buffer
622266077Sdes * \param[in] at the position in the buffer
623266077Sdes * \return 1 byte integer
624266077Sdes */
625266077SdesINLINE uint8_t
626266077Sdessldns_buffer_read_u8_at(sldns_buffer *buffer, size_t at)
627266077Sdes{
628266077Sdes	assert(sldns_buffer_available_at(buffer, at, sizeof(uint8_t)));
629266077Sdes	return buffer->_data[at];
630266077Sdes}
631266077Sdes
632266077Sdes/**
633266077Sdes * returns the byte value at the current position in the buffer
634266077Sdes * \param[in] buffer the buffer
635266077Sdes * \return 1 byte integer
636266077Sdes */
637266077SdesINLINE uint8_t
638266077Sdessldns_buffer_read_u8(sldns_buffer *buffer)
639266077Sdes{
640266077Sdes	uint8_t result = sldns_buffer_read_u8_at(buffer, buffer->_position);
641266077Sdes	buffer->_position += sizeof(uint8_t);
642266077Sdes	return result;
643266077Sdes}
644266077Sdes
645266077Sdes/**
646266077Sdes * returns the 2-byte integer value at the given position in the buffer
647266077Sdes * \param[in] buffer the buffer
648266077Sdes * \param[in] at position in the buffer
649266077Sdes * \return 2 byte integer
650266077Sdes */
651266077SdesINLINE uint16_t
652266077Sdessldns_buffer_read_u16_at(sldns_buffer *buffer, size_t at)
653266077Sdes{
654266077Sdes	assert(sldns_buffer_available_at(buffer, at, sizeof(uint16_t)));
655266077Sdes	return sldns_read_uint16(buffer->_data + at);
656266077Sdes}
657266077Sdes
658266077Sdes/**
659266077Sdes * returns the 2-byte integer value at the current position in the buffer
660266077Sdes * \param[in] buffer the buffer
661266077Sdes * \return 2 byte integer
662266077Sdes */
663266077SdesINLINE uint16_t
664266077Sdessldns_buffer_read_u16(sldns_buffer *buffer)
665266077Sdes{
666266077Sdes	uint16_t result = sldns_buffer_read_u16_at(buffer, buffer->_position);
667266077Sdes	buffer->_position += sizeof(uint16_t);
668266077Sdes	return result;
669266077Sdes}
670266077Sdes
671266077Sdes/**
672266077Sdes * returns the 4-byte integer value at the given position in the buffer
673266077Sdes * \param[in] buffer the buffer
674266077Sdes * \param[in] at position in the buffer
675266077Sdes * \return 4 byte integer
676266077Sdes */
677266077SdesINLINE uint32_t
678266077Sdessldns_buffer_read_u32_at(sldns_buffer *buffer, size_t at)
679266077Sdes{
680266077Sdes	assert(sldns_buffer_available_at(buffer, at, sizeof(uint32_t)));
681266077Sdes	return sldns_read_uint32(buffer->_data + at);
682266077Sdes}
683266077Sdes
684266077Sdes/**
685266077Sdes * returns the 4-byte integer value at the current position in the buffer
686266077Sdes * \param[in] buffer the buffer
687266077Sdes * \return 4 byte integer
688266077Sdes */
689266077SdesINLINE uint32_t
690266077Sdessldns_buffer_read_u32(sldns_buffer *buffer)
691266077Sdes{
692266077Sdes	uint32_t result = sldns_buffer_read_u32_at(buffer, buffer->_position);
693266077Sdes	buffer->_position += sizeof(uint32_t);
694266077Sdes	return result;
695266077Sdes}
696266077Sdes
697266077Sdes/**
698266077Sdes * returns the status of the buffer
699266077Sdes * \param[in] buffer
700266077Sdes * \return the status
701266077Sdes */
702266077SdesINLINE int
703266077Sdessldns_buffer_status(sldns_buffer *buffer)
704266077Sdes{
705266077Sdes	return (int)buffer->_status_err;
706266077Sdes}
707266077Sdes
708266077Sdes/**
709266077Sdes * returns true if the status of the buffer is LDNS_STATUS_OK, false otherwise
710266077Sdes * \param[in] buffer the buffer
711266077Sdes * \return true or false
712266077Sdes */
713266077SdesINLINE int
714266077Sdessldns_buffer_status_ok(sldns_buffer *buffer)
715266077Sdes{
716266077Sdes	if (buffer) {
717266077Sdes		return sldns_buffer_status(buffer) == 0;
718266077Sdes	} else {
719266077Sdes		return 0;
720266077Sdes	}
721266077Sdes}
722266077Sdes
723266077Sdes/**
724266077Sdes * prints to the buffer, increasing the capacity if required using
725266077Sdes * buffer_reserve(). The buffer's position is set to the terminating '\\0'
726266077Sdes * Returns the number of characters written (not including the
727266077Sdes * terminating '\\0') or -1 on failure.
728266077Sdes */
729266077Sdesint sldns_buffer_printf(sldns_buffer *buffer, const char *format, ...)
730266077Sdes	ATTR_FORMAT(printf, 2, 3);
731266077Sdes
732266077Sdes/**
733266077Sdes * frees the buffer.
734266077Sdes * \param[in] *buffer the buffer to be freed
735266077Sdes * \return void
736266077Sdes */
737266077Sdesvoid sldns_buffer_free(sldns_buffer *buffer);
738266077Sdes
739266077Sdes/**
740266077Sdes * Copy contents of the from buffer to the result buffer and then flips
741266077Sdes * the result buffer. Data will be silently truncated if the result buffer is
742266077Sdes * too small.
743266077Sdes * \param[out] *result resulting buffer which is copied to.
744266077Sdes * \param[in] *from what to copy to result.
745266077Sdes */
746266077Sdesvoid sldns_buffer_copy(sldns_buffer* result, sldns_buffer* from);
747266077Sdes
748266077Sdes#ifdef __cplusplus
749266077Sdes}
750266077Sdes#endif
751266077Sdes
752266077Sdes#endif /* LDNS_SBUFFER_H */
753