File Coverage

include/ldns/buffer.h
Criterion Covered Total %
statement 0 6 0.0
branch n/a
condition n/a
subroutine n/a
pod n/a
total 0 6 0.0


line stmt bran cond sub pod time code
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_BUFFER_H
14             #define LDNS_BUFFER_H
15              
16             #include
17             #include
18             #include
19              
20             #include
21             #include
22              
23             #include "ldns/util.h"
24              
25             #ifdef __cplusplus
26             extern "C" {
27             #endif
28              
29             /**
30             * number of initial bytes in buffer of
31             * which we cannot tell the size before hand
32             */
33             #define LDNS_MIN_BUFLEN 512
34              
35             /**
36             * \file buffer.h
37             *
38             * This file contains the definition of ldns_buffer, and functions to manipulate those.
39             */
40              
41             /**
42             * implementation of buffers to ease operations
43             *
44             * ldns_buffers can contain arbitrary information, per octet. You can write
45             * to the current end of a buffer, read from the current position, and
46             * access any data within it.
47             *
48             * Example use of buffers is in the source code of \ref host2str.c
49             */
50             struct ldns_struct_buffer
51             {
52             /** The current position used for reading/writing */
53             size_t _position;
54              
55             /** The read/write limit */
56             size_t _limit;
57              
58             /** The amount of data the buffer can contain */
59             size_t _capacity;
60              
61             /** The data contained in the buffer */
62             uint8_t *_data;
63              
64             /** If the buffer is fixed it cannot be resized */
65             unsigned _fixed : 1;
66              
67             /** The current state of the buffer. If writing to the buffer fails
68             * for any reason, this value is changed. This way, you can perform
69             * multiple writes in sequence and check for success afterwards. */
70             ldns_status _status;
71             };
72             typedef struct ldns_struct_buffer ldns_buffer;
73              
74              
75             #ifdef NDEBUG
76             INLINE void
77             ldns_buffer_invariant(ldns_buffer *ATTR_UNUSED(buffer))
78             {
79             }
80             #else
81             INLINE void
82             ldns_buffer_invariant(ldns_buffer *buffer)
83             {
84             assert(buffer != NULL);
85             assert(buffer->_position <= buffer->_limit);
86             assert(buffer->_limit <= buffer->_capacity);
87             assert(buffer->_data != NULL);
88             }
89             #endif
90              
91             /**
92             * creates a new buffer with the specified capacity.
93             *
94             * \param[in] capacity the size (in bytes) to allocate for the buffer
95             * \return the created buffer
96             */
97             ldns_buffer *ldns_buffer_new(size_t capacity);
98              
99             /**
100             * creates a buffer with the specified data. The data IS copied
101             * and MEMORY allocations are done. The buffer is not fixed and can
102             * be resized using buffer_reserve().
103             *
104             * \param[in] buffer pointer to the buffer to put the data in
105             * \param[in] data the data to encapsulate in the buffer
106             * \param[in] size the size of the data
107             */
108             void ldns_buffer_new_frm_data(ldns_buffer *buffer, void *data, size_t size);
109              
110             /**
111             * clears the buffer and make it ready for writing. The buffer's limit
112             * is set to the capacity and the position is set to 0.
113             * \param[in] buffer the buffer to clear
114             */
115             INLINE void ldns_buffer_clear(ldns_buffer *buffer)
116             {
117             ldns_buffer_invariant(buffer);
118              
119             /* reset status here? */
120              
121             buffer->_position = 0;
122             buffer->_limit = buffer->_capacity;
123             }
124              
125             /**
126             * makes the buffer ready for reading the data that has been written to
127             * the buffer. The buffer's limit is set to the current position and
128             * the position is set to 0.
129             *
130             * \param[in] buffer the buffer to flip
131             * \return void
132             */
133             INLINE void ldns_buffer_flip(ldns_buffer *buffer)
134             {
135             ldns_buffer_invariant(buffer);
136              
137             buffer->_limit = buffer->_position;
138             buffer->_position = 0;
139             }
140              
141             /**
142             * make the buffer ready for re-reading the data. The buffer's
143             * position is reset to 0.
144             * \param[in] buffer the buffer to rewind
145             */
146             INLINE void ldns_buffer_rewind(ldns_buffer *buffer)
147             {
148             ldns_buffer_invariant(buffer);
149              
150             buffer->_position = 0;
151             }
152              
153             /**
154             * returns the current position in the buffer (as a number of bytes)
155             * \param[in] buffer the buffer
156             * \return the current position
157             */
158             INLINE size_t
159 0           ldns_buffer_position(ldns_buffer *buffer)
160             {
161 0           return buffer->_position;
162             }
163              
164             /**
165             * sets the buffer's position to MARK. The position must be less than
166             * or equal to the buffer's limit.
167             * \param[in] buffer the buffer
168             * \param[in] mark the mark to use
169             */
170             INLINE void
171             ldns_buffer_set_position(ldns_buffer *buffer, size_t mark)
172             {
173             assert(mark <= buffer->_limit);
174             buffer->_position = mark;
175             }
176              
177             /**
178             * changes the buffer's position by COUNT bytes. The position must not
179             * be moved behind the buffer's limit or before the beginning of the
180             * buffer.
181             * \param[in] buffer the buffer
182             * \param[in] count the count to use
183             */
184             INLINE void
185             ldns_buffer_skip(ldns_buffer *buffer, ssize_t count)
186             {
187             assert(buffer->_position + count <= buffer->_limit);
188             buffer->_position += count;
189             }
190              
191             /**
192             * returns the maximum size of the buffer
193             * \param[in] buffer
194             * \return the size
195             */
196             INLINE size_t
197             ldns_buffer_limit(ldns_buffer *buffer)
198             {
199             return buffer->_limit;
200             }
201              
202             /**
203             * changes the buffer's limit. If the buffer's position is greater
204             * than the new limit the position is set to the limit.
205             * \param[in] buffer the buffer
206             * \param[in] limit the new limit
207             */
208             INLINE void
209             ldns_buffer_set_limit(ldns_buffer *buffer, size_t limit)
210             {
211             assert(limit <= buffer->_capacity);
212             buffer->_limit = limit;
213             if (buffer->_position > buffer->_limit)
214             buffer->_position = buffer->_limit;
215             }
216              
217             /**
218             * returns the number of bytes the buffer can hold.
219             * \param[in] buffer the buffer
220             * \return the number of bytes
221             */
222             INLINE size_t
223             ldns_buffer_capacity(ldns_buffer *buffer)
224             {
225             return buffer->_capacity;
226             }
227              
228             /**
229             * changes the buffer's capacity. The data is reallocated so any
230             * pointers to the data may become invalid. The buffer's limit is set
231             * to the buffer's new capacity.
232             * \param[in] buffer the buffer
233             * \param[in] capacity the capacity to use
234             * \return whether this failed or succeeded
235             */
236             bool ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity);
237              
238             /**
239             * ensures BUFFER can contain at least AMOUNT more bytes. The buffer's
240             * capacity is increased if necessary using buffer_set_capacity().
241             *
242             * The buffer's limit is always set to the (possibly increased)
243             * capacity.
244             * \param[in] buffer the buffer
245             * \param[in] amount amount to use
246             * \return whether this failed or succeeded
247             */
248             bool ldns_buffer_reserve(ldns_buffer *buffer, size_t amount);
249              
250             /**
251             * returns a pointer to the data at the indicated position.
252             * \param[in] buffer the buffer
253             * \param[in] at position
254             * \return the pointer to the data
255             */
256             INLINE uint8_t *
257 0           ldns_buffer_at(const ldns_buffer *buffer, size_t at)
258             {
259             assert(at <= buffer->_limit);
260 0           return buffer->_data + at;
261             }
262              
263             /**
264             * returns a pointer to the beginning of the buffer (the data at
265             * position 0).
266             * \param[in] buffer the buffer
267             * \return the pointer
268             */
269             INLINE uint8_t *
270 0           ldns_buffer_begin(const ldns_buffer *buffer)
271             {
272 0           return ldns_buffer_at(buffer, 0);
273             }
274              
275             /**
276             * returns a pointer to the end of the buffer (the data at the buffer's
277             * limit).
278             * \param[in] buffer the buffer
279             * \return the pointer
280             */
281             INLINE uint8_t *
282             ldns_buffer_end(ldns_buffer *buffer)
283             {
284             return ldns_buffer_at(buffer, buffer->_limit);
285             }
286              
287             /**
288             * returns a pointer to the data at the buffer's current position.
289             * \param[in] buffer the buffer
290             * \return the pointer
291             */
292             INLINE uint8_t *
293             ldns_buffer_current(ldns_buffer *buffer)
294             {
295             return ldns_buffer_at(buffer, buffer->_position);
296             }
297              
298             /**
299             * returns the number of bytes remaining between the indicated position and
300             * the limit.
301             * \param[in] buffer the buffer
302             * \param[in] at indicated position
303             * \return number of bytes
304             */
305             INLINE size_t
306             ldns_buffer_remaining_at(ldns_buffer *buffer, size_t at)
307             {
308             ldns_buffer_invariant(buffer);
309             assert(at <= buffer->_limit);
310             return buffer->_limit - at;
311             }
312              
313             /**
314             * returns the number of bytes remaining between the buffer's position and
315             * limit.
316             * \param[in] buffer the buffer
317             * \return the number of bytes
318             */
319             INLINE size_t
320             ldns_buffer_remaining(ldns_buffer *buffer)
321             {
322             return ldns_buffer_remaining_at(buffer, buffer->_position);
323             }
324              
325             /**
326             * checks if the buffer has at least COUNT more bytes available.
327             * Before reading or writing the caller needs to ensure enough space
328             * is available!
329             * \param[in] buffer the buffer
330             * \param[in] at indicated position
331             * \param[in] count how much is available
332             * \return true or false (as int?)
333             */
334             INLINE int
335             ldns_buffer_available_at(ldns_buffer *buffer, size_t at, size_t count)
336             {
337             return count <= ldns_buffer_remaining_at(buffer, at);
338             }
339              
340             /**
341             * checks if the buffer has count bytes available at the current position
342             * \param[in] buffer the buffer
343             * \param[in] count how much is available
344             * \return true or false (as int?)
345             */
346             INLINE int
347             ldns_buffer_available(ldns_buffer *buffer, size_t count)
348             {
349             return ldns_buffer_available_at(buffer, buffer->_position, count);
350             }
351              
352             /**
353             * writes the given data to the buffer at the specified position
354             * \param[in] buffer the buffer
355             * \param[in] at the position (in number of bytes) to write the data at
356             * \param[in] data pointer to the data to write to the buffer
357             * \param[in] count the number of bytes of data to write
358             */
359             INLINE void
360             ldns_buffer_write_at(ldns_buffer *buffer, size_t at, const void *data, size_t count)
361             {
362             assert(ldns_buffer_available_at(buffer, at, count));
363             memcpy(buffer->_data + at, data, count);
364             }
365              
366             /**
367             * writes count bytes of data to the current position of the buffer
368             * \param[in] buffer the buffer
369             * \param[in] data the data to write
370             * \param[in] count the lenght of the data to write
371             */
372             INLINE void
373             ldns_buffer_write(ldns_buffer *buffer, const void *data, size_t count)
374             {
375             ldns_buffer_write_at(buffer, buffer->_position, data, count);
376             buffer->_position += count;
377             }
378              
379             /**
380             * copies the given (null-delimited) string to the specified position at the buffer
381             * \param[in] buffer the buffer
382             * \param[in] at the position in the buffer
383             * \param[in] str the string to write
384             */
385             INLINE void
386             ldns_buffer_write_string_at(ldns_buffer *buffer, size_t at, const char *str)
387             {
388             ldns_buffer_write_at(buffer, at, str, strlen(str));
389             }
390              
391             /**
392             * copies the given (null-delimited) string to the current position at the buffer
393             * \param[in] buffer the buffer
394             * \param[in] str the string to write
395             */
396             INLINE void
397             ldns_buffer_write_string(ldns_buffer *buffer, const char *str)
398             {
399             ldns_buffer_write(buffer, str, strlen(str));
400             }
401              
402             /**
403             * writes the given byte of data at the given position in the buffer
404             * \param[in] buffer the buffer
405             * \param[in] at the position in the buffer
406             * \param[in] data the 8 bits to write
407             */
408             INLINE void
409             ldns_buffer_write_u8_at(ldns_buffer *buffer, size_t at, uint8_t data)
410             {
411             assert(ldns_buffer_available_at(buffer, at, sizeof(data)));
412             buffer->_data[at] = data;
413             }
414              
415             /**
416             * writes the given byte of data at the current position in the buffer
417             * \param[in] buffer the buffer
418             * \param[in] data the 8 bits to write
419             */
420             INLINE void
421             ldns_buffer_write_u8(ldns_buffer *buffer, uint8_t data)
422             {
423             ldns_buffer_write_u8_at(buffer, buffer->_position, data);
424             buffer->_position += sizeof(data);
425             }
426              
427             /**
428             * writes the given 2 byte integer at the given position in the buffer
429             * \param[in] buffer the buffer
430             * \param[in] at the position in the buffer
431             * \param[in] data the 16 bits to write
432             */
433             INLINE void
434             ldns_buffer_write_u16_at(ldns_buffer *buffer, size_t at, uint16_t data)
435             {
436             assert(ldns_buffer_available_at(buffer, at, sizeof(data)));
437             ldns_write_uint16(buffer->_data + at, data);
438             }
439              
440             /**
441             * writes the given 2 byte integer at the current position in the buffer
442             * \param[in] buffer the buffer
443             * \param[in] data the 16 bits to write
444             */
445             INLINE void
446             ldns_buffer_write_u16(ldns_buffer *buffer, uint16_t data)
447             {
448             ldns_buffer_write_u16_at(buffer, buffer->_position, data);
449             buffer->_position += sizeof(data);
450             }
451              
452             /**
453             * writes the given 4 byte integer at the given position in the buffer
454             * \param[in] buffer the buffer
455             * \param[in] at the position in the buffer
456             * \param[in] data the 32 bits to write
457             */
458             INLINE void
459             ldns_buffer_write_u32_at(ldns_buffer *buffer, size_t at, uint32_t data)
460             {
461             assert(ldns_buffer_available_at(buffer, at, sizeof(data)));
462             ldns_write_uint32(buffer->_data + at, data);
463             }
464              
465             /**
466             * writes the given 4 byte integer at the current position in the buffer
467             * \param[in] buffer the buffer
468             * \param[in] data the 32 bits to write
469             */
470             INLINE void
471             ldns_buffer_write_u32(ldns_buffer *buffer, uint32_t data)
472             {
473             ldns_buffer_write_u32_at(buffer, buffer->_position, data);
474             buffer->_position += sizeof(data);
475             }
476              
477             /**
478             * copies count bytes of data at the given position to the given data-array
479             * \param[in] buffer the buffer
480             * \param[in] at the position in the buffer to start
481             * \param[out] data buffer to copy to
482             * \param[in] count the length of the data to copy
483             */
484             INLINE void
485             ldns_buffer_read_at(ldns_buffer *buffer, size_t at, void *data, size_t count)
486             {
487             assert(ldns_buffer_available_at(buffer, at, count));
488             memcpy(data, buffer->_data + at, count);
489             }
490              
491             /**
492             * copies count bytes of data at the current position to the given data-array
493             * \param[in] buffer the buffer
494             * \param[out] data buffer to copy to
495             * \param[in] count the length of the data to copy
496             */
497             INLINE void
498             ldns_buffer_read(ldns_buffer *buffer, void *data, size_t count)
499             {
500             ldns_buffer_read_at(buffer, buffer->_position, data, count);
501             buffer->_position += count;
502             }
503              
504             /**
505             * returns the byte value at the given position in the buffer
506             * \param[in] buffer the buffer
507             * \param[in] at the position in the buffer
508             * \return 1 byte integer
509             */
510             INLINE uint8_t
511             ldns_buffer_read_u8_at(ldns_buffer *buffer, size_t at)
512             {
513             assert(ldns_buffer_available_at(buffer, at, sizeof(uint8_t)));
514             return buffer->_data[at];
515             }
516              
517             /**
518             * returns the byte value at the current position in the buffer
519             * \param[in] buffer the buffer
520             * \return 1 byte integer
521             */
522             INLINE uint8_t
523             ldns_buffer_read_u8(ldns_buffer *buffer)
524             {
525             uint8_t result = ldns_buffer_read_u8_at(buffer, buffer->_position);
526             buffer->_position += sizeof(uint8_t);
527             return result;
528             }
529              
530             /**
531             * returns the 2-byte integer value at the given position in the buffer
532             * \param[in] buffer the buffer
533             * \param[in] at position in the buffer
534             * \return 2 byte integer
535             */
536             INLINE uint16_t
537             ldns_buffer_read_u16_at(ldns_buffer *buffer, size_t at)
538             {
539             assert(ldns_buffer_available_at(buffer, at, sizeof(uint16_t)));
540             return ldns_read_uint16(buffer->_data + at);
541             }
542              
543             /**
544             * returns the 2-byte integer value at the current position in the buffer
545             * \param[in] buffer the buffer
546             * \return 2 byte integer
547             */
548             INLINE uint16_t
549             ldns_buffer_read_u16(ldns_buffer *buffer)
550             {
551             uint16_t result = ldns_buffer_read_u16_at(buffer, buffer->_position);
552             buffer->_position += sizeof(uint16_t);
553             return result;
554             }
555              
556             /**
557             * returns the 4-byte integer value at the given position in the buffer
558             * \param[in] buffer the buffer
559             * \param[in] at position in the buffer
560             * \return 4 byte integer
561             */
562             INLINE uint32_t
563             ldns_buffer_read_u32_at(ldns_buffer *buffer, size_t at)
564             {
565             assert(ldns_buffer_available_at(buffer, at, sizeof(uint32_t)));
566             return ldns_read_uint32(buffer->_data + at);
567             }
568              
569             /**
570             * returns the 4-byte integer value at the current position in the buffer
571             * \param[in] buffer the buffer
572             * \return 4 byte integer
573             */
574             INLINE uint32_t
575             ldns_buffer_read_u32(ldns_buffer *buffer)
576             {
577             uint32_t result = ldns_buffer_read_u32_at(buffer, buffer->_position);
578             buffer->_position += sizeof(uint32_t);
579             return result;
580             }
581              
582             /**
583             * returns the status of the buffer
584             * \param[in] buffer
585             * \return the status
586             */
587             INLINE ldns_status
588             ldns_buffer_status(ldns_buffer *buffer)
589             {
590             return buffer->_status;
591             }
592              
593             /**
594             * returns true if the status of the buffer is LDNS_STATUS_OK, false otherwise
595             * \param[in] buffer the buffer
596             * \return true or false
597             */
598             INLINE bool
599             ldns_buffer_status_ok(ldns_buffer *buffer)
600             {
601             if (buffer) {
602             return ldns_buffer_status(buffer) == LDNS_STATUS_OK;
603             } else {
604             return false;
605             }
606             }
607              
608             /**
609             * prints to the buffer, increasing the capacity if required using
610             * buffer_reserve(). The buffer's position is set to the terminating '\\0'
611             * Returns the number of characters written (not including the
612             * terminating '\\0') or -1 on failure.
613             */
614             int ldns_buffer_printf(ldns_buffer *buffer, const char *format, ...);
615             /* ATTR_FORMAT(printf, 2, 3);*/
616              
617             /**
618             * frees the buffer.
619             * \param[in] *buffer the buffer to be freed
620             * \return void
621             */
622             void ldns_buffer_free(ldns_buffer *buffer);
623              
624             /**
625             * Makes the buffer fixed and returns a pointer to the data. The
626             * caller is responsible for free'ing the result.
627             * \param[in] *buffer the buffer to be exported
628             * \return void
629             */
630             void *ldns_buffer_export(ldns_buffer *buffer);
631              
632             /**
633             * Copy contents of the from buffer to the result buffer and then flips
634             * the result buffer. Data will be silently truncated if the result buffer is
635             * too small.
636             * \param[out] *result resulting buffer which is copied to.
637             * \param[in] *from what to copy to result.
638             */
639             void ldns_buffer_copy(ldns_buffer* result, ldns_buffer* from);
640              
641             #ifdef __cplusplus
642             }
643             #endif
644              
645             #endif /* LDNS_BUFFER_H */