1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/buffer.c Tue Oct 17 16:15:41 2017 +0200 1.3 @@ -0,0 +1,236 @@ 1.4 +/* 1.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 1.6 + * 1.7 + * Copyright 2017 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 "ucx/buffer.h" 1.33 + 1.34 +#include <stdarg.h> 1.35 +#include <stdlib.h> 1.36 +#include <string.h> 1.37 + 1.38 +UcxBuffer *ucx_buffer_new(void *space, size_t capacity, int flags) { 1.39 + UcxBuffer *buffer = (UcxBuffer*) malloc(sizeof(UcxBuffer)); 1.40 + if (buffer) { 1.41 + buffer->flags = flags; 1.42 + if (!space) { 1.43 + buffer->space = (char*)malloc(capacity); 1.44 + if (!buffer->space) { 1.45 + free(buffer); 1.46 + return NULL; 1.47 + } 1.48 + memset(buffer->space, 0, capacity); 1.49 + buffer->flags |= UCX_BUFFER_AUTOFREE; 1.50 + } else { 1.51 + buffer->space = (char*)space; 1.52 + } 1.53 + buffer->capacity = capacity; 1.54 + buffer->size = 0; 1.55 + 1.56 + buffer->pos = 0; 1.57 + } 1.58 + 1.59 + return buffer; 1.60 +} 1.61 + 1.62 +void ucx_buffer_free(UcxBuffer *buffer) { 1.63 + if ((buffer->flags & UCX_BUFFER_AUTOFREE) == UCX_BUFFER_AUTOFREE) { 1.64 + free(buffer->space); 1.65 + } 1.66 + free(buffer); 1.67 +} 1.68 + 1.69 +UcxBuffer* ucx_buffer_extract( 1.70 + UcxBuffer *src, size_t start, size_t length, int flags) { 1.71 + if (src->size == 0 || length == 0 || 1.72 + ((size_t)-1) - start < length || start+length > src->capacity) 1.73 + { 1.74 + return NULL; 1.75 + } 1.76 + 1.77 + UcxBuffer *dst = (UcxBuffer*) malloc(sizeof(UcxBuffer)); 1.78 + if (dst) { 1.79 + dst->space = (char*)malloc(length); 1.80 + if (!dst->space) { 1.81 + free(dst); 1.82 + return NULL; 1.83 + } 1.84 + dst->capacity = length; 1.85 + dst->size = length; 1.86 + dst->flags = flags | UCX_BUFFER_AUTOFREE; 1.87 + dst->pos = 0; 1.88 + memcpy(dst->space, src->space+start, length); 1.89 + } 1.90 + return dst; 1.91 +} 1.92 + 1.93 +int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence) { 1.94 + size_t npos; 1.95 + switch (whence) { 1.96 + case SEEK_CUR: 1.97 + npos = buffer->pos; 1.98 + break; 1.99 + case SEEK_END: 1.100 + npos = buffer->size; 1.101 + break; 1.102 + case SEEK_SET: 1.103 + npos = 0; 1.104 + break; 1.105 + default: 1.106 + return -1; 1.107 + } 1.108 + 1.109 + size_t opos = npos; 1.110 + npos += offset; 1.111 + 1.112 + if ((offset > 0 && npos < opos) || (offset < 0 && npos > opos)) { 1.113 + return -1; 1.114 + } 1.115 + 1.116 + if (npos >= buffer->size) { 1.117 + return -1; 1.118 + } else { 1.119 + buffer->pos = npos; 1.120 + return 0; 1.121 + } 1.122 + 1.123 +} 1.124 + 1.125 +int ucx_buffer_eof(UcxBuffer *buffer) { 1.126 + return buffer->pos >= buffer->size; 1.127 +} 1.128 + 1.129 +int ucx_buffer_extend(UcxBuffer *buffer, size_t len) { 1.130 + size_t newcap = buffer->capacity; 1.131 + 1.132 + if (buffer->capacity + len < buffer->capacity) { 1.133 + return -1; 1.134 + } 1.135 + 1.136 + while (buffer->capacity + len > newcap) { 1.137 + newcap <<= 1; 1.138 + if (newcap < buffer->capacity) { 1.139 + return -1; 1.140 + } 1.141 + } 1.142 + 1.143 + char *newspace = (char*)realloc(buffer->space, newcap); 1.144 + if (newspace) { 1.145 + memset(newspace+buffer->size, 0, newcap-buffer->size); 1.146 + buffer->space = newspace; 1.147 + buffer->capacity = newcap; 1.148 + } else { 1.149 + return -1; 1.150 + } 1.151 + 1.152 + return 0; 1.153 +} 1.154 + 1.155 +size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems, 1.156 + UcxBuffer *buffer) { 1.157 + size_t len = size * nitems; 1.158 + size_t required = buffer->pos + len; 1.159 + if (buffer->pos > required) { 1.160 + return 0; 1.161 + } 1.162 + 1.163 + if (required > buffer->capacity) { 1.164 + if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) { 1.165 + if (ucx_buffer_extend(buffer, required - buffer->capacity)) { 1.166 + return 0; 1.167 + } 1.168 + } else { 1.169 + len = buffer->capacity - buffer->pos; 1.170 + if (size > 1) { 1.171 + len -= len%size; 1.172 + } 1.173 + } 1.174 + } 1.175 + 1.176 + if (len == 0) { 1.177 + return len; 1.178 + } 1.179 + 1.180 + memcpy(buffer->space + buffer->pos, ptr, len); 1.181 + buffer->pos += len; 1.182 + if(buffer->pos > buffer->size) { 1.183 + buffer->size = buffer->pos; 1.184 + } 1.185 + 1.186 + return len / size; 1.187 +} 1.188 + 1.189 +size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems, 1.190 + UcxBuffer *buffer) { 1.191 + size_t len = size * nitems; 1.192 + if (buffer->pos + len > buffer->size) { 1.193 + len = buffer->size - buffer->pos; 1.194 + if (size > 1) len -= len%size; 1.195 + } 1.196 + 1.197 + if (len <= 0) { 1.198 + return len; 1.199 + } 1.200 + 1.201 + memcpy(ptr, buffer->space + buffer->pos, len); 1.202 + buffer->pos += len; 1.203 + 1.204 + return len / size; 1.205 +} 1.206 + 1.207 +int ucx_buffer_putc(UcxBuffer *buffer, int c) { 1.208 + if(buffer->pos >= buffer->capacity) { 1.209 + if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) { 1.210 + if(ucx_buffer_extend(buffer, 1)) { 1.211 + return EOF; 1.212 + } 1.213 + } else { 1.214 + return EOF; 1.215 + } 1.216 + } 1.217 + 1.218 + c &= 0xFF; 1.219 + buffer->space[buffer->pos] = (char) c; 1.220 + buffer->pos++; 1.221 + if(buffer->pos > buffer->size) { 1.222 + buffer->size = buffer->pos; 1.223 + } 1.224 + return c; 1.225 +} 1.226 + 1.227 +int ucx_buffer_getc(UcxBuffer *buffer) { 1.228 + if (ucx_buffer_eof(buffer)) { 1.229 + return EOF; 1.230 + } else { 1.231 + int c = buffer->space[buffer->pos]; 1.232 + buffer->pos++; 1.233 + return c; 1.234 + } 1.235 +} 1.236 + 1.237 +size_t ucx_buffer_puts(UcxBuffer *buffer, char *str) { 1.238 + return ucx_buffer_write((const void*)str, 1, strlen(str), buffer); 1.239 +}