ucx/buffer.c

Tue, 13 Aug 2013 13:51:00 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Tue, 13 Aug 2013 13:51:00 +0200
changeset 13
8a0cc4d90de7
parent 5
88625853ae74
child 17
11dffb40cd91
permissions
-rw-r--r--

added some error messages

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2013 Olaf Wintermann. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "buffer.h"
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

UcxBuffer *ucx_buffer_new(void *space, size_t size, int flags) {
    UcxBuffer *buffer = (UcxBuffer*) malloc(sizeof(UcxBuffer));
    if (buffer) {
        buffer->flags = flags;
        if (!space) {
            buffer->space = (char*)malloc(size);
            if (!buffer->space) {
                free(buffer);
                return NULL;
            }
            memset(buffer->space, 0, size);
            buffer->flags |= UCX_BUFFER_AUTOFREE;
        } else {
            buffer->space = (char*)space;
        }
        buffer->capacity = size;
        buffer->size = 0;

        buffer->pos = 0;
    }

    return buffer;
}

void ucx_buffer_free(UcxBuffer *buffer) {
    if ((buffer->flags & UCX_BUFFER_AUTOFREE) == UCX_BUFFER_AUTOFREE) {
        free(buffer->space);
    }
    free(buffer);
}

UcxBuffer* ucx_buffer_extract(
        UcxBuffer *src, size_t start, size_t length, int flags) {
    if(src->size == 0) {
        return NULL;
    }
    if (length == 0) {
        length = src->size - start;
    }
    if (start+length > src->size) {
        return NULL;
    }

    UcxBuffer *dst = (UcxBuffer*) malloc(sizeof(UcxBuffer));
    if (dst) {
        dst->space = (char*)malloc(length);
        if (!dst->space) {
            free(dst);
            return NULL;
        }
        dst->capacity = length;
        dst->size = length;
        dst->flags = flags | UCX_BUFFER_AUTOFREE;
        dst->pos = 0;
        memcpy(dst->space, src->space+start, length);
    }
    return dst;
}

int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence) {
    size_t npos = 0;
    switch (whence) {
    case SEEK_SET:
        npos = 0;
        break;
    case SEEK_CUR:
        npos = buffer->pos;
        break;
    case SEEK_END:
        npos = buffer->size;
        break;
    }

    npos += offset;
    
    if (npos > buffer->size) {
        return -1;
    } else {
        buffer->pos = npos;
        return 0;
    }

}

int ucx_buffer_eof(UcxBuffer *buffer) {
    return buffer->pos >= buffer->size;
}

int ucx_buffer_extend(UcxBuffer *buffer, size_t len) {
    size_t newcap = buffer->capacity;
    while (buffer->pos + len > newcap) newcap <<= 1;
    
    char *newspace = (char*)realloc(buffer->space, newcap);
    if (newspace) {
        memset(newspace+buffer->size, 0, newcap-buffer->size);
        buffer->space = newspace;
        buffer->capacity = newcap;
    } else {
        return -1;
    }
    
    return 0;
}

size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems,
        UcxBuffer *buffer) {
    size_t len = size * nitems;
    if (buffer->pos + len > buffer->capacity) {
        if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) {
            if(ucx_buffer_extend(buffer, len)) {
                return -1;
            }
        } else {
            len = buffer->capacity - buffer->pos;
            if (size > 1) len -= len%size;
        }
    }
    
    if (len <= 0) {
        return len;
    }
    
    memcpy(buffer->space + buffer->pos, ptr, len);
    buffer->pos += len;
    if(buffer->pos > buffer->size) {
        buffer->size = buffer->pos;
    }
    
    return len / size;
}

size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems,
        UcxBuffer *buffer) {
    size_t len = size * nitems;
    if (buffer->pos + len > buffer->size) {
        len = buffer->size - buffer->pos;
        if (size > 1) len -= len%size;
    }
    
    if (len <= 0) {
        return len;
    }
    
    memcpy(ptr, buffer->space + buffer->pos, len);
    buffer->pos += len;
    
    return len / size;
}

int ucx_buffer_putc(UcxBuffer *buffer, int c) {
    if(buffer->pos >= buffer->capacity) {
        if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) {
            if(ucx_buffer_extend(buffer, 1)) {
                return EOF;
            }
        } else {
            return EOF;
        }
    }
    
    c &= 0xFF;
    buffer->space[buffer->pos] = (char) c;
    buffer->pos++;
    if(buffer->pos > buffer->size) {
        buffer->size = buffer->pos;
    }
    return c;
}

int ucx_buffer_getc(UcxBuffer *buffer) {
    if (ucx_buffer_eof(buffer)) {
        return EOF;
    } else {
        int c = buffer->space[buffer->pos];
        buffer->pos++;
        return c;
    }
}

size_t ucx_buffer_generic_copy(void *s1, void *s2,
        read_func readfnc, write_func writefnc, size_t bufsize) {
    size_t ncp = 0;
    char *buf = (char*)malloc(bufsize);
    if(buf == NULL) {
        return 0;
    }
    
    size_t r;
    while((r = readfnc(buf, 1, bufsize, s1)) != 0) {
        r = writefnc(buf, 1, r, s2);
        ncp += r;
        if(r == 0) {
            break;
        }
    }
    
    free(buf);
    return ncp;
}

size_t ucx_buffer_generic_ncopy(void *s1, void *s2,
        read_func readfnc, write_func writefnc, size_t bufsize, size_t n) {
    if(n == 0) {
        return 0;
    }
    
    size_t ncp = 0;
    char *buf = (char*)malloc(bufsize);
    if(buf == NULL) {
        return 0;
    }
    
    size_t r;
    size_t rn = bufsize > n ? n : bufsize;
    while((r = readfnc(buf, 1, rn, s1)) != 0) {
        r = writefnc(buf, 1, r, s2);
        ncp += r;
        n -= r;
        rn = bufsize > n ? n : bufsize;
        if(r == 0 || n == 0) {
            break;
        }
    }
    
    free(buf);
    return ncp;
}

mercurial