buffer.h
Go to the documentation of this file.
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 
33 #define LDNS_MIN_BUFLEN 512
34 
51 {
53  size_t _position;
54 
56  size_t _limit;
57 
59  size_t _capacity;
60 
62  uint8_t *_data;
63 
65  unsigned _fixed : 1;
66 
71 };
73 
74 
75 #ifdef NDEBUG
76 INLINE void
77 ldns_buffer_invariant(const ldns_buffer *ATTR_UNUSED(buffer))
78 {
79 }
80 #else
81 INLINE void
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 
97 ldns_buffer *ldns_buffer_new(size_t capacity);
98 
108 void ldns_buffer_new_frm_data(ldns_buffer *buffer, const void *data, size_t size);
109 
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 
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 
146 INLINE void ldns_buffer_rewind(ldns_buffer *buffer)
147 {
148  ldns_buffer_invariant(buffer);
149 
150  buffer->_position = 0;
151 }
152 
158 INLINE size_t
159 ldns_buffer_position(const ldns_buffer *buffer)
160 {
161  return buffer->_position;
162 }
163 
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 
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 
196 INLINE size_t
197 ldns_buffer_limit(const ldns_buffer *buffer)
198 {
199  return buffer->_limit;
200 }
201 
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 
222 INLINE size_t
223 ldns_buffer_capacity(const ldns_buffer *buffer)
224 {
225  return buffer->_capacity;
226 }
227 
236 bool ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity);
237 
248 bool ldns_buffer_reserve(ldns_buffer *buffer, size_t amount);
249 
256 INLINE uint8_t *
257 ldns_buffer_at(const ldns_buffer *buffer, size_t at)
258 {
259  assert(at <= buffer->_limit);
260  return buffer->_data + at;
261 }
262 
269 INLINE uint8_t *
270 ldns_buffer_begin(const ldns_buffer *buffer)
271 {
272  return ldns_buffer_at(buffer, 0);
273 }
274 
281 INLINE uint8_t *
282 ldns_buffer_end(const ldns_buffer *buffer)
283 {
284  return ldns_buffer_at(buffer, buffer->_limit);
285 }
286 
292 INLINE uint8_t *
293 ldns_buffer_current(const ldns_buffer *buffer)
294 {
295  return ldns_buffer_at(buffer, buffer->_position);
296 }
297 
305 INLINE size_t
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 
319 INLINE size_t
320 ldns_buffer_remaining(const ldns_buffer *buffer)
321 {
322  return ldns_buffer_remaining_at(buffer, buffer->_position);
323 }
324 
334 INLINE int
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 
346 INLINE int
347 ldns_buffer_available(const ldns_buffer *buffer, size_t count)
348 {
349  return ldns_buffer_available_at(buffer, buffer->_position, count);
350 }
351 
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 
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 
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 
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 
408 INLINE void
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 
424 INLINE void
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 
436 INLINE void
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 
449 INLINE void
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 
464 INLINE void
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 
476 INLINE void
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 
489 INLINE void
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 
501 INLINE void
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 
515 INLINE void
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 
528 INLINE void
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 
541 INLINE uint8_t
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 
553 INLINE uint8_t
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 
567 INLINE uint16_t
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 
579 INLINE uint16_t
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 
593 INLINE uint32_t
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 
605 INLINE uint32_t
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 
619 ldns_buffer_status(const ldns_buffer *buffer)
620 {
621  return buffer->_status;
622 }
623 
629 INLINE bool
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 
645 int ldns_buffer_printf(ldns_buffer *buffer, const char *format, ...);
646 /* ATTR_FORMAT(printf, 2, 3);*/
647 
653 void ldns_buffer_free(ldns_buffer *buffer);
654 
661 void *ldns_buffer_export(ldns_buffer *buffer);
662 
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 */
ldns_buffer * ldns_buffer_new(size_t capacity)
creates a new buffer with the specified capacity.
Definition: buffer.c:16
size_t _position
The current position used for reading/writing.
Definition: buffer.h:53
implementation of buffers to ease operations
Definition: buffer.h:50
bool ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity)
changes the buffer's capacity.
Definition: buffer.c:60
size_t _capacity
The amount of data the buffer can contain.
Definition: buffer.h:59
unsigned _fixed
If the buffer is fixed it cannot be resized.
Definition: buffer.h:65
@ LDNS_STATUS_OK
Definition: error.h:26
bool ldns_buffer_reserve(ldns_buffer *buffer, size_t amount)
ensures BUFFER can contain at least AMOUNT more bytes.
Definition: buffer.c:80
void ldns_buffer_copy(ldns_buffer *result, const ldns_buffer *from)
Copy contents of the from buffer to the result buffer and then flips the result buffer.
Definition: buffer.c:168
ldns_status _status
The current state of the buffer.
Definition: buffer.h:70
void ldns_buffer_free(ldns_buffer *buffer)
frees the buffer.
Definition: buffer.c:137
enum ldns_enum_status ldns_status
Definition: error.h:146
#define ATTR_UNUSED(x)
Definition: common.h:72
#define INLINE
splint static inline workaround
Definition: util.h:42
void * ldns_buffer_export(ldns_buffer *buffer)
Makes the buffer fixed and returns a pointer to the data.
Definition: buffer.c:150
size_t _limit
The read/write limit.
Definition: buffer.h:56
int ldns_buffer_printf(ldns_buffer *buffer, const char *format,...)
prints to the buffer, increasing the capacity if required using buffer_reserve().
Definition: buffer.c:99
uint8_t * _data
The data contained in the buffer.
Definition: buffer.h:62
@ LDNS_STATUS_MEM_ERR
Definition: error.h:34
void ldns_buffer_new_frm_data(ldns_buffer *buffer, const void *data, size_t size)
creates a buffer with the specified data.
Definition: buffer.c:41