/*
 * =====================================================================================
 *
 *       Filename:  circularQueue.c
 *
 *    Description:  Implement functions of circular queue
 *
 *        Version:  1.0
 *        Created:  08/12/2016 09:48:39 AM
 *       Compiler:  armcc
 *
 *         Author:  Dongwook Shim (), dw.shim@samsung.com
 *        Company:  Samsung Electronics
 *
 *        Copyright (c) 2016 by Samsung Electronics, All rights reserved. 
 *
 * =====================================================================================
 */

#include "circularQueue.h"

#define INCREASE_POS(x)		(((x + 1) % QUEUE_MAX_NUM) != 0 ) ? (x++) : (x = 0)

static char gCircularQueue[QUEUE_MAX_NUM][QUEUE_MAX_SIZE];	// 64KB.
static uint32_t gFront = 0, gRear = 0;

bool isQueueEmpty(void)
{
	if(gFront == gRear)
		return true;
	else
		return false;
}

bool isQueueFull(void)
{
	if(gFront == ((gRear + 1) % QUEUE_MAX_NUM))
		return true;
	else
		return false;
}

int getQueueSize(void)
{
	int i, size = 0;

	for(i = 0; i < QUEUE_MAX_NUM; i++)
		size += strlen(gCircularQueue[i]);

	return size;
}

int enqueueData(char *data, uint32_t dataLen)
{
	int writtenLen = (dataLen < QUEUE_MAX_SIZE - 2) ? dataLen : QUEUE_MAX_SIZE - 2;	// 0x0A, 0x00.

	if(data == NULL)
		return 0;

	if(isQueueFull())
	{
		memset(gCircularQueue[gFront], 0, sizeof(gCircularQueue[gFront]));
		INCREASE_POS(gFront);
	}

	memset(gCircularQueue[gRear], 0, sizeof(gCircularQueue[gRear]));
	memcpy(gCircularQueue[gRear], data, writtenLen);
	gCircularQueue[gRear][writtenLen] = '\n';

	INCREASE_POS(gRear);

	return writtenLen;
}

int dequeueData(char *data, uint32_t dataLen)
{
	int readMaxLen = (dataLen < QUEUE_MAX_SIZE) ? dataLen : QUEUE_MAX_SIZE;
	int strLen = 0, copyLen = 0;

	if(data == NULL)
		return 0;

	if(!isQueueEmpty())
	{
		memset(data, 0, readMaxLen);
		strLen = strlen(gCircularQueue[gFront]);
		copyLen = (strLen < readMaxLen) ? strLen : readMaxLen;
		memcpy(data, gCircularQueue[gFront], copyLen);
		memset(gCircularQueue[gFront], 0, sizeof(gCircularQueue[gFront]));
		INCREASE_POS(gFront);

		return copyLen;
	}
	else
		return 0;
}
