1 /* |
1 /* |
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
3 * |
3 * |
4 * Copyright 2016 Olaf Wintermann. All rights reserved. |
4 * Copyright 2017 Mike Becker, Olaf Wintermann All rights reserved. |
5 * |
5 * |
6 * Redistribution and use in source and binary forms, with or without |
6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions are met: |
7 * modification, are permitted provided that the following conditions are met: |
8 * |
8 * |
9 * 1. Redistributions of source code must retain the above copyright |
9 * 1. Redistributions of source code must retain the above copyright |
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
26 * POSSIBILITY OF SUCH DAMAGE. |
26 * POSSIBILITY OF SUCH DAMAGE. |
27 */ |
27 */ |
28 |
28 |
29 #include "buffer.h" |
29 #include "ucx/buffer.h" |
|
30 |
30 #include <stdarg.h> |
31 #include <stdarg.h> |
31 #include <stdlib.h> |
32 #include <stdlib.h> |
32 #include <string.h> |
33 #include <string.h> |
33 |
34 |
34 UcxBuffer *ucx_buffer_new(void *space, size_t capacity, int flags) { |
35 UcxBuffer *ucx_buffer_new(void *space, size_t capacity, int flags) { |
62 free(buffer); |
63 free(buffer); |
63 } |
64 } |
64 |
65 |
65 UcxBuffer* ucx_buffer_extract( |
66 UcxBuffer* ucx_buffer_extract( |
66 UcxBuffer *src, size_t start, size_t length, int flags) { |
67 UcxBuffer *src, size_t start, size_t length, int flags) { |
67 |
68 if (src->size == 0 || length == 0 || |
68 if (src->size == 0 || length == 0 || start+length > src->capacity) { |
69 ((size_t)-1) - start < length || start+length > src->capacity) |
|
70 { |
69 return NULL; |
71 return NULL; |
70 } |
72 } |
71 |
73 |
72 UcxBuffer *dst = (UcxBuffer*) malloc(sizeof(UcxBuffer)); |
74 UcxBuffer *dst = (UcxBuffer*) malloc(sizeof(UcxBuffer)); |
73 if (dst) { |
75 if (dst) { |
147 return 0; |
149 return 0; |
148 } |
150 } |
149 |
151 |
150 size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems, |
152 size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems, |
151 UcxBuffer *buffer) { |
153 UcxBuffer *buffer) { |
152 size_t len = size * nitems; |
154 size_t len; |
153 const char *string = ptr; |
155 if(ucx_szmul(size, nitems, &len)) { |
|
156 return 0; |
|
157 } |
154 size_t required = buffer->pos + len; |
158 size_t required = buffer->pos + len; |
155 if (buffer->pos > required) { |
159 if (buffer->pos > required) { |
156 return 0; |
160 return 0; |
157 } |
161 } |
158 |
162 |
182 return len / size; |
186 return len / size; |
183 } |
187 } |
184 |
188 |
185 size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems, |
189 size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems, |
186 UcxBuffer *buffer) { |
190 UcxBuffer *buffer) { |
187 size_t len = size * nitems; |
191 size_t len; |
|
192 if(ucx_szmul(size, nitems, &len)) { |
|
193 return 0; |
|
194 } |
188 if (buffer->pos + len > buffer->size) { |
195 if (buffer->pos + len > buffer->size) { |
189 len = buffer->size - buffer->pos; |
196 len = buffer->size - buffer->pos; |
190 if (size > 1) len -= len%size; |
197 if (size > 1) len -= len%size; |
191 } |
198 } |
192 |
199 |
222 |
229 |
223 int ucx_buffer_getc(UcxBuffer *buffer) { |
230 int ucx_buffer_getc(UcxBuffer *buffer) { |
224 if (ucx_buffer_eof(buffer)) { |
231 if (ucx_buffer_eof(buffer)) { |
225 return EOF; |
232 return EOF; |
226 } else { |
233 } else { |
227 int c = buffer->space[buffer->pos]; |
234 int c = ((unsigned char*)buffer->space)[buffer->pos]; |
228 buffer->pos++; |
235 buffer->pos++; |
229 return c; |
236 return c; |
230 } |
237 } |
231 } |
238 } |
232 |
239 |
233 size_t ucx_buffer_puts(UcxBuffer *buffer, char *str) { |
240 size_t ucx_buffer_puts(UcxBuffer *buffer, const char *str) { |
234 return ucx_buffer_write((const void*)str, 1, strlen(str), buffer); |
241 return ucx_buffer_write((const void*)str, 1, strlen(str), buffer); |
235 } |
242 } |
|
243 |
|
244 int ucx_buffer_shift_left(UcxBuffer* buffer, size_t shift) { |
|
245 if (shift >= buffer->size) { |
|
246 buffer->pos = buffer->size = 0; |
|
247 } else { |
|
248 memmove(buffer->space, buffer->space + shift, buffer->size - shift); |
|
249 buffer->size -= shift; |
|
250 |
|
251 if (buffer->pos >= shift) { |
|
252 buffer->pos -= shift; |
|
253 } else { |
|
254 buffer->pos = 0; |
|
255 } |
|
256 } |
|
257 return 0; |
|
258 } |
|
259 |
|
260 int ucx_buffer_shift_right(UcxBuffer* buffer, size_t shift) { |
|
261 size_t req_capacity = buffer->size + shift; |
|
262 size_t movebytes; |
|
263 |
|
264 // auto extend buffer, if required and enabled |
|
265 if (buffer->capacity < req_capacity) { |
|
266 if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) { |
|
267 if (ucx_buffer_extend(buffer, req_capacity - buffer->capacity)) { |
|
268 return 1; |
|
269 } |
|
270 movebytes = buffer->size; |
|
271 } else { |
|
272 movebytes = buffer->capacity - shift; |
|
273 } |
|
274 } else { |
|
275 movebytes = buffer->size; |
|
276 } |
|
277 |
|
278 memmove(buffer->space + shift, buffer->space, movebytes); |
|
279 buffer->size = shift+movebytes; |
|
280 |
|
281 buffer->pos += shift; |
|
282 if (buffer->pos > buffer->size) { |
|
283 buffer->pos = buffer->size; |
|
284 } |
|
285 |
|
286 return 0; |
|
287 } |
|
288 |
|
289 int ucx_buffer_shift(UcxBuffer* buffer, off_t shift) { |
|
290 if (shift < 0) { |
|
291 return ucx_buffer_shift_left(buffer, (size_t) (-shift)); |
|
292 } else if (shift > 0) { |
|
293 return ucx_buffer_shift_right(buffer, (size_t) shift); |
|
294 } else { |
|
295 return 0; |
|
296 } |
|
297 } |