]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/unbound/ldns/sbuffer.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / unbound / ldns / 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 "ldns/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->_status_err = 0;
37         
38         sldns_buffer_invariant(buffer);
39         
40         return buffer;
41 }
42
43 void
44 sldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size)
45 {
46         assert(data != NULL);
47
48         buffer->_position = 0; 
49         buffer->_limit = buffer->_capacity = size;
50         buffer->_fixed = 0;
51         buffer->_data = malloc(size);
52         if(!buffer->_data) {
53                 buffer->_status_err = 1;
54                 return;
55         }
56         memcpy(buffer->_data, data, size);
57         buffer->_status_err = 0;
58         
59         sldns_buffer_invariant(buffer);
60 }
61
62 void
63 sldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size)
64 {
65         memset(buffer, 0, sizeof(*buffer));
66         buffer->_data = data;
67         buffer->_capacity = buffer->_limit = size;
68         buffer->_fixed = 1;
69 }
70
71 int
72 sldns_buffer_set_capacity(sldns_buffer *buffer, size_t capacity)
73 {
74         void *data;
75         
76         sldns_buffer_invariant(buffer);
77         assert(buffer->_position <= capacity);
78
79         data = (uint8_t *) realloc(buffer->_data, capacity);
80         if (!data) {
81                 buffer->_status_err = 1;
82                 return 0;
83         } else {
84                 buffer->_data = data;
85                 buffer->_limit = buffer->_capacity = capacity;
86                 return 1;
87         }
88 }
89
90 int
91 sldns_buffer_reserve(sldns_buffer *buffer, size_t amount)
92 {
93         sldns_buffer_invariant(buffer);
94         assert(!buffer->_fixed);
95         if (buffer->_capacity < buffer->_position + amount) {
96                 size_t new_capacity = buffer->_capacity * 3 / 2;
97
98                 if (new_capacity < buffer->_position + amount) {
99                         new_capacity = buffer->_position + amount;
100                 }
101                 if (!sldns_buffer_set_capacity(buffer, new_capacity)) {
102                         buffer->_status_err = 1;
103                         return 0;
104                 }
105         }
106         buffer->_limit = buffer->_capacity;
107         return 1;
108 }
109
110 int
111 sldns_buffer_printf(sldns_buffer *buffer, const char *format, ...)
112 {
113         va_list args;
114         int written = 0;
115         size_t remaining;
116         
117         if (sldns_buffer_status_ok(buffer)) {
118                 sldns_buffer_invariant(buffer);
119                 assert(buffer->_limit == buffer->_capacity);
120
121                 remaining = sldns_buffer_remaining(buffer);
122                 va_start(args, format);
123                 written = vsnprintf((char *) sldns_buffer_current(buffer), remaining,
124                                     format, args);
125                 va_end(args);
126                 if (written == -1) {
127                         buffer->_status_err = 1;
128                         return -1;
129                 } else if ((size_t) written >= remaining) {
130                         if (!sldns_buffer_reserve(buffer, (size_t) written + 1)) {
131                                 buffer->_status_err = 1;
132                                 return -1;
133                         }
134                         va_start(args, format);
135                         written = vsnprintf((char *) sldns_buffer_current(buffer),
136                             sldns_buffer_remaining(buffer), format, args);
137                         va_end(args);
138                         if (written == -1) {
139                                 buffer->_status_err = 1;
140                                 return -1;
141                         }
142                 }
143                 buffer->_position += written;
144         }
145         return written;
146 }
147
148 void
149 sldns_buffer_free(sldns_buffer *buffer)
150 {
151         if (!buffer) {
152                 return;
153         }
154
155         if (!buffer->_fixed)
156                 free(buffer->_data);
157
158         free(buffer);
159 }
160
161 void *
162 sldns_buffer_export(sldns_buffer *buffer)
163 {
164         buffer->_fixed = 1;
165         return buffer->_data;
166 }
167
168 void 
169 sldns_buffer_copy(sldns_buffer* result, sldns_buffer* from)
170 {
171         size_t tocopy = sldns_buffer_limit(from);
172
173         if(tocopy > sldns_buffer_capacity(result))
174                 tocopy = sldns_buffer_capacity(result);
175         sldns_buffer_clear(result);
176         sldns_buffer_write(result, sldns_buffer_begin(from), tocopy);
177         sldns_buffer_flip(result);
178 }