UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2017 Mike Becker, Olaf Wintermann All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 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. 15 * 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. 27 */ 28 29 #include "ucx/buffer.h" 30 31 #include <stdarg.h> 32 #include <stdlib.h> 33 #include <string.h> 34 35 UcxBuffer *ucx_buffer_new(void *space, size_t capacity, int flags) { 36 UcxBuffer *buffer = (UcxBuffer*) malloc(sizeof(UcxBuffer)); 37 if (buffer) { 38 buffer->flags = flags; 39 if (!space) { 40 buffer->space = (char*)malloc(capacity); 41 if (!buffer->space) { 42 free(buffer); 43 return NULL; 44 } 45 memset(buffer->space, 0, capacity); 46 buffer->flags |= UCX_BUFFER_AUTOFREE; 47 } else { 48 buffer->space = (char*)space; 49 } 50 buffer->capacity = capacity; 51 buffer->size = 0; 52 53 buffer->pos = 0; 54 } 55 56 return buffer; 57 } 58 59 void ucx_buffer_free(UcxBuffer *buffer) { 60 if ((buffer->flags & UCX_BUFFER_AUTOFREE) == UCX_BUFFER_AUTOFREE) { 61 free(buffer->space); 62 } 63 free(buffer); 64 } 65 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) 70 { 71 return NULL; 72 } 73 74 UcxBuffer *dst = (UcxBuffer*) malloc(sizeof(UcxBuffer)); 75 if (dst) { 76 dst->space = (char*)malloc(length); 77 if (!dst->space) { 78 free(dst); 79 return NULL; 80 } 81 dst->capacity = length; 82 dst->size = length; 83 dst->flags = flags | UCX_BUFFER_AUTOFREE; 84 dst->pos = 0; 85 memcpy(dst->space, src->space+start, length); 86 } 87 return dst; 88 } 89 90 int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence) { 91 size_t npos; 92 switch (whence) { 93 case SEEK_CUR: 94 npos = buffer->pos; 95 break; 96 case SEEK_END: 97 npos = buffer->size; 98 break; 99 case SEEK_SET: 100 npos = 0; 101 break; 102 default: 103 return -1; 104 } 105 106 size_t opos = npos; 107 npos += offset; 108 109 if ((offset > 0 && npos < opos) || (offset < 0 && npos > opos)) { 110 return -1; 111 } 112 113 if (npos >= buffer->size) { 114 return -1; 115 } else { 116 buffer->pos = npos; 117 return 0; 118 } 119 120 } 121 122 int ucx_buffer_eof(UcxBuffer *buffer) { 123 return buffer->pos >= buffer->size; 124 } 125 126 int ucx_buffer_extend(UcxBuffer *buffer, size_t len) { 127 size_t newcap = buffer->capacity; 128 129 if (buffer->capacity + len < buffer->capacity) { 130 return -1; 131 } 132 133 while (buffer->capacity + len > newcap) { 134 newcap <<= 1; 135 if (newcap < buffer->capacity) { 136 return -1; 137 } 138 } 139 140 char *newspace = (char*)realloc(buffer->space, newcap); 141 if (newspace) { 142 memset(newspace+buffer->size, 0, newcap-buffer->size); 143 buffer->space = newspace; 144 buffer->capacity = newcap; 145 } else { 146 return -1; 147 } 148 149 return 0; 150 } 151 152 size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems, 153 UcxBuffer *buffer) { 154 size_t len; 155 if(ucx_szmul(size, nitems, &len)) { 156 return 0; 157 } 158 size_t required = buffer->pos + len; 159 if (buffer->pos > required) { 160 return 0; 161 } 162 163 if (required > buffer->capacity) { 164 if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) { 165 if (ucx_buffer_extend(buffer, required - buffer->capacity)) { 166 return 0; 167 } 168 } else { 169 len = buffer->capacity - buffer->pos; 170 if (size > 1) { 171 len -= len%size; 172 } 173 } 174 } 175 176 if (len == 0) { 177 return len; 178 } 179 180 memcpy(buffer->space + buffer->pos, ptr, len); 181 buffer->pos += len; 182 if(buffer->pos > buffer->size) { 183 buffer->size = buffer->pos; 184 } 185 186 return len / size; 187 } 188 189 size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems, 190 UcxBuffer *buffer) { 191 size_t len; 192 if(ucx_szmul(size, nitems, &len)) { 193 return 0; 194 } 195 if (buffer->pos + len > buffer->size) { 196 len = buffer->size - buffer->pos; 197 if (size > 1) len -= len%size; 198 } 199 200 if (len <= 0) { 201 return len; 202 } 203 204 memcpy(ptr, buffer->space + buffer->pos, len); 205 buffer->pos += len; 206 207 return len / size; 208 } 209 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)) { 214 return EOF; 215 } 216 } else { 217 return EOF; 218 } 219 } 220 221 c &= 0xFF; 222 buffer->space[buffer->pos] = (char) c; 223 buffer->pos++; 224 if(buffer->pos > buffer->size) { 225 buffer->size = buffer->pos; 226 } 227 return c; 228 } 229 230 int ucx_buffer_getc(UcxBuffer *buffer) { 231 if (ucx_buffer_eof(buffer)) { 232 return EOF; 233 } else { 234 int c = ((unsigned char*)buffer->space)[buffer->pos]; 235 buffer->pos++; 236 return c; 237 } 238 } 239 240 size_t ucx_buffer_puts(UcxBuffer *buffer, const char *str) { 241 return ucx_buffer_write((const void*)str, 1, strlen(str), buffer); 242 } 243 244 int ucx_buffer_shift_left(UcxBuffer* buffer, size_t shift) { 245 if (shift >= buffer->size) { 246 buffer->pos = buffer->size = 0; 247 } else { 248 memmove(buffer->space, buffer->space + shift, buffer->size - shift); 249 buffer->size -= shift; 250 251 if (buffer->pos >= shift) { 252 buffer->pos -= shift; 253 } else { 254 buffer->pos = 0; 255 } 256 } 257 return 0; 258 } 259 260 int ucx_buffer_shift_right(UcxBuffer* buffer, size_t shift) { 261 size_t req_capacity = buffer->size + shift; 262 size_t movebytes; 263 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)) { 268 return 1; 269 } 270 movebytes = buffer->size; 271 } else { 272 movebytes = buffer->capacity - shift; 273 } 274 } else { 275 movebytes = buffer->size; 276 } 277 278 memmove(buffer->space + shift, buffer->space, movebytes); 279 buffer->size = shift+movebytes; 280 281 buffer->pos += shift; 282 if (buffer->pos > buffer->size) { 283 buffer->pos = buffer->size; 284 } 285 286 return 0; 287 } 288 289 int ucx_buffer_shift(UcxBuffer* buffer, off_t shift) { 290 if (shift < 0) { 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); 294 } else { 295 return 0; 296 } 297 } 298