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