2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 * Copyright 2017 Mike Becker, Olaf Wintermann All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
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
26 * POSSIBILITY OF SUCH DAMAGE.
29 #include "ucx/buffer.h"
35 UcxBuffer *ucx_buffer_new(void *space, size_t capacity, int flags) {
36 UcxBuffer *buffer = (UcxBuffer*) malloc(sizeof(UcxBuffer));
38 buffer->flags = flags;
40 buffer->space = (char*)malloc(capacity);
45 memset(buffer->space, 0, capacity);
46 buffer->flags |= UCX_BUFFER_AUTOFREE;
48 buffer->space = (char*)space;
50 buffer->capacity = capacity;
59 void ucx_buffer_free(UcxBuffer *buffer) {
60 if ((buffer->flags & UCX_BUFFER_AUTOFREE) == UCX_BUFFER_AUTOFREE) {
66 UcxBuffer* ucx_buffer_extract(
67 UcxBuffer *src, size_t start, size_t length, int flags) {
68 if (src->size == 0 || length == 0 ||
69 ((size_t)-1) - start < length || start+length > src->capacity)
74 UcxBuffer *dst = (UcxBuffer*) malloc(sizeof(UcxBuffer));
76 dst->space = (char*)malloc(length);
81 dst->capacity = length;
83 dst->flags = flags | UCX_BUFFER_AUTOFREE;
85 memcpy(dst->space, src->space+start, length);
90 int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence) {
109 if ((offset > 0 && npos < opos) || (offset < 0 && npos > opos)) {
113 if (npos >= buffer->size) {
122 int ucx_buffer_eof(UcxBuffer *buffer) {
123 return buffer->pos >= buffer->size;
126 int ucx_buffer_extend(UcxBuffer *buffer, size_t len) {
127 size_t newcap = buffer->capacity;
129 if (buffer->capacity + len < buffer->capacity) {
133 while (buffer->capacity + len > newcap) {
135 if (newcap < buffer->capacity) {
140 char *newspace = (char*)realloc(buffer->space, newcap);
142 memset(newspace+buffer->size, 0, newcap-buffer->size);
143 buffer->space = newspace;
144 buffer->capacity = newcap;
152 size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems,
155 if(ucx_szmul(size, nitems, &len)) {
158 size_t required = buffer->pos + len;
159 if (buffer->pos > required) {
163 if (required > buffer->capacity) {
164 if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) {
165 if (ucx_buffer_extend(buffer, required - buffer->capacity)) {
169 len = buffer->capacity - buffer->pos;
180 memcpy(buffer->space + buffer->pos, ptr, len);
182 if(buffer->pos > buffer->size) {
183 buffer->size = buffer->pos;
189 size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems,
192 if(ucx_szmul(size, nitems, &len)) {
195 if (buffer->pos + len > buffer->size) {
196 len = buffer->size - buffer->pos;
197 if (size > 1) len -= len%size;
204 memcpy(ptr, buffer->space + buffer->pos, len);
210 int ucx_buffer_putc(UcxBuffer *buffer, int c) {
211 if(buffer->pos >= buffer->capacity) {
212 if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) {
213 if(ucx_buffer_extend(buffer, 1)) {
222 buffer->space[buffer->pos] = (char) c;
224 if(buffer->pos > buffer->size) {
225 buffer->size = buffer->pos;
230 int ucx_buffer_getc(UcxBuffer *buffer) {
231 if (ucx_buffer_eof(buffer)) {
234 int c = ((unsigned char*)buffer->space)[buffer->pos];
240 size_t ucx_buffer_puts(UcxBuffer *buffer, const char *str) {
241 return ucx_buffer_write((const void*)str, 1, strlen(str), buffer);
244 int ucx_buffer_shift_left(UcxBuffer* buffer, size_t shift) {
245 if (shift >= buffer->size) {
246 buffer->pos = buffer->size = 0;
248 memmove(buffer->space, buffer->space + shift, buffer->size - shift);
249 buffer->size -= shift;
251 if (buffer->pos >= shift) {
252 buffer->pos -= shift;
260 int ucx_buffer_shift_right(UcxBuffer* buffer, size_t shift) {
261 size_t req_capacity = buffer->size + shift;
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)) {
270 movebytes = buffer->size;
272 movebytes = buffer->capacity - shift;
275 movebytes = buffer->size;
278 memmove(buffer->space + shift, buffer->space, movebytes);
279 buffer->size = shift+movebytes;
281 buffer->pos += shift;
282 if (buffer->pos > buffer->size) {
283 buffer->pos = buffer->size;
289 int ucx_buffer_shift(UcxBuffer* buffer, off_t shift) {
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);