xref: /dragonfly/contrib/ldns/buffer.c (revision 7733acb50455a11cc2ee36edd926ff0fa3361e9a)
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 
15 ldns_buffer *
ldns_buffer_new(size_t capacity)16 ldns_buffer_new(size_t capacity)
17 {
18           ldns_buffer *buffer = LDNS_MALLOC(ldns_buffer);
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
ldns_buffer_new_frm_data(ldns_buffer * buffer,const void * data,size_t size)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
ldns_buffer_set_capacity(ldns_buffer * buffer,size_t capacity)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
ldns_buffer_reserve(ldns_buffer * buffer,size_t amount)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
ldns_buffer_printf(ldns_buffer * buffer,const char * format,...)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) {
115                               buffer->_status = LDNS_STATUS_INTERNAL_ERR;
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) {
127                                         buffer->_status = LDNS_STATUS_INTERNAL_ERR;
128                                         return -1;
129                               }
130                     }
131                     buffer->_position += written;
132           }
133           return written;
134 }
135 
136 void
ldns_buffer_free(ldns_buffer * buffer)137 ldns_buffer_free(ldns_buffer *buffer)
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 *
ldns_buffer_export(ldns_buffer * buffer)150 ldns_buffer_export(ldns_buffer *buffer)
151 {
152           buffer->_fixed = 1;
153           return buffer->_data;
154 }
155 
156 int
ldns_bgetc(ldns_buffer * buffer)157 ldns_bgetc(ldns_buffer *buffer)
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
ldns_buffer_copy(ldns_buffer * result,const ldns_buffer * from)168 ldns_buffer_copy(ldns_buffer* result, const ldns_buffer* from)
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 }
178