UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2016 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 "buffer.h" 30 #include <stdarg.h> 31 #include <stdlib.h> 32 #include <string.h> 33 34 UcxBuffer *ucx_buffer_new(void *space, size_t capacity, int flags) { 35 UcxBuffer *buffer = (UcxBuffer*) malloc(sizeof(UcxBuffer)); 36 if (buffer) { 37 buffer->flags = flags; 38 if (!space) { 39 buffer->space = (char*)malloc(capacity); 40 if (!buffer->space) { 41 free(buffer); 42 return NULL; 43 } 44 memset(buffer->space, 0, capacity); 45 buffer->flags |= UCX_BUFFER_AUTOFREE; 46 } else { 47 buffer->space = (char*)space; 48 } 49 buffer->capacity = capacity; 50 buffer->size = 0; 51 52 buffer->pos = 0; 53 } 54 55 return buffer; 56 } 57 58 void ucx_buffer_free(UcxBuffer *buffer) { 59 if ((buffer->flags & UCX_BUFFER_AUTOFREE) == UCX_BUFFER_AUTOFREE) { 60 free(buffer->space); 61 } 62 free(buffer); 63 } 64 65 UcxBuffer* ucx_buffer_extract( 66 UcxBuffer *src, size_t start, size_t length, int flags) { 67 68 if (src->size == 0 || length == 0 || start+length > src->capacity) { 69 return NULL; 70 } 71 72 UcxBuffer *dst = (UcxBuffer*) malloc(sizeof(UcxBuffer)); 73 if (dst) { 74 dst->space = (char*)malloc(length); 75 if (!dst->space) { 76 free(dst); 77 return NULL; 78 } 79 dst->capacity = length; 80 dst->size = length; 81 dst->flags = flags | UCX_BUFFER_AUTOFREE; 82 dst->pos = 0; 83 memcpy(dst->space, src->space+start, length); 84 } 85 return dst; 86 } 87 88 int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence) { 89 size_t npos; 90 switch (whence) { 91 case SEEK_CUR: 92 npos = buffer->pos; 93 break; 94 case SEEK_END: 95 npos = buffer->size; 96 break; 97 case SEEK_SET: 98 npos = 0; 99 break; 100 default: 101 return -1; 102 } 103 104 size_t opos = npos; 105 npos += offset; 106 107 if ((offset > 0 && npos < opos) || (offset < 0 && npos > opos)) { 108 return -1; 109 } 110 111 if (npos >= buffer->size) { 112 return -1; 113 } else { 114 buffer->pos = npos; 115 return 0; 116 } 117 118 } 119 120 int ucx_buffer_eof(UcxBuffer *buffer) { 121 return buffer->pos >= buffer->size; 122 } 123 124 int ucx_buffer_extend(UcxBuffer *buffer, size_t len) { 125 size_t newcap = buffer->capacity; 126 127 if (buffer->capacity + len < buffer->capacity) { 128 return -1; 129 } 130 131 while (buffer->capacity + len > newcap) { 132 newcap <<= 1; 133 if (newcap < buffer->capacity) { 134 return -1; 135 } 136 } 137 138 char *newspace = (char*)realloc(buffer->space, newcap); 139 if (newspace) { 140 memset(newspace+buffer->size, 0, newcap-buffer->size); 141 buffer->space = newspace; 142 buffer->capacity = newcap; 143 } else { 144 return -1; 145 } 146 147 return 0; 148 } 149 150 size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems, 151 UcxBuffer *buffer) { 152 size_t len = size * nitems; 153 size_t required = buffer->pos + len; 154 if (buffer->pos > required) { 155 return 0; 156 } 157 158 if (required > buffer->capacity) { 159 if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) { 160 if (ucx_buffer_extend(buffer, required - buffer->capacity)) { 161 return 0; 162 } 163 } else { 164 len = buffer->capacity - buffer->pos; 165 if (size > 1) { 166 len -= len%size; 167 } 168 } 169 } 170 171 if (len == 0) { 172 return len; 173 } 174 175 memcpy(buffer->space + buffer->pos, ptr, len); 176 buffer->pos += len; 177 if(buffer->pos > buffer->size) { 178 buffer->size = buffer->pos; 179 } 180 181 return len / size; 182 } 183 184 size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems, 185 UcxBuffer *buffer) { 186 size_t len = size * nitems; 187 if (buffer->pos + len > buffer->size) { 188 len = buffer->size - buffer->pos; 189 if (size > 1) len -= len%size; 190 } 191 192 if (len <= 0) { 193 return len; 194 } 195 196 memcpy(ptr, buffer->space + buffer->pos, len); 197 buffer->pos += len; 198 199 return len / size; 200 } 201 202 int ucx_buffer_putc(UcxBuffer *buffer, int c) { 203 if(buffer->pos >= buffer->capacity) { 204 if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) { 205 if(ucx_buffer_extend(buffer, 1)) { 206 return EOF; 207 } 208 } else { 209 return EOF; 210 } 211 } 212 213 c &= 0xFF; 214 buffer->space[buffer->pos] = (char) c; 215 buffer->pos++; 216 if(buffer->pos > buffer->size) { 217 buffer->size = buffer->pos; 218 } 219 return c; 220 } 221 222 int ucx_buffer_getc(UcxBuffer *buffer) { 223 if (ucx_buffer_eof(buffer)) { 224 return EOF; 225 } else { 226 int c = buffer->space[buffer->pos]; 227 buffer->pos++; 228 return c; 229 } 230 } 231 232 size_t ucx_buffer_puts(UcxBuffer *buffer, char *str) { 233 return ucx_buffer_write((const void*)str, 1, strlen(str), buffer); 234 } 235