packages feed

buffer-builder-0.1.0.0: buffer.cpp

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const size_t TRIM_THRESHOLD = 8192; // minimum number of bytes saved to trim

namespace {
    struct BufferWriter {
        unsigned char* data;
        size_t size;
        size_t capacity;
    };
}

// assumes malloc will not fail
// TODO: replace assert with some other error mechanism

extern "C" BufferWriter* bw_new(size_t initialCapacity) {
    assert(initialCapacity >= 1);
    BufferWriter* bw = reinterpret_cast<BufferWriter*>(malloc(sizeof(BufferWriter)));
    assert(bw);
    bw->data = reinterpret_cast<unsigned char*>(malloc(initialCapacity));
    assert(bw->data);
    bw->size = 0;
    bw->capacity = initialCapacity;
    return bw;
}

extern "C" void bw_free(BufferWriter* bw) {
    free(bw->data);
    free(bw);
}

extern "C" void bw_append_byte(BufferWriter* bw, unsigned char byte) {
    assert(bw->data);
    if (bw->size >= bw->capacity) {
        size_t newCapacity = bw->capacity * 2;
        unsigned char* nd = reinterpret_cast<unsigned char*>(realloc(bw->data, newCapacity));
        assert(nd);
        bw->data = nd;
        bw->capacity = newCapacity;
    }

    bw->data[bw->size] = byte;
    bw->size += 1;
}

extern "C" void bw_append_bs(BufferWriter* bw, size_t size, unsigned char* data) {
    assert(bw->data);
    if (bw->size + size > bw->capacity) {
        size_t newCapacity = bw->capacity * 2;
        while (bw->size + size > newCapacity) {
            newCapacity *= 2;
        }
        unsigned char* nd = reinterpret_cast<unsigned char*>(realloc(bw->data, newCapacity));
        assert(nd);
        bw->data = nd;
        bw->capacity = newCapacity;
    }

    memcpy(bw->data + bw->size, data, size);
    bw->size += size;
}

extern "C" size_t bw_get_size(BufferWriter* bw) {
    return bw->size;
}

extern "C" unsigned char* bw_trim_and_release_address(BufferWriter* bw) {
    unsigned char* data = bw->data;
    
    if (bw->size + TRIM_THRESHOLD < bw->capacity) {
        // try to shrink
        data = reinterpret_cast<unsigned char*>(realloc(data, bw->size));
        if (!data) {
            // no problem
            data = bw->data;
        }
    }

    bw->data = 0;
    return data;
}