]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/unbound/sldns/sbuffer.c
MFV r336950: 9290 device removal reduces redundancy of mirrors
[FreeBSD/FreeBSD.git] / contrib / unbound / sldns / sbuffer.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  * \file
11  *
12  * This file contains the definition of sldns_buffer, and functions to manipulate those.
13  */
14 #include "config.h"
15 #include "sldns/sbuffer.h"
16 #include <stdarg.h>
17
18 sldns_buffer *
19 sldns_buffer_new(size_t capacity)
20 {
21         sldns_buffer *buffer = (sldns_buffer*)malloc(sizeof(sldns_buffer));
22
23         if (!buffer) {
24                 return NULL;
25         }
26         
27         buffer->_data = (uint8_t *) malloc(capacity);
28         if (!buffer->_data) {
29                 free(buffer);
30                 return NULL;
31         }
32         
33         buffer->_position = 0;
34         buffer->_limit = buffer->_capacity = capacity;
35         buffer->_fixed = 0;
36         buffer->_vfixed = 0;
37         buffer->_status_err = 0;
38         
39         sldns_buffer_invariant(buffer);
40         
41         return buffer;
42 }
43
44 void
45 sldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size)
46 {
47         assert(data != NULL);
48
49         buffer->_position = 0; 
50         buffer->_limit = buffer->_capacity = size;
51         buffer->_fixed = 0;
52         buffer->_vfixed = 0;
53         if (!buffer->_fixed && buffer->_data)
54                 free(buffer->_data);
55         buffer->_data = malloc(size);
56         if(!buffer->_data) {
57                 buffer->_status_err = 1;
58                 return;
59         }
60         memcpy(buffer->_data, data, size);
61         buffer->_status_err = 0;
62         
63         sldns_buffer_invariant(buffer);
64 }
65
66 void
67 sldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size)
68 {
69         memset(buffer, 0, sizeof(*buffer));
70         buffer->_data = data;
71         buffer->_capacity = buffer->_limit = size;
72         buffer->_fixed = 1;
73         buffer->_vfixed = 0;
74 }
75
76 void
77 sldns_buffer_init_vfixed_frm_data(sldns_buffer *buffer, void *data, size_t size)
78 {
79         memset(buffer, 0, sizeof(*buffer));
80         buffer->_data = data;
81         buffer->_capacity = buffer->_limit = size;
82         buffer->_fixed = 1;
83         buffer->_vfixed = 1;
84 }
85
86 int
87 sldns_buffer_set_capacity(sldns_buffer *buffer, size_t capacity)
88 {
89         void *data;
90         
91         sldns_buffer_invariant(buffer);
92         assert(buffer->_position <= capacity && !buffer->_fixed);
93
94         data = (uint8_t *) realloc(buffer->_data, capacity);
95         if (!data) {
96                 buffer->_status_err = 1;
97                 return 0;
98         } else {
99                 buffer->_data = data;
100                 buffer->_limit = buffer->_capacity = capacity;
101                 return 1;
102         }
103 }
104
105 int
106 sldns_buffer_reserve(sldns_buffer *buffer, size_t amount)
107 {
108         sldns_buffer_invariant(buffer);
109         assert(!buffer->_fixed);
110         if (buffer->_capacity < buffer->_position + amount) {
111                 size_t new_capacity = buffer->_capacity * 3 / 2;
112
113                 if (new_capacity < buffer->_position + amount) {
114                         new_capacity = buffer->_position + amount;
115                 }
116                 if (!sldns_buffer_set_capacity(buffer, new_capacity)) {
117                         buffer->_status_err = 1;
118                         return 0;
119                 }
120         }
121         buffer->_limit = buffer->_capacity;
122         return 1;
123 }
124
125 int
126 sldns_buffer_printf(sldns_buffer *buffer, const char *format, ...)
127 {
128         va_list args;
129         int written = 0;
130         size_t remaining;
131         
132         if (sldns_buffer_status_ok(buffer)) {
133                 sldns_buffer_invariant(buffer);
134                 assert(buffer->_limit == buffer->_capacity);
135
136                 remaining = sldns_buffer_remaining(buffer);
137                 va_start(args, format);
138                 written = vsnprintf((char *) sldns_buffer_current(buffer), remaining,
139                                     format, args);
140                 va_end(args);
141                 if (written == -1) {
142                         buffer->_status_err = 1;
143                         return -1;
144                 } else if (!buffer->_vfixed && (size_t) written >= remaining) {
145                         if (!sldns_buffer_reserve(buffer, (size_t) written + 1)) {
146                                 buffer->_status_err = 1;
147                                 return -1;
148                         }
149                         va_start(args, format);
150                         written = vsnprintf((char *) sldns_buffer_current(buffer),
151                             sldns_buffer_remaining(buffer), format, args);
152                         va_end(args);
153                         if (written == -1) {
154                                 buffer->_status_err = 1;
155                                 return -1;
156                         }
157                 }
158                 buffer->_position += written;
159         }
160         return written;
161 }
162
163 void
164 sldns_buffer_free(sldns_buffer *buffer)
165 {
166         if (!buffer) {
167                 return;
168         }
169
170         if (!buffer->_fixed)
171                 free(buffer->_data);
172
173         free(buffer);
174 }
175
176 void *
177 sldns_buffer_export(sldns_buffer *buffer)
178 {
179         buffer->_fixed = 1;
180         return buffer->_data;
181 }
182
183 void 
184 sldns_buffer_copy(sldns_buffer* result, sldns_buffer* from)
185 {
186         size_t tocopy = sldns_buffer_limit(from);
187
188         if(tocopy > sldns_buffer_capacity(result))
189                 tocopy = sldns_buffer_capacity(result);
190         sldns_buffer_clear(result);
191         sldns_buffer_write(result, sldns_buffer_begin(from), tocopy);
192         sldns_buffer_flip(result);
193 }