#pragma once
//关键段
class CSimpleCriticalSection {
private:
	CRITICAL_SECTION FSection;
public:
	CSimpleCriticalSection(){InitializeCriticalSection(&FSection);}
	virtual ~CSimpleCriticalSection(){DeleteCriticalSection(&FSection);}
	void Enter(){EnterCriticalSection(&FSection);}
	void Leave(){LeaveCriticalSection(&FSection);}
};
//循环缓冲区类
class CBufferLoop {
private:
	int FSize;  						//缓冲区大小
	int FStart; 						//有效数据头
	int FEnd;   						//有效数据尾
	int FLength;						//有效数据长度
	BYTE* FBuffer;						//缓冲区地址
protected:
		CSimpleCriticalSection* cs;
protected:
	INT16 Append(const unsigned char* Src, const UINT32 alen)
	{
		INT16 len = (alen > (UINT32) FSize) ? FSize : (INT16) alen;
		//assert(len > 0);
		//缓存剩余空间不够Length
		if ((len + FLength) >= FSize)
			len = FSize - FLength;
		if ((len + FEnd) >= FSize) {
			//缓存内数据块后部空间不够Length,将数据块移到缓存首地址
			memcpy(FBuffer, FBuffer + FStart, FLength);
			FStart = 0;
			FEnd = FLength;
		}
		memcpy(FBuffer + FEnd, Src, len);
		FEnd += len;
		FLength += len;
		return len;
	}
	void Drop(const int len)
	{
		//assert(len > 0);
		if (len > FLength) {
			FStart = 0;
			FEnd = 0;
			FLength = 0;
		} else {
			FStart += len;
			FLength -= len;
		}
	}
	int Size(){return FSize;}
	int Length(){return FLength;}
public:
	CBufferLoop() : FSize(512), FStart(0), FEnd(0), FLength(0), FBuffer(0),cs(new CSimpleCriticalSection())
	{
		FBuffer = new unsigned char[FSize];
		memset(FBuffer, 0, FSize);
	};
	CBufferLoop(const CBufferLoop& abl)
		: FSize(abl.FSize), FStart(abl.FStart), FEnd(abl.FEnd),
		FLength(abl.FLength), FBuffer(0)
	{
		FBuffer = new unsigned char[FSize];
		memcpy(FBuffer, abl.FBuffer, FSize);
	}
	virtual ~CBufferLoop(){

		delete[] FBuffer;
		FBuffer = 0;
		//by CYH 不注释会报错,原因未知
		//delete cs;

	}
	CBufferLoop& operator=(const CBufferLoop& abl)
	{
		if (this == &abl)
			return *this;   				 // 见条款17
		if (FBuffer)
			delete[] FBuffer;
		FSize = abl.FSize;
		FStart = abl.FStart;
		FEnd = abl.FEnd;
		FLength = abl.FLength;
		FBuffer = new unsigned char[FSize];
		memcpy(FBuffer, abl.FBuffer, FSize);
		return *this;
	}
	BYTE* const Addr()	{return FBuffer + FStart;}
	void Reset()
	{
		memset(FBuffer, 0, FSize);
		FStart = 0;
		FEnd = 0;
		FLength = 0;
	}
	//重新申请缓冲区
	void CBufferLoop::AllocMemory(int len)
	{
		if ( (len > FSize) && (FSize >= 0) && (len < 64 * 1024 * 1024) )
		{
			unsigned char *temp = new unsigned char[len];
			if(temp != NULL)
			{
				if (FBuffer != 0)
				{
					if (FLength > 0)
					{
#ifndef __MSDOS__
						cs->Enter();
#endif
						memcpy((void*)temp, (void*)(FBuffer + FStart), (unsigned int)FLength);
						FSize = len;
						FStart = 0;
						FEnd = FLength;
#ifndef __MSDOS__
						cs->Leave();
#endif
					}
					else
					{
						FSize = len;
						FStart = 0;
						FEnd = 0;
						FLength = 0;
					}
					delete[] FBuffer;
				}
				FBuffer = temp;
			}
		}
	}
};