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 <assert.h>
17 #include <stdarg.h>
18 #include <string.h>
19
20 #include <ldns/error.h>
21 #include <ldns/common.h>
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
ldns_buffer_invariant(const ldns_buffer * ATTR_UNUSED (buffer))77 ldns_buffer_invariant(const ldns_buffer *ATTR_UNUSED(buffer))
78 {
79 }
80 #else
81 INLINE void
ldns_buffer_invariant(const ldns_buffer * buffer)82 ldns_buffer_invariant(const 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, const 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 */
ldns_buffer_clear(ldns_buffer * buffer)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 */
ldns_buffer_flip(ldns_buffer * buffer)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 */
ldns_buffer_rewind(ldns_buffer * buffer)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
ldns_buffer_position(const ldns_buffer * buffer)159 ldns_buffer_position(const ldns_buffer *buffer)
160 {
161 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
ldns_buffer_set_position(ldns_buffer * buffer,size_t mark)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
ldns_buffer_skip(ldns_buffer * buffer,ssize_t count)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
ldns_buffer_limit(const ldns_buffer * buffer)197 ldns_buffer_limit(const 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
ldns_buffer_set_limit(ldns_buffer * buffer,size_t limit)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
ldns_buffer_capacity(const ldns_buffer * buffer)223 ldns_buffer_capacity(const 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 *
ldns_buffer_at(const ldns_buffer * buffer,size_t at)257 ldns_buffer_at(const ldns_buffer *buffer, size_t at)
258 {
259 assert(at <= buffer->_limit);
260 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 *
ldns_buffer_begin(const ldns_buffer * buffer)270 ldns_buffer_begin(const ldns_buffer *buffer)
271 {
272 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 *
ldns_buffer_end(const ldns_buffer * buffer)282 ldns_buffer_end(const 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 *
ldns_buffer_current(const ldns_buffer * buffer)293 ldns_buffer_current(const 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
ldns_buffer_remaining_at(const ldns_buffer * buffer,size_t at)306 ldns_buffer_remaining_at(const 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
ldns_buffer_remaining(const ldns_buffer * buffer)320 ldns_buffer_remaining(const 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
ldns_buffer_available_at(const ldns_buffer * buffer,size_t at,size_t count)335 ldns_buffer_available_at(const 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
ldns_buffer_available(const ldns_buffer * buffer,size_t count)347 ldns_buffer_available(const 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
ldns_buffer_write_at(ldns_buffer * buffer,size_t at,const void * data,size_t count)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 length of the data to write
371 */
372 INLINE void
ldns_buffer_write(ldns_buffer * buffer,const void * data,size_t count)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
ldns_buffer_write_string_at(ldns_buffer * buffer,size_t at,const char * str)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
ldns_buffer_write_string(ldns_buffer * buffer,const char * str)397 ldns_buffer_write_string(ldns_buffer *buffer, const char *str)
398 {
399 ldns_buffer_write(buffer, str, strlen(str));
400 }
401
402 /**
403 * copies the given (null-delimited) string to the current position at the buffer
404 * increasing the capacity if necessary
405 * \param[in] buffer the buffer
406 * \param[in] str the string to write
407 */
408 INLINE void
ldns_buffer_write_chars(ldns_buffer * buffer,const char * str)409 ldns_buffer_write_chars(ldns_buffer *buffer, const char *str)
410 {
411 if (!ldns_buffer_reserve(buffer, strlen(str)))
412 buffer->_status = LDNS_STATUS_MEM_ERR;
413 else
414 ldns_buffer_write_string(buffer, str);
415 }
416
417
418 /**
419 * writes the given byte of data at the given position in the buffer
420 * \param[in] buffer the buffer
421 * \param[in] at the position in the buffer
422 * \param[in] data the 8 bits to write
423 */
424 INLINE void
ldns_buffer_write_u8_at(ldns_buffer * buffer,size_t at,uint8_t data)425 ldns_buffer_write_u8_at(ldns_buffer *buffer, size_t at, uint8_t data)
426 {
427 assert(ldns_buffer_available_at(buffer, at, sizeof(data)));
428 buffer->_data[at] = data;
429 }
430
431 /**
432 * writes the given byte of data at the current position in the buffer
433 * \param[in] buffer the buffer
434 * \param[in] data the 8 bits to write
435 */
436 INLINE void
ldns_buffer_write_u8(ldns_buffer * buffer,uint8_t data)437 ldns_buffer_write_u8(ldns_buffer *buffer, uint8_t data)
438 {
439 ldns_buffer_write_u8_at(buffer, buffer->_position, data);
440 buffer->_position += sizeof(data);
441 }
442
443 /**
444 * writes the given byte of data at the current position in the buffer
445 * increasing the capacity if necessary
446 * \param[in] buffer the buffer
447 * \param[in] data the 8 bits to write
448 */
449 INLINE void
ldns_buffer_write_char(ldns_buffer * buffer,uint8_t data)450 ldns_buffer_write_char(ldns_buffer *buffer, uint8_t data)
451 {
452 if (!ldns_buffer_reserve(buffer, sizeof(data)))
453 buffer->_status = LDNS_STATUS_MEM_ERR;
454 else
455 ldns_buffer_write_u8(buffer, data);
456 }
457
458 /**
459 * writes the given 2 byte integer at the given position in the buffer
460 * \param[in] buffer the buffer
461 * \param[in] at the position in the buffer
462 * \param[in] data the 16 bits to write
463 */
464 INLINE void
ldns_buffer_write_u16_at(ldns_buffer * buffer,size_t at,uint16_t data)465 ldns_buffer_write_u16_at(ldns_buffer *buffer, size_t at, uint16_t data)
466 {
467 assert(ldns_buffer_available_at(buffer, at, sizeof(data)));
468 ldns_write_uint16(buffer->_data + at, data);
469 }
470
471 /**
472 * writes the given 2 byte integer at the current position in the buffer
473 * \param[in] buffer the buffer
474 * \param[in] data the 16 bits to write
475 */
476 INLINE void
ldns_buffer_write_u16(ldns_buffer * buffer,uint16_t data)477 ldns_buffer_write_u16(ldns_buffer *buffer, uint16_t data)
478 {
479 ldns_buffer_write_u16_at(buffer, buffer->_position, data);
480 buffer->_position += sizeof(data);
481 }
482
483 /**
484 * writes the given 4 byte integer at the given position in the buffer
485 * \param[in] buffer the buffer
486 * \param[in] at the position in the buffer
487 * \param[in] data the 32 bits to write
488 */
489 INLINE void
ldns_buffer_write_u32_at(ldns_buffer * buffer,size_t at,uint32_t data)490 ldns_buffer_write_u32_at(ldns_buffer *buffer, size_t at, uint32_t data)
491 {
492 assert(ldns_buffer_available_at(buffer, at, sizeof(data)));
493 ldns_write_uint32(buffer->_data + at, data);
494 }
495
496 /**
497 * writes the given 4 byte integer at the current position in the buffer
498 * \param[in] buffer the buffer
499 * \param[in] data the 32 bits to write
500 */
501 INLINE void
ldns_buffer_write_u32(ldns_buffer * buffer,uint32_t data)502 ldns_buffer_write_u32(ldns_buffer *buffer, uint32_t data)
503 {
504 ldns_buffer_write_u32_at(buffer, buffer->_position, data);
505 buffer->_position += sizeof(data);
506 }
507
508 /**
509 * copies count bytes of data at the given position to the given data-array
510 * \param[in] buffer the buffer
511 * \param[in] at the position in the buffer to start
512 * \param[out] data buffer to copy to
513 * \param[in] count the length of the data to copy
514 */
515 INLINE void
ldns_buffer_read_at(const ldns_buffer * buffer,size_t at,void * data,size_t count)516 ldns_buffer_read_at(const ldns_buffer *buffer, size_t at, void *data, size_t count)
517 {
518 assert(ldns_buffer_available_at(buffer, at, count));
519 memcpy(data, buffer->_data + at, count);
520 }
521
522 /**
523 * copies count bytes of data at the current position to the given data-array
524 * \param[in] buffer the buffer
525 * \param[out] data buffer to copy to
526 * \param[in] count the length of the data to copy
527 */
528 INLINE void
ldns_buffer_read(ldns_buffer * buffer,void * data,size_t count)529 ldns_buffer_read(ldns_buffer *buffer, void *data, size_t count)
530 {
531 ldns_buffer_read_at(buffer, buffer->_position, data, count);
532 buffer->_position += count;
533 }
534
535 /**
536 * returns the byte value at the given position in the buffer
537 * \param[in] buffer the buffer
538 * \param[in] at the position in the buffer
539 * \return 1 byte integer
540 */
541 INLINE uint8_t
ldns_buffer_read_u8_at(const ldns_buffer * buffer,size_t at)542 ldns_buffer_read_u8_at(const ldns_buffer *buffer, size_t at)
543 {
544 assert(ldns_buffer_available_at(buffer, at, sizeof(uint8_t)));
545 return buffer->_data[at];
546 }
547
548 /**
549 * returns the byte value at the current position in the buffer
550 * \param[in] buffer the buffer
551 * \return 1 byte integer
552 */
553 INLINE uint8_t
ldns_buffer_read_u8(ldns_buffer * buffer)554 ldns_buffer_read_u8(ldns_buffer *buffer)
555 {
556 uint8_t result = ldns_buffer_read_u8_at(buffer, buffer->_position);
557 buffer->_position += sizeof(uint8_t);
558 return result;
559 }
560
561 /**
562 * returns the 2-byte integer value at the given position in the buffer
563 * \param[in] buffer the buffer
564 * \param[in] at position in the buffer
565 * \return 2 byte integer
566 */
567 INLINE uint16_t
ldns_buffer_read_u16_at(ldns_buffer * buffer,size_t at)568 ldns_buffer_read_u16_at(ldns_buffer *buffer, size_t at)
569 {
570 assert(ldns_buffer_available_at(buffer, at, sizeof(uint16_t)));
571 return ldns_read_uint16(buffer->_data + at);
572 }
573
574 /**
575 * returns the 2-byte integer value at the current position in the buffer
576 * \param[in] buffer the buffer
577 * \return 2 byte integer
578 */
579 INLINE uint16_t
ldns_buffer_read_u16(ldns_buffer * buffer)580 ldns_buffer_read_u16(ldns_buffer *buffer)
581 {
582 uint16_t result = ldns_buffer_read_u16_at(buffer, buffer->_position);
583 buffer->_position += sizeof(uint16_t);
584 return result;
585 }
586
587 /**
588 * returns the 4-byte integer value at the given position in the buffer
589 * \param[in] buffer the buffer
590 * \param[in] at position in the buffer
591 * \return 4 byte integer
592 */
593 INLINE uint32_t
ldns_buffer_read_u32_at(ldns_buffer * buffer,size_t at)594 ldns_buffer_read_u32_at(ldns_buffer *buffer, size_t at)
595 {
596 assert(ldns_buffer_available_at(buffer, at, sizeof(uint32_t)));
597 return ldns_read_uint32(buffer->_data + at);
598 }
599
600 /**
601 * returns the 4-byte integer value at the current position in the buffer
602 * \param[in] buffer the buffer
603 * \return 4 byte integer
604 */
605 INLINE uint32_t
ldns_buffer_read_u32(ldns_buffer * buffer)606 ldns_buffer_read_u32(ldns_buffer *buffer)
607 {
608 uint32_t result = ldns_buffer_read_u32_at(buffer, buffer->_position);
609 buffer->_position += sizeof(uint32_t);
610 return result;
611 }
612
613 /**
614 * returns the status of the buffer
615 * \param[in] buffer
616 * \return the status
617 */
618 INLINE ldns_status
ldns_buffer_status(const ldns_buffer * buffer)619 ldns_buffer_status(const ldns_buffer *buffer)
620 {
621 return buffer->_status;
622 }
623
624 /**
625 * returns true if the status of the buffer is LDNS_STATUS_OK, false otherwise
626 * \param[in] buffer the buffer
627 * \return true or false
628 */
629 INLINE bool
ldns_buffer_status_ok(const ldns_buffer * buffer)630 ldns_buffer_status_ok(const ldns_buffer *buffer)
631 {
632 if (buffer) {
633 return ldns_buffer_status(buffer) == LDNS_STATUS_OK;
634 } else {
635 return false;
636 }
637 }
638
639 /**
640 * prints to the buffer, increasing the capacity if required using
641 * buffer_reserve(). The buffer's position is set to the terminating '\\0'
642 * Returns the number of characters written (not including the
643 * terminating '\\0') or -1 on failure.
644 */
645 int ldns_buffer_printf(ldns_buffer *buffer, const char *format, ...);
646 /* ATTR_FORMAT(printf, 2, 3);*/
647
648 /**
649 * frees the buffer.
650 * \param[in] *buffer the buffer to be freed
651 * \return void
652 */
653 void ldns_buffer_free(ldns_buffer *buffer);
654
655 /**
656 * Makes the buffer fixed and returns a pointer to the data. The
657 * caller is responsible for free'ing the result.
658 * \param[in] *buffer the buffer to be exported
659 * \return void
660 */
661 void *ldns_buffer_export(ldns_buffer *buffer);
662
663 /**
664 * Copy contents of the from buffer to the result buffer and then flips
665 * the result buffer. Data will be silently truncated if the result buffer is
666 * too small.
667 * \param[out] *result resulting buffer which is copied to.
668 * \param[in] *from what to copy to result.
669 */
670 void ldns_buffer_copy(ldns_buffer* result, const ldns_buffer* from);
671
672 #ifdef __cplusplus
673 }
674 #endif
675
676 #endif /* LDNS_BUFFER_H */
677