/*
 * CircularQueue.c
 * 
 * Simple circular queue used to buffer incoming messages from the Gocator.
 *
 * Copyright (C) 2014 by LMI Technologies Inc.
 * 
 * Licensed under The MIT License.
 * Redistributions of files must retain the above copyright notice.
 *
 */

#include "CircularQueue.h"

struct CircularQueue* CircularQueue_Construct(int size) 
{
   struct CircularQueue* q = malloc(sizeof(struct CircularQueue));
   
   if (!q) return NULL;
   q->capacity = size;
   q->front = -1;
   q->rear = -1;
   q->buffer = malloc(q->capacity * sizeof(void*));
   if (!q->buffer) return NULL;

  return q;
}

void CircularQueue_Destroy(struct CircularQueue* q) 
{
	if (q->buffer != NULL) free(q->buffer);
	if (q != NULL) free(q);
}

int CircularQueue_IsEmpty(struct CircularQueue* q) 
{
   return (q->front == -1);
}

int CircularQueue_IsFull(struct CircularQueue* q) 
{
   return (((q->rear + 1) % q->capacity) == q->rear);
}

int CircularQueue_Size(struct CircularQueue* q) 
{
   return (q->capacity - q->rear + q->front + 1) % q->capacity;
}

void CircularQueue_Add(struct CircularQueue* q, void* item) 
{
   if (CircularQueue_IsFull(q))
   {
	   printf("CircularQueue_Add: Overflow!\n");
   }
   else
   {
      q->rear = (q->rear + 1) % q->capacity;
      q->buffer[q->rear] = item;
      if (q->front == -1) 
	  {
         q->front = q->rear;
      }
   }
}

void* CircularQueue_Remove(struct CircularQueue* q) 
{
   void* data = NULL;

   if (CircularQueue_IsEmpty(q)) 
   {
      printf("CircularQueue_Remove: Empty Queue!");
      return NULL;
   }
   else 
   {
      data = q->buffer[q->front];
      if(q->front == q->rear)
         q->front=q->rear = -1;
      else
         q->front = (q->front + 1) % q->capacity;
   }

   return data;
}

void* CircularQueue_Peek(struct CircularQueue* q) 
{
   void* data = NULL;

   if (CircularQueue_IsEmpty(q)) 
   {
      printf("CircularQueue_Peek: Empty Queue!");
      return NULL;
   }
   else 
   {
      data = q->buffer[q->front];
   }

   return data;
}
