universe@103: /* universe@103: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. universe@103: * universe@259: * Copyright 2017 Mike Becker, Olaf Wintermann All rights reserved. universe@103: * universe@103: * Redistribution and use in source and binary forms, with or without universe@103: * modification, are permitted provided that the following conditions are met: universe@103: * universe@103: * 1. Redistributions of source code must retain the above copyright universe@103: * notice, this list of conditions and the following disclaimer. universe@103: * universe@103: * 2. Redistributions in binary form must reproduce the above copyright universe@103: * notice, this list of conditions and the following disclaimer in the universe@103: * documentation and/or other materials provided with the distribution. universe@103: * universe@103: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" universe@103: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE universe@103: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE universe@103: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE universe@103: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR universe@103: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF universe@103: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS universe@103: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN universe@103: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) universe@103: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE universe@103: * POSSIBILITY OF SUCH DAMAGE. universe@103: */ universe@103: universe@251: #include "ucx/buffer.h" universe@251: universe@56: #include universe@56: #include universe@56: #include universe@56: universe@169: UcxBuffer *ucx_buffer_new(void *space, size_t capacity, int flags) { universe@60: UcxBuffer *buffer = (UcxBuffer*) malloc(sizeof(UcxBuffer)); universe@60: if (buffer) { universe@61: buffer->flags = flags; universe@56: if (!space) { universe@169: buffer->space = (char*)malloc(capacity); universe@60: if (!buffer->space) { universe@60: free(buffer); universe@56: return NULL; universe@56: } universe@169: memset(buffer->space, 0, capacity); universe@61: buffer->flags |= UCX_BUFFER_AUTOFREE; universe@56: } else { olaf@78: buffer->space = (char*)space; universe@56: } universe@169: buffer->capacity = capacity; olaf@76: buffer->size = 0; universe@56: universe@60: buffer->pos = 0; universe@56: } universe@56: universe@60: return buffer; universe@56: } universe@56: universe@60: void ucx_buffer_free(UcxBuffer *buffer) { universe@63: if ((buffer->flags & UCX_BUFFER_AUTOFREE) == UCX_BUFFER_AUTOFREE) { universe@60: free(buffer->space); universe@56: } universe@60: free(buffer); universe@56: } universe@56: olaf@76: UcxBuffer* ucx_buffer_extract( olaf@76: UcxBuffer *src, size_t start, size_t length, int flags) { olaf@239: if (src->size == 0 || length == 0 || olaf@239: ((size_t)-1) - start < length || start+length > src->capacity) olaf@239: { universe@62: return NULL; universe@62: } universe@62: olaf@76: UcxBuffer *dst = (UcxBuffer*) malloc(sizeof(UcxBuffer)); universe@62: if (dst) { olaf@78: dst->space = (char*)malloc(length); universe@62: if (!dst->space) { universe@62: free(dst); universe@62: return NULL; universe@62: } olaf@76: dst->capacity = length; universe@62: dst->size = length; universe@62: dst->flags = flags | UCX_BUFFER_AUTOFREE; universe@62: dst->pos = 0; olaf@76: memcpy(dst->space, src->space+start, length); universe@62: } universe@62: return dst; universe@62: } universe@62: universe@60: int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence) { universe@140: size_t npos; universe@56: switch (whence) { universe@56: case SEEK_CUR: universe@60: npos = buffer->pos; universe@56: break; universe@56: case SEEK_END: olaf@76: npos = buffer->size; universe@56: break; universe@169: case SEEK_SET: universe@169: npos = 0; universe@169: break; universe@140: default: universe@169: return -1; universe@56: } universe@56: universe@169: size_t opos = npos; universe@56: npos += offset; olaf@76: universe@169: if ((offset > 0 && npos < opos) || (offset < 0 && npos > opos)) { universe@169: return -1; universe@169: } universe@169: universe@169: if (npos >= buffer->size) { universe@56: return -1; universe@56: } else { universe@60: buffer->pos = npos; universe@56: return 0; universe@56: } universe@56: universe@56: } universe@56: universe@60: int ucx_buffer_eof(UcxBuffer *buffer) { universe@62: return buffer->pos >= buffer->size; universe@56: } universe@56: olaf@76: int ucx_buffer_extend(UcxBuffer *buffer, size_t len) { olaf@76: size_t newcap = buffer->capacity; universe@169: universe@169: if (buffer->capacity + len < buffer->capacity) { universe@169: return -1; universe@169: } universe@169: universe@169: while (buffer->capacity + len > newcap) { universe@169: newcap <<= 1; universe@169: if (newcap < buffer->capacity) { universe@169: return -1; universe@169: } universe@169: } olaf@76: olaf@78: char *newspace = (char*)realloc(buffer->space, newcap); olaf@76: if (newspace) { olaf@76: memset(newspace+buffer->size, 0, newcap-buffer->size); olaf@76: buffer->space = newspace; olaf@76: buffer->capacity = newcap; olaf@76: } else { olaf@76: return -1; olaf@76: } olaf@76: olaf@76: return 0; olaf@76: } olaf@76: olaf@76: size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems, olaf@76: UcxBuffer *buffer) { olaf@76: size_t len = size * nitems; universe@169: size_t required = buffer->pos + len; universe@169: if (buffer->pos > required) { universe@169: return 0; universe@169: } universe@169: universe@169: if (required > buffer->capacity) { olaf@76: if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) { universe@169: if (ucx_buffer_extend(buffer, required - buffer->capacity)) { universe@169: return 0; universe@64: } universe@64: } else { olaf@76: len = buffer->capacity - buffer->pos; universe@169: if (size > 1) { universe@169: len -= len%size; universe@169: } universe@64: } universe@56: } olaf@76: universe@169: if (len == 0) { universe@64: return len; universe@56: } olaf@76: olaf@76: memcpy(buffer->space + buffer->pos, ptr, len); olaf@76: buffer->pos += len; olaf@76: if(buffer->pos > buffer->size) { olaf@76: buffer->size = buffer->pos; olaf@76: } olaf@76: olaf@76: return len / size; olaf@76: } universe@56: olaf@76: size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems, olaf@76: UcxBuffer *buffer) { olaf@76: size_t len = size * nitems; olaf@76: if (buffer->pos + len > buffer->size) { olaf@76: len = buffer->size - buffer->pos; olaf@76: if (size > 1) len -= len%size; universe@56: } olaf@76: olaf@76: if (len <= 0) { olaf@76: return len; olaf@76: } olaf@76: olaf@76: memcpy(ptr, buffer->space + buffer->pos, len); olaf@76: buffer->pos += len; olaf@76: olaf@76: return len / size; universe@56: } universe@56: universe@60: int ucx_buffer_putc(UcxBuffer *buffer, int c) { olaf@76: if(buffer->pos >= buffer->capacity) { olaf@76: if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) { olaf@76: if(ucx_buffer_extend(buffer, 1)) { olaf@76: return EOF; olaf@76: } olaf@76: } else { olaf@76: return EOF; olaf@76: } universe@56: } olaf@76: olaf@76: c &= 0xFF; olaf@76: buffer->space[buffer->pos] = (char) c; olaf@76: buffer->pos++; olaf@76: if(buffer->pos > buffer->size) { olaf@76: buffer->size = buffer->pos; olaf@76: } olaf@76: return c; universe@56: } universe@56: universe@60: int ucx_buffer_getc(UcxBuffer *buffer) { universe@60: if (ucx_buffer_eof(buffer)) { universe@56: return EOF; universe@56: } else { olaf@76: int c = buffer->space[buffer->pos]; universe@60: buffer->pos++; universe@56: return c; universe@56: } universe@56: } olaf@76: universe@140: size_t ucx_buffer_puts(UcxBuffer *buffer, char *str) { universe@140: return ucx_buffer_write((const void*)str, 1, strlen(str), buffer); olaf@76: }