awk: Add our README files
[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->_data = LDNS_XMALLOC(uint8_t, size);
48         memcpy(buffer->_data, data, size);
49         buffer->_fixed = 0;
50         buffer->_status = LDNS_STATUS_OK;
51         
52         ldns_buffer_invariant(buffer);
53 }
54
55 bool
56 ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity)
57 {
58         void *data;
59         
60         ldns_buffer_invariant(buffer);
61         assert(buffer->_position <= capacity);
62
63         data = (uint8_t *) LDNS_XREALLOC(buffer->_data, uint8_t, capacity);
64         if (!data) {
65                 buffer->_status = LDNS_STATUS_MEM_ERR;
66                 return false;
67         } else {
68                 buffer->_data = data;
69                 buffer->_limit = buffer->_capacity = capacity;
70                 return true;
71         }
72 }
73
74 bool
75 ldns_buffer_reserve(ldns_buffer *buffer, size_t amount)
76 {
77         ldns_buffer_invariant(buffer);
78         assert(!buffer->_fixed);
79         if (buffer->_capacity < buffer->_position + amount) {
80                 size_t new_capacity = buffer->_capacity * 3 / 2;
81
82                 if (new_capacity < buffer->_position + amount) {
83                         new_capacity = buffer->_position + amount;
84                 }
85                 if (!ldns_buffer_set_capacity(buffer, new_capacity)) {
86                         buffer->_status = LDNS_STATUS_MEM_ERR;
87                         return false;
88                 }
89         }
90         buffer->_limit = buffer->_capacity;
91         return true;
92 }
93
94 int
95 ldns_buffer_printf(ldns_buffer *buffer, const char *format, ...)
96 {
97         va_list args;
98         int written = 0;
99         size_t remaining;
100         
101         if (ldns_buffer_status_ok(buffer)) {
102                 ldns_buffer_invariant(buffer);
103                 assert(buffer->_limit == buffer->_capacity);
104
105                 remaining = ldns_buffer_remaining(buffer);
106                 va_start(args, format);
107                 written = vsnprintf((char *) ldns_buffer_current(buffer), remaining,
108                                     format, args);
109                 va_end(args);
110                 if (written == -1) {
111                         buffer->_status = LDNS_STATUS_INTERNAL_ERR;
112                         return -1;
113                 } else if ((size_t) written >= remaining) {
114                         if (!ldns_buffer_reserve(buffer, (size_t) written + 1)) {
115                                 buffer->_status = LDNS_STATUS_MEM_ERR;
116                                 return -1;
117                         }
118                         va_start(args, format);
119                         written = vsnprintf((char *) ldns_buffer_current(buffer),
120                             ldns_buffer_remaining(buffer), format, args);
121                         va_end(args);
122                         if (written == -1) {
123                                 buffer->_status = LDNS_STATUS_INTERNAL_ERR;
124                                 return -1;
125                         }
126                 }
127                 buffer->_position += written;
128         }
129         return written;
130 }
131
132 void
133 ldns_buffer_free(ldns_buffer *buffer)
134 {
135         if (!buffer) {
136                 return;
137         }
138
139         LDNS_FREE(buffer->_data);
140
141         LDNS_FREE(buffer);
142 }
143
144 void *
145 ldns_buffer_export(ldns_buffer *buffer)
146 {
147         buffer->_fixed = 1;
148         return buffer->_data;
149 }
150
151 int
152 ldns_bgetc(ldns_buffer *buffer)
153 {
154         if (!ldns_buffer_available_at(buffer, buffer->_position, sizeof(uint8_t))) {
155                 ldns_buffer_set_position(buffer, ldns_buffer_limit(buffer));
156                 /* ldns_buffer_rewind(buffer);*/
157                 return EOF;
158         }
159         return (int)ldns_buffer_read_u8(buffer);
160 }
161
162 void 
163 ldns_buffer_copy(ldns_buffer* result, ldns_buffer* from)
164 {
165         size_t tocopy = ldns_buffer_limit(from);
166
167         if(tocopy > ldns_buffer_capacity(result))
168                 tocopy = ldns_buffer_capacity(result);
169         ldns_buffer_clear(result);
170         ldns_buffer_write(result, ldns_buffer_begin(from), tocopy);
171         ldns_buffer_flip(result);
172 }