Line data Source code
1 : /* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 : /*
3 : Copyright (C) 2010 Red Hat, Inc.
4 :
5 : This library is free software; you can redistribute it and/or
6 : modify it under the terms of the GNU Lesser General Public
7 : License as published by the Free Software Foundation; either
8 : version 2.1 of the License, or (at your option) any later version.
9 :
10 : This library is distributed in the hope that it will be useful,
11 : but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : Lesser General Public License for more details.
14 :
15 : You should have received a copy of the GNU Lesser General Public
16 : License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 : */
18 : #include <config.h>
19 :
20 : #include "mem.h"
21 :
22 : #include <string.h>
23 :
24 : #ifndef MALLOC_ERROR
25 : #define MALLOC_ERROR(...) SPICE_STMT_START { \
26 : spice_error(__VA_ARGS__); \
27 : abort(); \
28 : } SPICE_STMT_END
29 : #endif
30 :
31 0 : size_t spice_strnlen(const char *str, size_t max_len)
32 : {
33 0 : size_t len = 0;
34 :
35 0 : while (len < max_len && *str != 0) {
36 0 : len++;
37 0 : str++;
38 : }
39 :
40 0 : return len;
41 : }
42 :
43 0 : char *spice_strdup(const char *str)
44 : {
45 : char *copy;
46 : size_t len;
47 :
48 0 : if (str == NULL) {
49 0 : return NULL;
50 : }
51 :
52 0 : len = strlen(str) + 1;
53 0 : copy = (char *)spice_malloc(len);
54 0 : memcpy(copy, str, len);
55 0 : return copy;
56 : }
57 :
58 0 : char *spice_strndup(const char *str, size_t n_bytes)
59 : {
60 : char *copy;
61 :
62 0 : if (str == NULL) {
63 0 : return NULL;
64 : }
65 :
66 0 : copy = (char *)spice_malloc(n_bytes + 1);
67 0 : strncpy(copy, str, n_bytes);
68 0 : copy[n_bytes] = 0;
69 0 : return copy;
70 : }
71 :
72 0 : void *spice_memdup(const void *mem, size_t n_bytes)
73 : {
74 : void *copy;
75 :
76 0 : if (mem == NULL) {
77 0 : return NULL;
78 : }
79 :
80 0 : copy = spice_malloc(n_bytes);
81 0 : memcpy(copy, mem, n_bytes);
82 0 : return copy;
83 : }
84 :
85 3 : void *spice_malloc(size_t n_bytes)
86 : {
87 : void *mem;
88 :
89 3 : if (SPICE_LIKELY(n_bytes)) {
90 3 : mem = malloc(n_bytes);
91 :
92 3 : if (SPICE_LIKELY(mem != NULL)) {
93 3 : return mem;
94 : }
95 :
96 0 : MALLOC_ERROR("unable to allocate %lu bytes", (unsigned long)n_bytes);
97 : }
98 0 : return NULL;
99 : }
100 :
101 0 : void *spice_malloc0(size_t n_bytes)
102 : {
103 : void *mem;
104 :
105 0 : if (SPICE_LIKELY(n_bytes)) {
106 0 : mem = calloc(1, n_bytes);
107 :
108 0 : if (SPICE_LIKELY(mem != NULL)) {
109 0 : return mem;
110 : }
111 :
112 0 : MALLOC_ERROR("unable to allocate %lu bytes", (unsigned long)n_bytes);
113 : }
114 0 : return NULL;
115 : }
116 :
117 0 : void *spice_realloc(void *mem, size_t n_bytes)
118 : {
119 0 : if (SPICE_LIKELY(n_bytes)) {
120 0 : mem = realloc(mem, n_bytes);
121 :
122 0 : if (SPICE_LIKELY(mem != NULL)) {
123 0 : return mem;
124 : }
125 :
126 0 : MALLOC_ERROR("unable to allocate %lu bytes", (unsigned long)n_bytes);
127 : }
128 :
129 0 : free(mem);
130 :
131 0 : return NULL;
132 : }
133 :
134 : #define SIZE_OVERFLOWS(a,b) (SPICE_UNLIKELY ((a) > SIZE_MAX / (b)))
135 :
136 2 : void *spice_malloc_n(size_t n_blocks, size_t n_block_bytes)
137 : {
138 2 : if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) {
139 0 : MALLOC_ERROR("overflow allocating %lu*%lu bytes",
140 : (unsigned long)n_blocks, (unsigned long)n_block_bytes);
141 : }
142 :
143 2 : return spice_malloc(n_blocks * n_block_bytes);
144 : }
145 :
146 0 : void *spice_malloc_n_m(size_t n_blocks, size_t n_block_bytes, size_t extra_size)
147 : {
148 : size_t size1, size2;
149 0 : if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) {
150 0 : MALLOC_ERROR("spice_malloc_n: overflow allocating %lu*%lu + %lubytes",
151 : (unsigned long)n_blocks, (unsigned long)n_block_bytes, (unsigned long)extra_size);
152 : }
153 0 : size1 = n_blocks * n_block_bytes;
154 0 : size2 = size1 + extra_size;
155 0 : if (size2 < size1) {
156 0 : MALLOC_ERROR("spice_malloc_n: overflow allocating %lu*%lu + %lubytes",
157 : (unsigned long)n_blocks, (unsigned long)n_block_bytes, (unsigned long)extra_size);
158 : }
159 0 : return spice_malloc(size2);
160 : }
161 :
162 :
163 0 : void *spice_malloc0_n(size_t n_blocks, size_t n_block_bytes)
164 : {
165 0 : if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) {
166 0 : MALLOC_ERROR("spice_malloc0_n: overflow allocating %lu*%lu bytes",
167 : (unsigned long)n_blocks, (unsigned long)n_block_bytes);
168 : }
169 :
170 0 : return spice_malloc0 (n_blocks * n_block_bytes);
171 : }
172 :
173 0 : void *spice_realloc_n(void *mem, size_t n_blocks, size_t n_block_bytes)
174 : {
175 0 : if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) {
176 0 : MALLOC_ERROR("spice_realloc_n: overflow allocating %lu*%lu bytes",
177 : (unsigned long)n_blocks, (unsigned long)n_block_bytes);
178 : }
179 :
180 0 : return spice_realloc(mem, n_blocks * n_block_bytes);
181 : }
182 :
183 0 : SpiceChunks *spice_chunks_new(uint32_t count)
184 : {
185 : SpiceChunks *chunks;
186 :
187 0 : chunks = (SpiceChunks *)spice_malloc_n_m(count, sizeof(SpiceChunk), sizeof(SpiceChunks));
188 0 : chunks->flags = 0;
189 0 : chunks->num_chunks = count;
190 :
191 0 : return chunks;
192 : }
193 :
194 0 : SpiceChunks *spice_chunks_new_linear(uint8_t *data, uint32_t len)
195 : {
196 : SpiceChunks *chunks;
197 :
198 0 : chunks = spice_chunks_new(1);
199 0 : chunks->data_size = chunks->chunk[0].len = len;
200 0 : chunks->chunk[0].data = data;
201 0 : return chunks;
202 : }
203 :
204 0 : void spice_chunks_destroy(SpiceChunks *chunks)
205 : {
206 : unsigned int i;
207 :
208 0 : if (chunks->flags & SPICE_CHUNKS_FLAGS_FREE) {
209 0 : for (i = 0; i < chunks->num_chunks; i++) {
210 0 : free(chunks->chunk[i].data);
211 : }
212 : }
213 :
214 0 : free(chunks);
215 0 : }
216 :
217 0 : void spice_chunks_linearize(SpiceChunks *chunks)
218 : {
219 : uint8_t *data, *p;
220 : unsigned int i;
221 :
222 0 : if (chunks->num_chunks > 1) {
223 0 : data = (uint8_t*)spice_malloc(chunks->data_size);
224 0 : for (p = data, i = 0; i < chunks->num_chunks; i++) {
225 0 : memcpy(p, chunks->chunk[i].data,
226 0 : chunks->chunk[i].len);
227 0 : p += chunks->chunk[i].len;
228 : }
229 0 : if (chunks->flags & SPICE_CHUNKS_FLAGS_FREE) {
230 0 : for (i = 0; i < chunks->num_chunks; i++) {
231 0 : free(chunks->chunk[i].data);
232 : }
233 : }
234 0 : chunks->num_chunks = 1;
235 0 : chunks->flags |= SPICE_CHUNKS_FLAGS_FREE;
236 0 : chunks->flags &= ~SPICE_CHUNKS_FLAGS_UNSTABLE;
237 0 : chunks->chunk[0].data = data;
238 0 : chunks->chunk[0].len = chunks->data_size;
239 : }
240 0 : }
241 :
242 0 : void spice_buffer_reserve(SpiceBuffer *buffer, size_t len)
243 : {
244 0 : if ((buffer->capacity - buffer->offset) < len) {
245 0 : buffer->capacity += (len + 1024);
246 0 : buffer->buffer = (uint8_t*)spice_realloc(buffer->buffer, buffer->capacity);
247 : }
248 0 : }
249 :
250 0 : int spice_buffer_empty(SpiceBuffer *buffer)
251 : {
252 0 : return buffer->offset == 0;
253 : }
254 :
255 0 : uint8_t *spice_buffer_end(SpiceBuffer *buffer)
256 : {
257 0 : return buffer->buffer + buffer->offset;
258 : }
259 :
260 0 : void spice_buffer_reset(SpiceBuffer *buffer)
261 : {
262 0 : buffer->offset = 0;
263 0 : }
264 :
265 0 : void spice_buffer_free(SpiceBuffer *buffer)
266 : {
267 0 : free(buffer->buffer);
268 0 : buffer->offset = 0;
269 0 : buffer->capacity = 0;
270 0 : buffer->buffer = NULL;
271 0 : }
272 :
273 0 : void spice_buffer_append(SpiceBuffer *buffer, const void *data, size_t len)
274 : {
275 0 : spice_buffer_reserve(buffer, len);
276 0 : memcpy(buffer->buffer + buffer->offset, data, len);
277 0 : buffer->offset += len;
278 0 : }
279 :
280 0 : size_t spice_buffer_copy(SpiceBuffer *buffer, void *dest, size_t len)
281 : {
282 0 : len = MIN(buffer->offset, len);
283 0 : memcpy(dest, buffer->buffer, len);
284 0 : return len;
285 : }
286 :
287 0 : size_t spice_buffer_remove(SpiceBuffer *buffer, size_t len)
288 : {
289 0 : len = MIN(buffer->offset, len);
290 0 : memmove(buffer->buffer, buffer->buffer + len, buffer->offset - len);
291 0 : buffer->offset -= len;
292 0 : return len;
293 : }
294 :
295 : #ifdef SPICE_DEBUG_ALIGNMENT
296 : void spice_alignment_warning(const char *loc, void *p, unsigned sz)
297 : {
298 : static const char *last_loc = NULL;
299 : if (loc != last_loc) {
300 : last_loc = loc;
301 : spice_log(G_LOG_LEVEL_WARNING, loc, __FUNCTION__,
302 : "Misaligned access at %p, alignment %u", p, sz);
303 : }
304 : }
305 :
306 : void spice_alignment_debug(const char *loc, void *p, unsigned sz)
307 : {
308 : static const char *last_loc = NULL;
309 : if (loc != last_loc) {
310 : last_loc = loc;
311 : spice_log(G_LOG_LEVEL_DEBUG, loc, __FUNCTION__,
312 : "Expected misaligned access at %p, alignment %u", p, sz);
313 : }
314 : }
315 : #endif // SPICE_DEBUG_ALIGNMENT
|