]>
Commit | Line | Data |
---|---|---|
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 | } |