buffer.c
Go to the documentation of this file.
1 /*
2  * buffer.c -- generic memory buffer .
3  *
4  * Copyright (c) 2001-2008, NLnet Labs. All rights reserved.
5  *
6  * See LICENSE for the license.
7  *
8  */
9 
10 #include <ldns/config.h>
11 
12 #include <ldns/ldns.h>
13 #include <ldns/buffer.h>
14 
16 ldns_buffer_new(size_t capacity)
17 {
19 
20  if (!buffer) {
21  return NULL;
22  }
23 
24  buffer->_data = (uint8_t *) LDNS_XMALLOC(uint8_t, capacity);
25  if (!buffer->_data) {
26  LDNS_FREE(buffer);
27  return NULL;
28  }
29 
30  buffer->_position = 0;
31  buffer->_limit = buffer->_capacity = capacity;
32  buffer->_fixed = 0;
33  buffer->_status = LDNS_STATUS_OK;
34 
35  ldns_buffer_invariant(buffer);
36 
37  return buffer;
38 }
39 
40 void
41 ldns_buffer_new_frm_data(ldns_buffer *buffer, const void *data, size_t size)
42 {
43  assert(data != NULL);
44 
45  buffer->_position = 0;
46  buffer->_limit = buffer->_capacity = size;
47  buffer->_fixed = 0;
48  buffer->_data = LDNS_XMALLOC(uint8_t, size);
49  if(!buffer->_data) {
50  buffer->_status = LDNS_STATUS_MEM_ERR;
51  return;
52  }
53  memcpy(buffer->_data, data, size);
54  buffer->_status = LDNS_STATUS_OK;
55 
56  ldns_buffer_invariant(buffer);
57 }
58 
59 bool
60 ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity)
61 {
62  void *data;
63 
64  ldns_buffer_invariant(buffer);
65  assert(buffer->_position <= capacity);
66  assert(!buffer->_fixed);
67 
68  data = (uint8_t *) LDNS_XREALLOC(buffer->_data, uint8_t, capacity);
69  if (!data) {
70  buffer->_status = LDNS_STATUS_MEM_ERR;
71  return false;
72  } else {
73  buffer->_data = data;
74  buffer->_limit = buffer->_capacity = capacity;
75  return true;
76  }
77 }
78 
79 bool
80 ldns_buffer_reserve(ldns_buffer *buffer, size_t amount)
81 {
82  ldns_buffer_invariant(buffer);
83  if (buffer->_capacity < buffer->_position + amount) {
84  size_t new_capacity = buffer->_capacity * 3 / 2;
85 
86  if (new_capacity < buffer->_position + amount) {
87  new_capacity = buffer->_position + amount;
88  }
89  if (!ldns_buffer_set_capacity(buffer, new_capacity)) {
90  buffer->_status = LDNS_STATUS_MEM_ERR;
91  return false;
92  }
93  }
94  buffer->_limit = buffer->_capacity;
95  return true;
96 }
97 
98 int
99 ldns_buffer_printf(ldns_buffer *buffer, const char *format, ...)
100 {
101  va_list args;
102  int written = 0;
103  size_t remaining;
104 
105  if (ldns_buffer_status_ok(buffer)) {
106  ldns_buffer_invariant(buffer);
107  assert(buffer->_limit == buffer->_capacity);
108 
109  remaining = ldns_buffer_remaining(buffer);
110  va_start(args, format);
111  written = vsnprintf((char *) ldns_buffer_current(buffer), remaining,
112  format, args);
113  va_end(args);
114  if (written == -1) {
116  return -1;
117  } else if ((size_t) written >= remaining) {
118  if (!ldns_buffer_reserve(buffer, (size_t) written + 1)) {
119  buffer->_status = LDNS_STATUS_MEM_ERR;
120  return -1;
121  }
122  va_start(args, format);
123  written = vsnprintf((char *) ldns_buffer_current(buffer),
124  ldns_buffer_remaining(buffer), format, args);
125  va_end(args);
126  if (written == -1) {
128  return -1;
129  }
130  }
131  buffer->_position += written;
132  }
133  return written;
134 }
135 
136 void
138 {
139  if (!buffer) {
140  return;
141  }
142 
143  if (!buffer->_fixed)
144  LDNS_FREE(buffer->_data);
145 
146  LDNS_FREE(buffer);
147 }
148 
149 void *
151 {
152  buffer->_fixed = 1;
153  return buffer->_data;
154 }
155 
156 int
158 {
159  if (!ldns_buffer_available_at(buffer, buffer->_position, sizeof(uint8_t))) {
160  ldns_buffer_set_position(buffer, ldns_buffer_limit(buffer));
161  /* ldns_buffer_rewind(buffer);*/
162  return EOF;
163  }
164  return (int)ldns_buffer_read_u8(buffer);
165 }
166 
167 void
169 {
170  size_t tocopy = ldns_buffer_limit(from);
171 
172  if(tocopy > ldns_buffer_capacity(result))
173  tocopy = ldns_buffer_capacity(result);
174  ldns_buffer_clear(result);
175  ldns_buffer_write(result, ldns_buffer_begin(from), tocopy);
176  ldns_buffer_flip(result);
177 }
void ldns_buffer_free(ldns_buffer *buffer)
frees the buffer.
Definition: buffer.c:137
bool ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity)
changes the buffer's capacity.
Definition: buffer.c:60
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
int ldns_bgetc(ldns_buffer *buffer)
returns the next character from a buffer.
Definition: buffer.c:157
ldns_buffer * ldns_buffer_new(size_t capacity)
creates a new buffer with the specified capacity.
Definition: buffer.c:16
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
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
void * ldns_buffer_export(ldns_buffer *buffer)
Makes the buffer fixed and returns a pointer to the data.
Definition: buffer.c:150
This file contains the definition of ldns_buffer, and functions to manipulate those.
@ LDNS_STATUS_MEM_ERR
Definition: error.h:34
@ LDNS_STATUS_INTERNAL_ERR
Definition: error.h:35
@ LDNS_STATUS_OK
Definition: error.h:26
Including this file will include all ldns files, and define some lookup tables.
implementation of buffers to ease operations
Definition: buffer.h:51
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
size_t _position
The current position used for reading/writing.
Definition: buffer.h:53
ldns_status _status
The current state of the buffer.
Definition: buffer.h:70
uint8_t * _data
The data contained in the buffer.
Definition: buffer.h:62
size_t _limit
The read/write limit.
Definition: buffer.h:56
#define LDNS_FREE(ptr)
Definition: util.h:60
#define LDNS_MALLOC(type)
Memory management macros.
Definition: util.h:49
#define LDNS_XMALLOC(type, count)
Definition: util.h:51
#define LDNS_XREALLOC(ptr, type, count)
Definition: util.h:57