Export to GitHub

armvn-repo - RING_BUFFER.wiki


Ring buffer implementation

``` typedef struct { char *buffer; int length; int start; int end; } RingBuffer;

RingBuffer *RingBuffer_create(int length);

void RingBuffer_destroy(RingBuffer *buffer);

int RingBuffer_read(RingBuffer *buffer, char *target, int amount);

int RingBuffer_write(RingBuffer *buffer, char *data, int length);

int RingBuffer_empty(RingBuffer *buffer);

int RingBuffer_full(RingBuffer *buffer);

int RingBuffer_available_data(RingBuffer *buffer);

int RingBuffer_available_space(RingBuffer *buffer);

bstring RingBuffer_gets(RingBuffer *buffer, int amount);

define RingBuffer_available_data(B) (((B)->end + 1) % (B)->length - (B)->start - 1)

define RingBuffer_available_space(B) ((B)->length - (B)->end - 1)

define RingBuffer_full(B) (RingBuffer_available_data((B)) - (B)->length == 0)

define RingBuffer_empty(B) (RingBuffer_available_data((B)) == 0)

define RingBuffer_puts(B, D) RingBuffer_write((B), bdata((D)), blength((D)))

define RingBuffer_get_all(B) RingBuffer_gets((B), RingBuffer_available_data((B)))

define RingBuffer_starts_at(B) ((B)->buffer + (B)->start)

define RingBuffer_ends_at(B) ((B)->buffer + (B)->end)

define RingBuffer_commit_read(B, A) ((B)->start = ((B)->start + (A)) % (B)->length)

define RingBuffer_commit_write(B, A) ((B)->end = ((B)->end + (A)) % (B)->length)

endif

```

``` RingBuffer *RingBuffer_create(int length) { RingBuffer *buffer = calloc(1, sizeof(RingBuffer)); buffer->length = length + 1; buffer->start = 0; buffer->end = 0; buffer->buffer = calloc(buffer->length, 1);

return buffer;

} ```

void RingBuffer_destroy(RingBuffer *buffer) { if(buffer) { free(buffer->buffer); free(buffer); } }

``` int RingBuffer_write(RingBuffer *buffer, char *data, int length) { if(RingBuffer_available_data(buffer) == 0) { buffer->start = buffer->end = 0; }

check(length <= RingBuffer_available_space(buffer),
        "Not enough space: %d request, %d available",
        RingBuffer_available_data(buffer), length);

void *result = memcpy(RingBuffer_ends_at(buffer), data, length);
check(result != NULL, "Failed to write data into buffer.");

RingBuffer_commit_write(buffer, length);

return length;

error: return -1; } ```

``` int RingBuffer_read(RingBuffer *buffer, char *target, int amount) { check_debug(amount <= RingBuffer_available_data(buffer), "Not enough in the buffer: has %d, needs %d", RingBuffer_available_data(buffer), amount);

void *result = memcpy(target, RingBuffer_starts_at(buffer), amount);
check(result != NULL, "Failed to write buffer into data.");

RingBuffer_commit_read(buffer, amount);

if(buffer->end == buffer->start) {
    buffer->start = buffer->end = 0;
}

return amount;

error: return -1; } ```

``` bstring RingBuffer_gets(RingBuffer *buffer, int amount) { check(amount > 0, "Need more than 0 for gets, you gave: %d ", amount); check_debug(amount <= RingBuffer_available_data(buffer), "Not enough in the buffer.");

bstring result = blk2bstr(RingBuffer_starts_at(buffer), amount);
check(result != NULL, "Failed to create gets result.");
check(blength(result) == amount, "Wrong result length.");

RingBuffer_commit_read(buffer, amount);
assert(RingBuffer_available_data(buffer) >= 0 && "Error in read commit.");

return result;

error: return NULL; } ```