1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/ucx/buffer.c Tue Aug 23 13:49:38 2016 +0200 1.3 @@ -0,0 +1,234 @@ 1.4 +/* 1.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 1.6 + * 1.7 + * Copyright 2015 Olaf Wintermann. All rights reserved. 1.8 + * 1.9 + * Redistribution and use in source and binary forms, with or without 1.10 + * modification, are permitted provided that the following conditions are met: 1.11 + * 1.12 + * 1. Redistributions of source code must retain the above copyright 1.13 + * notice, this list of conditions and the following disclaimer. 1.14 + * 1.15 + * 2. Redistributions in binary form must reproduce the above copyright 1.16 + * notice, this list of conditions and the following disclaimer in the 1.17 + * documentation and/or other materials provided with the distribution. 1.18 + * 1.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 1.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 1.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 1.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 1.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 1.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 1.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 1.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 1.29 + * POSSIBILITY OF SUCH DAMAGE. 1.30 + */ 1.31 + 1.32 +#include "buffer.h" 1.33 +#include <stdarg.h> 1.34 +#include <stdlib.h> 1.35 +#include <string.h> 1.36 + 1.37 +UcxBuffer *ucx_buffer_new(void *space, size_t capacity, int flags) { 1.38 + UcxBuffer *buffer = (UcxBuffer*) malloc(sizeof(UcxBuffer)); 1.39 + if (buffer) { 1.40 + buffer->flags = flags; 1.41 + if (!space) { 1.42 + buffer->space = (char*)malloc(capacity); 1.43 + if (!buffer->space) { 1.44 + free(buffer); 1.45 + return NULL; 1.46 + } 1.47 + memset(buffer->space, 0, capacity); 1.48 + buffer->flags |= UCX_BUFFER_AUTOFREE; 1.49 + } else { 1.50 + buffer->space = (char*)space; 1.51 + } 1.52 + buffer->capacity = capacity; 1.53 + buffer->size = 0; 1.54 + 1.55 + buffer->pos = 0; 1.56 + } 1.57 + 1.58 + return buffer; 1.59 +} 1.60 + 1.61 +void ucx_buffer_free(UcxBuffer *buffer) { 1.62 + if ((buffer->flags & UCX_BUFFER_AUTOFREE) == UCX_BUFFER_AUTOFREE) { 1.63 + free(buffer->space); 1.64 + } 1.65 + free(buffer); 1.66 +} 1.67 + 1.68 +UcxBuffer* ucx_buffer_extract( 1.69 + UcxBuffer *src, size_t start, size_t length, int flags) { 1.70 + 1.71 + if (src->size == 0 || length == 0 || start+length > src->capacity) { 1.72 + return NULL; 1.73 + } 1.74 + 1.75 + UcxBuffer *dst = (UcxBuffer*) malloc(sizeof(UcxBuffer)); 1.76 + if (dst) { 1.77 + dst->space = (char*)malloc(length); 1.78 + if (!dst->space) { 1.79 + free(dst); 1.80 + return NULL; 1.81 + } 1.82 + dst->capacity = length; 1.83 + dst->size = length; 1.84 + dst->flags = flags | UCX_BUFFER_AUTOFREE; 1.85 + dst->pos = 0; 1.86 + memcpy(dst->space, src->space+start, length); 1.87 + } 1.88 + return dst; 1.89 +} 1.90 + 1.91 +int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence) { 1.92 + size_t npos; 1.93 + switch (whence) { 1.94 + case SEEK_CUR: 1.95 + npos = buffer->pos; 1.96 + break; 1.97 + case SEEK_END: 1.98 + npos = buffer->size; 1.99 + break; 1.100 + case SEEK_SET: 1.101 + npos = 0; 1.102 + break; 1.103 + default: 1.104 + return -1; 1.105 + } 1.106 + 1.107 + size_t opos = npos; 1.108 + npos += offset; 1.109 + 1.110 + if ((offset > 0 && npos < opos) || (offset < 0 && npos > opos)) { 1.111 + return -1; 1.112 + } 1.113 + 1.114 + if (npos >= buffer->size) { 1.115 + return -1; 1.116 + } else { 1.117 + buffer->pos = npos; 1.118 + return 0; 1.119 + } 1.120 + 1.121 +} 1.122 + 1.123 +int ucx_buffer_eof(UcxBuffer *buffer) { 1.124 + return buffer->pos >= buffer->size; 1.125 +} 1.126 + 1.127 +int ucx_buffer_extend(UcxBuffer *buffer, size_t len) { 1.128 + size_t newcap = buffer->capacity; 1.129 + 1.130 + if (buffer->capacity + len < buffer->capacity) { 1.131 + return -1; 1.132 + } 1.133 + 1.134 + while (buffer->capacity + len > newcap) { 1.135 + newcap <<= 1; 1.136 + if (newcap < buffer->capacity) { 1.137 + return -1; 1.138 + } 1.139 + } 1.140 + 1.141 + char *newspace = (char*)realloc(buffer->space, newcap); 1.142 + if (newspace) { 1.143 + memset(newspace+buffer->size, 0, newcap-buffer->size); 1.144 + buffer->space = newspace; 1.145 + buffer->capacity = newcap; 1.146 + } else { 1.147 + return -1; 1.148 + } 1.149 + 1.150 + return 0; 1.151 +} 1.152 + 1.153 +size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems, 1.154 + UcxBuffer *buffer) { 1.155 + size_t len = size * nitems; 1.156 + size_t required = buffer->pos + len; 1.157 + if (buffer->pos > required) { 1.158 + return 0; 1.159 + } 1.160 + 1.161 + if (required > buffer->capacity) { 1.162 + if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) { 1.163 + if (ucx_buffer_extend(buffer, required - buffer->capacity)) { 1.164 + return 0; 1.165 + } 1.166 + } else { 1.167 + len = buffer->capacity - buffer->pos; 1.168 + if (size > 1) { 1.169 + len -= len%size; 1.170 + } 1.171 + } 1.172 + } 1.173 + 1.174 + if (len == 0) { 1.175 + return len; 1.176 + } 1.177 + 1.178 + memcpy(buffer->space + buffer->pos, ptr, len); 1.179 + buffer->pos += len; 1.180 + if(buffer->pos > buffer->size) { 1.181 + buffer->size = buffer->pos; 1.182 + } 1.183 + 1.184 + return len / size; 1.185 +} 1.186 + 1.187 +size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems, 1.188 + UcxBuffer *buffer) { 1.189 + size_t len = size * nitems; 1.190 + if (buffer->pos + len > buffer->size) { 1.191 + len = buffer->size - buffer->pos; 1.192 + if (size > 1) len -= len%size; 1.193 + } 1.194 + 1.195 + if (len <= 0) { 1.196 + return len; 1.197 + } 1.198 + 1.199 + memcpy(ptr, buffer->space + buffer->pos, len); 1.200 + buffer->pos += len; 1.201 + 1.202 + return len / size; 1.203 +} 1.204 + 1.205 +int ucx_buffer_putc(UcxBuffer *buffer, int c) { 1.206 + if(buffer->pos >= buffer->capacity) { 1.207 + if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) { 1.208 + if(ucx_buffer_extend(buffer, 1)) { 1.209 + return EOF; 1.210 + } 1.211 + } else { 1.212 + return EOF; 1.213 + } 1.214 + } 1.215 + 1.216 + c &= 0xFF; 1.217 + buffer->space[buffer->pos] = (char) c; 1.218 + buffer->pos++; 1.219 + if(buffer->pos > buffer->size) { 1.220 + buffer->size = buffer->pos; 1.221 + } 1.222 + return c; 1.223 +} 1.224 + 1.225 +int ucx_buffer_getc(UcxBuffer *buffer) { 1.226 + if (ucx_buffer_eof(buffer)) { 1.227 + return EOF; 1.228 + } else { 1.229 + int c = buffer->space[buffer->pos]; 1.230 + buffer->pos++; 1.231 + return c; 1.232 + } 1.233 +} 1.234 + 1.235 +size_t ucx_buffer_puts(UcxBuffer *buffer, char *str) { 1.236 + return ucx_buffer_write((const void*)str, 1, strlen(str), buffer); 1.237 +}