Merge branch 'master' of ssh://crater.dragonflybsd.org/repository/git/dragonfly
[dragonfly.git] / contrib / ldns / buffer.c
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 *
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
41 ldns_buffer_new_frm_data(ldns_buffer *buffer, 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
67         data = (uint8_t *) LDNS_XREALLOC(buffer->_data, uint8_t, capacity);
68         if (!data) {
69                 buffer->_status = LDNS_STATUS_MEM_ERR;
70                 return false;
71         } else {
72                 buffer->_data = data;
73                 buffer->_limit = buffer->_capacity = capacity;
74                 return true;
75         }
76 }
77
78 bool
79 ldns_buffer_reserve(ldns_buffer *buffer, size_t amount)
80 {
81         ldns_buffer_invariant(buffer);
82         assert(!buffer->_fixed);
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) {
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
137 ldns_buffer_free(ldns_buffer *buffer)
138 {
139         if (!buffer) {
140                 return;
141         }
142
143         LDNS_FREE(buffer->_data);
144
145         LDNS_FREE(buffer);
146 }
147
148 void *
149 ldns_buffer_export(ldns_buffer *buffer)
150 {
151         buffer->_fixed = 1;
152         return buffer->_data;
153 }
154
155 int
156 ldns_bgetc(ldns_buffer *buffer)
157 {
158         if (!ldns_buffer_available_at(buffer, buffer->_position, sizeof(uint8_t))) {
159                 ldns_buffer_set_position(buffer, ldns_buffer_limit(buffer));
160                 /* ldns_buffer_rewind(buffer);*/
161                 return EOF;
162         }
163         return (int)ldns_buffer_read_u8(buffer);
164 }
165
166 void 
167 ldns_buffer_copy(ldns_buffer* result, ldns_buffer* from)
168 {
169         size_t tocopy = ldns_buffer_limit(from);
170
171         if(tocopy > ldns_buffer_capacity(result))
172                 tocopy = ldns_buffer_capacity(result);
173         ldns_buffer_clear(result);
174         ldns_buffer_write(result, ldns_buffer_begin(from), tocopy);
175         ldns_buffer_flip(result);
176 }