Skip to content
Snippets Groups Projects
circ_buffer.c 1.98 KiB
//
// Created by dawehr on 10/24/2016.
//

#include "circ_buffer.h"

#define circ_buf_min(a,b) \
   ({ __typeof__ (a) _a = (a); \
       __typeof__ (b) _b = (b); \
     _a < _b ? _a : _b; })


static unsigned char buffer[CIRC_BUFFER_SIZE];
static size_t buf_start = 0;
static size_t buf_end = 0;
static size_t size = 0;


struct data_chunk getChunk(size_t amount) {
    size_t chunk_end = buf_end;
    if (buf_end < buf_start) {
        chunk_end = CIRC_BUFFER_SIZE;
    }
    size_t ret_size = circ_buf_min(amount, chunk_end - buf_start);
    struct data_chunk c = {
            ret_size,
             &buffer[buf_start]
    };
    return c;
}


void markConsumed(size_t n_consumed) {
    size_t chunk_end = buf_start + n_consumed;
    buf_start = chunk_end;
    size -= n_consumed;
    if (buf_start == CIRC_BUFFER_SIZE) {
        buf_start = 0;
    }

}

size_t putChunk(struct data_chunk c) {
    // The amount that will be placed into the buffer
    size_t will_place = circ_buf_min(CIRC_BUFFER_SIZE - size, c.length);
    // Actual amount placed so far
    size_t placed = 0;
    int loops = 0; // Limit on number of iterations, just in case
    while (placed < will_place && loops < 2) {
        // Available room without wrapping
        size_t to_copy;
        if (buf_end  >= buf_start) {
            // If buffer is not wrapped, we can copy until the end of the buffer
            to_copy = circ_buf_min(will_place, CIRC_BUFFER_SIZE - buf_end);
        } else {
            // Otherwise, remaining space in buffer is contiguous
            to_copy = will_place - placed;
        }
        memcpy(buffer + buf_end, c.data + placed, to_copy);
        // Update buffer endpoint
        buf_end += to_copy;
        // If we copied to the end
        if (buf_end >= CIRC_BUFFER_SIZE) {
            buf_end = 0;
        }
        placed += to_copy;
        loops += 1;
    }
    size += placed;
    return placed;
}

size_t circ_buf_size(){
	return size;
}

size_t circ_buf_available() {
    return CIRC_BUFFER_SIZE - size;
}