/src/pupnp/upnp/src/genlib/util/membuffer.c
Line | Count | Source |
1 | | /******************************************************************************* |
2 | | * |
3 | | * Copyright (c) 2000-2003 Intel Corporation |
4 | | * All rights reserved. |
5 | | * Copyright (c) 2012 France Telecom All rights reserved. |
6 | | * |
7 | | * Redistribution and use in source and binary forms, with or without |
8 | | * modification, are permitted provided that the following conditions are met: |
9 | | * |
10 | | * - Redistributions of source code must retain the above copyright notice, |
11 | | * this list of conditions and the following disclaimer. |
12 | | * - Redistributions in binary form must reproduce the above copyright notice, |
13 | | * this list of conditions and the following disclaimer in the documentation |
14 | | * and/or other materials provided with the distribution. |
15 | | * - Neither name of Intel Corporation nor the names of its contributors |
16 | | * may be used to endorse or promote products derived from this software |
17 | | * without specific prior written permission. |
18 | | * |
19 | | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
20 | | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
21 | | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
22 | | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR |
23 | | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
24 | | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
25 | | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
26 | | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
27 | | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
28 | | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
29 | | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
30 | | * |
31 | | ******************************************************************************/ |
32 | | |
33 | | /* |
34 | | * \file |
35 | | * |
36 | | * \brief This file contains functions that operate on memory and buffers, |
37 | | * allocation, re-allocation, and modification of the memory |
38 | | */ |
39 | | |
40 | | #include "membuffer.h" |
41 | | #include "UpnpGlobal.h" |
42 | | #include "upnp.h" |
43 | | |
44 | | #include <assert.h> |
45 | | #include <stdlib.h> |
46 | | #include <string.h> |
47 | | |
48 | | #include "posix_overwrites.h" // IWYU pragma: keep |
49 | | |
50 | | char *str_alloc(const char *str, size_t str_len) |
51 | 802 | { |
52 | 802 | char *s; |
53 | | |
54 | 802 | s = (char *)malloc(str_len + (size_t)1); |
55 | 802 | if (s == NULL) { |
56 | 0 | return NULL; /* no mem */ |
57 | 0 | } |
58 | | |
59 | 802 | memcpy(s, str, str_len); |
60 | 802 | s[str_len] = '\0'; |
61 | | |
62 | 802 | return s; |
63 | 802 | } |
64 | | |
65 | | int memptr_cmp(memptr *m, const char *s) |
66 | 3.53k | { |
67 | 3.53k | int cmp; |
68 | | |
69 | 3.53k | cmp = strncmp(m->buf, s, m->length); |
70 | | |
71 | 3.53k | if (cmp == 0 && m->length < strlen(s)) { |
72 | | /* both strings equal for 'm->length' chars */ |
73 | | /* if m is shorter than s, then s is greater */ |
74 | 20 | return -1; |
75 | 20 | } |
76 | | |
77 | 3.51k | return cmp; |
78 | 3.53k | } |
79 | | |
80 | | int memptr_cmp_nocase(memptr *m, const char *s) |
81 | 215k | { |
82 | 215k | int cmp; |
83 | | |
84 | 215k | cmp = strncasecmp(m->buf, s, m->length); |
85 | 215k | if (cmp == 0 && m->length < strlen(s)) { |
86 | | /* both strings equal for 'm->length' chars */ |
87 | | /* if m is shorter than s, then s is greater */ |
88 | 3.09k | return -1; |
89 | 3.09k | } |
90 | | |
91 | 212k | return cmp; |
92 | 215k | } |
93 | | |
94 | | /*! |
95 | | * \brief Initialize the buffer. |
96 | | */ |
97 | | static UPNP_INLINE void membuffer_initialize( |
98 | | /*! [in,out] Buffer to be initialized. */ |
99 | | membuffer *m) |
100 | 27.9k | { |
101 | 27.9k | m->buf = NULL; |
102 | 27.9k | m->length = (size_t)0; |
103 | 27.9k | m->capacity = (size_t)0; |
104 | 27.9k | } |
105 | | |
106 | | int membuffer_set_size(membuffer *m, size_t new_length) |
107 | 18.7k | { |
108 | 18.7k | size_t diff; |
109 | 18.7k | size_t alloc_len; |
110 | 18.7k | char *temp_buf; |
111 | | |
112 | 18.7k | if (new_length >= m->length) { /* increase length */ |
113 | | /* need more mem? */ |
114 | 15.7k | if (new_length <= m->capacity) { |
115 | 2.90k | return 0; /* have enough mem; done */ |
116 | 2.90k | } |
117 | | |
118 | 12.8k | diff = new_length - m->length; |
119 | 12.8k | alloc_len = MAXVAL(m->size_inc, diff) + m->capacity; |
120 | 12.8k | } else { /* decrease length */ |
121 | | |
122 | 2.96k | assert(new_length <= m->length); |
123 | | |
124 | | /* if diff is 0..m->size_inc, don't free */ |
125 | 2.96k | if ((m->capacity - new_length) <= m->size_inc) { |
126 | 268 | return 0; |
127 | 268 | } |
128 | | |
129 | 2.69k | alloc_len = new_length + m->size_inc; |
130 | 2.69k | } |
131 | | |
132 | 18.7k | assert(alloc_len >= new_length); |
133 | | |
134 | 15.5k | temp_buf = realloc(m->buf, alloc_len + (size_t)1); /*LEAK_FIX_MK */ |
135 | | |
136 | | /*temp_buf = Realloc( m->buf,m->length, alloc_len + 1 );LEAK_FIX_MK */ |
137 | | |
138 | 15.5k | if (temp_buf == NULL) { |
139 | | /* try smaller size */ |
140 | 0 | alloc_len = new_length; |
141 | 0 | temp_buf = |
142 | 0 | realloc(m->buf, alloc_len + (size_t)1); /*LEAK_FIX_MK */ |
143 | | /*temp_buf = Realloc( m->buf,m->length, alloc_len + 1 |
144 | | * );LEAK_FIX_MK */ |
145 | |
|
146 | 0 | if (temp_buf == NULL) { |
147 | 0 | return UPNP_E_OUTOF_MEMORY; |
148 | 0 | } |
149 | 0 | } |
150 | | /* save */ |
151 | 15.5k | m->buf = temp_buf; |
152 | 15.5k | m->capacity = alloc_len; |
153 | 15.5k | return 0; |
154 | 15.5k | } |
155 | | |
156 | | void membuffer_init(membuffer *m) |
157 | 27.9k | { |
158 | 27.9k | assert(m != NULL); |
159 | | |
160 | 27.9k | m->size_inc = MEMBUF_DEF_SIZE_INC; |
161 | 27.9k | membuffer_initialize(m); |
162 | 27.9k | } |
163 | | |
164 | | void membuffer_destroy(membuffer *m) |
165 | 13.9k | { |
166 | 13.9k | if (m == NULL) { |
167 | 0 | return; |
168 | 0 | } |
169 | | |
170 | 13.9k | free(m->buf); |
171 | 13.9k | membuffer_init(m); |
172 | 13.9k | } |
173 | | |
174 | | int membuffer_assign(membuffer *m, const void *buf, size_t buf_len) |
175 | 9.75k | { |
176 | 9.75k | int return_code; |
177 | | |
178 | 9.75k | assert(m != NULL); |
179 | | |
180 | | /* set value to null */ |
181 | 9.75k | if (buf == NULL) { |
182 | 0 | membuffer_destroy(m); |
183 | 0 | return 0; |
184 | 0 | } |
185 | | /* alloc mem */ |
186 | 9.75k | return_code = membuffer_set_size(m, buf_len); |
187 | 9.75k | if (return_code != 0) |
188 | 0 | return return_code; |
189 | | /* copy */ |
190 | 9.75k | if (buf_len) { |
191 | 8.53k | memcpy(m->buf, buf, buf_len); |
192 | 8.53k | m->buf[buf_len] = 0; /* null-terminate */ |
193 | 8.53k | } |
194 | 9.75k | m->length = buf_len; |
195 | | |
196 | 9.75k | return 0; |
197 | 9.75k | } |
198 | | |
199 | | int membuffer_assign_str(membuffer *m, const char *c_str) |
200 | 0 | { |
201 | 0 | return membuffer_assign(m, c_str, strlen(c_str)); |
202 | 0 | } |
203 | | |
204 | | int membuffer_append(membuffer *m, const void *buf, size_t buf_len) |
205 | 4.40k | { |
206 | 4.40k | assert(m != NULL); |
207 | | |
208 | 4.40k | return membuffer_insert(m, buf, buf_len, m->length); |
209 | 4.40k | } |
210 | | |
211 | | int membuffer_append_str(membuffer *m, const char *c_str) |
212 | 1.63k | { |
213 | 1.63k | return membuffer_insert(m, c_str, strlen(c_str), m->length); |
214 | 1.63k | } |
215 | | |
216 | | int membuffer_insert( |
217 | | membuffer *m, const void *buf, size_t buf_len, size_t index) |
218 | 6.04k | { |
219 | 6.04k | int return_code; |
220 | | |
221 | 6.04k | assert(m != NULL); |
222 | | |
223 | 6.04k | if (index > m->length) |
224 | 0 | return UPNP_E_OUTOF_BOUNDS; |
225 | 6.04k | if (!buf || !buf_len) { |
226 | 2 | return 0; |
227 | 2 | } |
228 | | /* alloc mem */ |
229 | 6.04k | return_code = membuffer_set_size(m, m->length + buf_len); |
230 | 6.04k | if (return_code) { |
231 | 0 | return return_code; |
232 | 0 | } |
233 | | /* insert data */ |
234 | | /* move data to right of insertion point */ |
235 | 6.04k | memmove(m->buf + index + buf_len, m->buf + index, m->length - index); |
236 | 6.04k | memcpy(m->buf + index, buf, buf_len); |
237 | 6.04k | m->length += buf_len; |
238 | | /* null-terminate */ |
239 | 6.04k | m->buf[m->length] = 0; |
240 | | |
241 | 6.04k | return 0; |
242 | 6.04k | } |
243 | | |
244 | | void membuffer_delete(membuffer *m, size_t index, size_t num_bytes) |
245 | 2.96k | { |
246 | 2.96k | int return_value; |
247 | 2.96k | size_t new_length; |
248 | 2.96k | size_t copy_len; |
249 | | |
250 | 2.96k | assert(m != NULL); |
251 | | |
252 | 2.96k | if (!m || !m->length) |
253 | 0 | return; |
254 | | /* shrink count if it goes beyond buffer */ |
255 | 2.96k | if (index + num_bytes > m->length) { |
256 | 0 | num_bytes = m->length - index; |
257 | | /* every thing at and after index purged */ |
258 | 0 | copy_len = (size_t)0; |
259 | 2.96k | } else { |
260 | | /* calc num bytes after deleted string */ |
261 | 2.96k | copy_len = m->length - (index + num_bytes); |
262 | 2.96k | } |
263 | 2.96k | memmove(m->buf + index, m->buf + index + num_bytes, copy_len); |
264 | 2.96k | new_length = m->length - num_bytes; |
265 | | /* trim buffer */ |
266 | 2.96k | return_value = membuffer_set_size(m, new_length); |
267 | | /* shrinking should always work */ |
268 | 2.96k | assert(return_value == 0); |
269 | 2.96k | if (return_value != 0) |
270 | 0 | return; |
271 | | |
272 | | /* don't modify until buffer is set */ |
273 | 2.96k | m->length = new_length; |
274 | 2.96k | m->buf[new_length] = 0; |
275 | 2.96k | } |
276 | | |
277 | | char *membuffer_detach(membuffer *m) |
278 | 0 | { |
279 | 0 | char *buf; |
280 | |
|
281 | 0 | assert(m != NULL); |
282 | |
|
283 | 0 | buf = m->buf; |
284 | | |
285 | | /* free all */ |
286 | 0 | membuffer_initialize(m); |
287 | |
|
288 | 0 | return buf; |
289 | 0 | } |
290 | | |
291 | | void membuffer_attach(membuffer *m, char *new_buf, size_t buf_len) |
292 | 0 | { |
293 | 0 | assert(m != NULL); |
294 | |
|
295 | 0 | membuffer_destroy(m); |
296 | 0 | m->buf = new_buf; |
297 | 0 | m->length = buf_len; |
298 | 0 | m->capacity = buf_len; |
299 | 0 | } |