// UB_CIRC.CPP
//
// Copyright (c) 1995-1999 Symbian Ltd.  All rights reserved.
//

#include "ub_std.h"

EXPORT_C CCirBufBase::CCirBufBase(TInt aSize)
//
// Constrcutor
//
	: iSize(aSize)
	{

	__ASSERT_ALWAYS(iSize>0,Panic(ECircItemSizeNegativeOrZero));
//	iCount=0;
//	iLength=0;
//	iPtr=NULL;
//	iPtrE=NULL;
//	iHead=NULL;
//	iTail=NULL;
	__DECLARE_NAME(_S("CCirBufBase"));
	}

EXPORT_C CCirBufBase::~CCirBufBase()
//
// Destrcutor
//
	{

	User::Free(iPtr);
	}

EXPORT_C void CCirBufBase::SetLengthL(TInt aLength)
//
// ReAlloc - Resets all the buffer pointers
//
	{

	__ASSERT_ALWAYS(aLength>0,Panic(ECircSetLengthNegativeOrZero));
	iPtr=(TUint8 *)User::ReAllocL(iPtr,aLength*iSize);
	iPtrE=iPtr+(aLength*iSize);
	iHead=iTail=iPtr;
	iLength=aLength;
	iCount=0;
	}

EXPORT_C void CCirBufBase::Reset()
//
// Reset the buffer to empty.
//
	{

	iHead=iTail=iPtr;
	iCount=0;
#if defined(_DEBUG)
	Mem::FillZ(iPtr,iLength*iSize);
#endif
	}

EXPORT_C TInt CCirBufBase::DoAdd(const TUint8 *aPtr)
//
// Add a single item to the buffer.
//
	{

	__ASSERT_ALWAYS(iPtr!=NULL,Panic(ECircNoBufferAllocated));
	if (iCount>=iLength)
		return(KErrNone);
	Mem::Copy(iHead,aPtr,iSize);
	iCount++;
	iHead+=iSize;
	if (iHead>=iPtrE)
		iHead=iPtr;
	return(1);
	}

EXPORT_C TInt CCirBufBase::DoAdd(const TUint8 *aPtr,TInt aCount)
//
// Add multiple items to the buffer.
//
	{

	__ASSERT_ALWAYS(iPtr!=NULL,Panic(ECircNoBufferAllocated));
	__ASSERT_ALWAYS(aCount>0,Panic(ECircAddCountNegative));
	TInt rem=iLength-iCount;
	if (rem==0)
		return(0);
	aCount=Min(aCount,rem);
	rem=(iPtrE-iHead)/iSize;
	if (aCount<=rem)
		iHead=Mem::Copy(iHead,aPtr,aCount*iSize);
	else
		{
		TInt len=(rem*iSize);
		Mem::Copy(iHead,aPtr,len);
		iHead=Mem::Copy(iPtr,aPtr+len,(aCount*iSize)-len);
		}
	if (iHead>=iPtrE)
		iHead=iPtr;
	iCount+=aCount;
	return(aCount);
	}

EXPORT_C TInt CCirBufBase::DoRemove(TUint8 *aPtr)
//
// Remove a single item from the buffer.
//
	{

	if (iCount==0)
		return(0);
	Mem::Copy(aPtr,iTail,iSize);
	iTail+=iSize;
	if (iTail>=iPtrE)
		iTail=iPtr;
	iCount--;
	return(1);
	}

EXPORT_C TInt CCirBufBase::DoRemove(TUint8 *aPtr,TInt aCount)
//
// Remove multiple items from the buffer.
//
	{

	if (iCount==0)
		return(0);
	__ASSERT_ALWAYS(aCount>0,Panic(ECircRemoveCountNegative));
	aCount=Min(aCount,iCount);
	TInt rem=(iPtrE-iTail)/iSize;
	TInt len=rem*iSize;
	if (aCount<=rem)
		{
		Mem::Copy(aPtr,iTail,aCount*iSize);
		iTail+=aCount*iSize;
		}
	else
		{
		Mem::Copy(aPtr,iTail,len);
		rem=(aCount*iSize)-len;
		Mem::Copy(aPtr+len,iPtr,rem);
		iTail=iPtr+rem;
		}
	if (iTail>=iPtrE)
		iTail=iPtr;
	iCount-=aCount;
	return(aCount);
	}

EXPORT_C CCirBuffer::CCirBuffer()
//
// Constrcutor
//
	: CCirBuf<TUint8>()
	{}

EXPORT_C CCirBuffer::~CCirBuffer()
//
// Destrcutor
//
	{
	}

EXPORT_C TInt CCirBuffer::Get()
//
// Get a single item from the buffer. Return KErrGeneral if empty.
//
	{

	if (iCount==0)
		return(KErrGeneral);
	TUint8 *p=iTail++;
	if (iTail>=iPtrE)
		iTail=iPtr;
	iCount--;
	return(*p);
	}

EXPORT_C TInt CCirBuffer::Put(TInt aVal)
//
// Put a single item to the buffer. Return KErrGeneral if full.
//
	{

	__ASSERT_ALWAYS(iPtr!=NULL,Panic(ECircNoBufferAllocated));
	if (iCount>=iLength)
		return(KErrGeneral);
	*iHead++=(TUint8)aVal;
	if (iHead>=iPtrE)
		iHead=iPtr;
	iCount++;
	return(KErrNone);
	}

