src/buffer.c

Mon, 27 Dec 2021 16:51:10 +0100

author
Mike Becker <universe@uap-core.de>
date
Mon, 27 Dec 2021 16:51:10 +0100
changeset 483
929016224c3c
child 489
af6be1e123aa
permissions
-rw-r--r--

add ported UCX buffer implementation

Notes:
* ucx_buffer_extend has been removed
in favor of cxBufferMinimumCapacity
* the buffer struct now has a union for
char* and unsigned char* buffers

     1 /*
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * Copyright 2021 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  */
    29 #include "cx/buffer.h"
    30 #include "cx/utils.h"
    32 #include <stdlib.h>
    33 #include <string.h>
    35 CxBuffer cxBufferCreate(
    36         void *space,
    37         size_t capacity,
    38         int flags
    39 ) {
    40     CxBuffer buffer = (CxBuffer) malloc(sizeof(cx_buffer_s));
    41     if (buffer) {
    42         buffer->flags = flags;
    43         if (!space) {
    44             buffer->bytes = malloc(capacity);
    45             if (!buffer->bytes) {
    46                 free(buffer);
    47                 return NULL;
    48             }
    49             memset(buffer->bytes, 0, capacity);
    50             buffer->flags |= CX_BUFFER_FREE_CONTENTS;
    51         } else {
    52             buffer->bytes = space;
    53         }
    54         buffer->capacity = capacity;
    55         buffer->size = 0;
    57         buffer->pos = 0;
    58     }
    60     return buffer;
    61 }
    63 void cxBufferDestroy(CxBuffer buffer) {
    64     if ((buffer->flags & CX_BUFFER_FREE_CONTENTS) == CX_BUFFER_FREE_CONTENTS) {
    65         free(buffer->bytes);
    66     }
    67     free(buffer);
    68 }
    70 CxBuffer cxBufferExtract(
    71         CxBuffer src,
    72         size_t start,
    73         size_t length,
    74         int flags
    75 ) {
    76     if (src->size == 0 || length == 0 ||
    77         ((size_t) -1) - start < length || start + length > src->capacity) {
    78         return NULL;
    79     }
    81     CxBuffer dst = (CxBuffer) malloc(sizeof(cx_buffer_s));
    82     if (dst) {
    83         dst->bytes = malloc(length);
    84         if (!dst->bytes) {
    85             free(dst);
    86             return NULL;
    87         }
    88         dst->capacity = length;
    89         dst->size = length;
    90         dst->flags = flags | CX_BUFFER_FREE_CONTENTS;
    91         dst->pos = 0;
    92         memcpy(dst->bytes, src->bytes + start, length);
    93     }
    94     return dst;
    95 }
    97 int cxBufferSeek(
    98         CxBuffer buffer,
    99         off_t offset,
   100         int whence
   101 ) {
   102     size_t npos;
   103     switch (whence) {
   104         case SEEK_CUR:
   105             npos = buffer->pos;
   106             break;
   107         case SEEK_END:
   108             npos = buffer->size;
   109             break;
   110         case SEEK_SET:
   111             npos = 0;
   112             break;
   113         default:
   114             return -1;
   115     }
   117     size_t opos = npos;
   118     npos += offset;
   120     if ((offset > 0 && npos < opos) || (offset < 0 && npos > opos)) {
   121         return -1;
   122     }
   124     if (npos >= buffer->size) {
   125         return -1;
   126     } else {
   127         buffer->pos = npos;
   128         return 0;
   129     }
   131 }
   133 int cxBufferEof(CxBuffer buffer) {
   134     return buffer->pos >= buffer->size;
   135 }
   137 int cxBufferMinimumCapacity(
   138         CxBuffer buffer,
   139         size_t additional_bytes
   140 ) {
   141     size_t newcap = buffer->capacity + additional_bytes;
   143     // overflow protection
   144     if (newcap < buffer->capacity) {
   145         return -1;
   146     }
   148     unsigned char *newspace = realloc(buffer->bytes, newcap);
   149     if (newspace) {
   150         memset(newspace + buffer->size, 0, newcap - buffer->size);
   151         buffer->bytes = newspace;
   152         buffer->capacity = newcap;
   153     } else {
   154         return -1;
   155     }
   157     return 0;
   158 }
   160 size_t cxBufferWrite(
   161         const void *ptr,
   162         size_t size,
   163         size_t nitems,
   164         CxBuffer buffer
   165 ) {
   166     size_t len;
   167     if (cx_szmul(size, nitems, &len)) {
   168         return 0;
   169     }
   170     size_t required = buffer->pos + len;
   171     if (buffer->pos > required) {
   172         return 0;
   173     }
   175     if (required > buffer->capacity) {
   176         if ((buffer->flags & CX_BUFFER_AUTO_EXTEND) == CX_BUFFER_AUTO_EXTEND) {
   177             if (cxBufferMinimumCapacity(buffer, required)) {
   178                 return 0;
   179             }
   180         } else {
   181             len = buffer->capacity - buffer->pos;
   182             if (size > 1) {
   183                 len -= len % size;
   184             }
   185         }
   186     }
   188     if (len == 0) {
   189         return len;
   190     }
   192     memcpy(buffer->bytes + buffer->pos, ptr, len);
   193     buffer->pos += len;
   194     if (buffer->pos > buffer->size) {
   195         buffer->size = buffer->pos;
   196     }
   198     return len / size;
   199 }
   201 size_t cxBufferRead(
   202         void *ptr,
   203         size_t size,
   204         size_t nitems,
   205         CxBuffer buffer
   206 ) {
   207     size_t len;
   208     if (cx_szmul(size, nitems, &len)) {
   209         return 0;
   210     }
   211     if (buffer->pos + len > buffer->size) {
   212         len = buffer->size - buffer->pos;
   213         if (size > 1) len -= len % size;
   214     }
   216     if (len <= 0) {
   217         return len;
   218     }
   220     memcpy(ptr, buffer->bytes + buffer->pos, len);
   221     buffer->pos += len;
   223     return len / size;
   224 }
   226 int cxBufferPut(
   227         CxBuffer buffer,
   228         int c
   229 ) {
   230     if (buffer->pos >= buffer->capacity) {
   231         if ((buffer->flags & CX_BUFFER_AUTO_EXTEND) == CX_BUFFER_AUTO_EXTEND) {
   232             if (cxBufferMinimumCapacity(buffer, buffer->capacity + 1)) {
   233                 return EOF;
   234             }
   235         } else {
   236             return EOF;
   237         }
   238     }
   240     c &= 0xFF;
   241     buffer->bytes[buffer->pos] = (unsigned char) c;
   242     buffer->pos++;
   243     if (buffer->pos > buffer->size) {
   244         buffer->size = buffer->pos;
   245     }
   246     return c;
   247 }
   249 int cxBufferGet(CxBuffer buffer) {
   250     if (cxBufferEof(buffer)) {
   251         return EOF;
   252     } else {
   253         int c = buffer->bytes[buffer->pos];
   254         buffer->pos++;
   255         return c;
   256     }
   257 }
   259 size_t cxBufferPutString(
   260         CxBuffer buffer,
   261         const char *str
   262 ) {
   263     return cxBufferWrite(str, 1, strlen(str), buffer);
   264 }
   266 int cxBufferShiftLeft(
   267         CxBuffer buffer,
   268         size_t shift
   269 ) {
   270     if (shift >= buffer->size) {
   271         buffer->pos = buffer->size = 0;
   272     } else {
   273         memmove(buffer->bytes, buffer->bytes + shift, buffer->size - shift);
   274         buffer->size -= shift;
   276         if (buffer->pos >= shift) {
   277             buffer->pos -= shift;
   278         } else {
   279             buffer->pos = 0;
   280         }
   281     }
   282     return 0;
   283 }
   285 int cxBufferShiftRight(
   286         CxBuffer buffer,
   287         size_t shift
   288 ) {
   289     size_t req_capacity = buffer->size + shift;
   290     size_t movebytes;
   292     // auto extend buffer, if required and enabled
   293     if (buffer->capacity < req_capacity) {
   294         if ((buffer->flags & CX_BUFFER_AUTO_EXTEND) == CX_BUFFER_AUTO_EXTEND) {
   295             if (cxBufferMinimumCapacity(buffer, req_capacity)) {
   296                 return 1;
   297             }
   298             movebytes = buffer->size;
   299         } else {
   300             movebytes = buffer->capacity - shift;
   301         }
   302     } else {
   303         movebytes = buffer->size;
   304     }
   306     memmove(buffer->bytes + shift, buffer->bytes, movebytes);
   307     buffer->size = shift + movebytes;
   309     buffer->pos += shift;
   310     if (buffer->pos > buffer->size) {
   311         buffer->pos = buffer->size;
   312     }
   314     return 0;
   315 }
   317 int cxBufferShift(
   318         CxBuffer buffer,
   319         off_t shift
   320 ) {
   321     if (shift < 0) {
   322         return cxBufferShiftLeft(buffer, (size_t) (-shift));
   323     } else if (shift > 0) {
   324         return cxBufferShiftRight(buffer, (size_t) shift);
   325     } else {
   326         return 0;
   327     }
   328 }

mercurial