Skip to content
Snippets Groups Projects
circ_buffer.c 1.87 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; })


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


struct data_chunk getChunk() {
    size_t chunk_end = buf_end;
    if (buf_end < buf_start) {
        chunk_end = CIRC_BUFFER_SIZE;
    }
    size_t ret_size = 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;
    while (placed < will_place) {
        // 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 (buf_end > CIRC_BUFFER_SIZE) {
            printf("Error: buf_end: %d\n", buf_end);
        }
        // If we copied to the end
        if (buf_end == CIRC_BUFFER_SIZE) {
            buf_end = 0;
        }
        placed += to_copy;
    }
    size += placed;
    return placed;
}

size_t get_buffer_size() {
    return size;
}