/*
 * File:   ring_buf.c
 *
 * Ring Buffer Library
 *
 * Cheng Xing, Rene Zhang
 * cx34, rz99
 * December 2015
 */

#include <stdlib.h>
#include "ring_buf.h"

struct ring_buf {
  out_t* data;
  unsigned int size;
  unsigned int start;
  unsigned int end;
};

ring_buf_t ring_new(unsigned int size) {
  ring_buf_t ring = (ring_buf_t) malloc(sizeof(struct ring_buf));
  ring->data = (out_t*) malloc(sizeof(out_t) * (size + 1));

  ring->size = (size + 1);
  ring->start = 0;
  ring->end = 0;

  return ring;
}

void ring_free(ring_buf_t ring) {
  free(ring->data);
  free(ring);
}

unsigned int ring_empty(ring_buf_t ring) {
  return (ring->start == ring->end);
}

unsigned int ring_size(ring_buf_t ring) {
  return (ring->size + ring->end - ring->start) % (ring->size);
}

unsigned int ring_max_size(ring_buf_t ring) {
  return (ring->size - 1);
}

void ring_push(ring_buf_t ring, out_t data) {
  ring->data[ring->end] = data;
  ring->end = (ring->end + 1) % (ring->size);
  if (ring->start == ring->end) {
    ring->start = (ring->start + 1) % (ring->size);
  }
}

out_t ring_pop(ring_buf_t ring) {
  if (ring->start != ring->end) { // Nonzero size
    out_t temp = ring->data[ring->start];
    ring->start = (ring->start + 1) % (ring->size);
    return temp;
  }
  return 0;
}
