/***********************************************************************/
//文 件 名：CBuffers.cpp
//功	能：CBuffers类实现
/***********************************************************************/
#include "pch.h"
#include "Buffers.h"
#include <windows.h>

#ifdef _DEBUG
#include "stdio.h"
#include <iostream>
using namespace std;
#endif

//直接从zwl_memory中搬过来
//属于粗放型的内存管理

template<class _Tc>class template_malloc
{
#ifdef _DEBUG
	//检测用
public:
	unsigned int nItems;
#endif 
#pragma pack(push,1)	//强制本结构1字节对齐
	typedef	struct tagItem
	{
		union
		{
			tagItem*next;
			size_t size;
		};
		_Tc	data;
	}ITEM,*PITEM;
#pragma pack(pop)
public:
	char* mlloc(void)
	{
		if(!__item__) return(NULL);
		PITEM pitem = __item__;
		__item__ = __item__->next;
		pitem->size = sizeof(_Tc);
#ifdef _DEBUG
		nItems--;
#endif 
		return(pitem->data);
	}

#ifdef _DEBUG
	int getItemCount(){
		return nItems;
	}
#endif 

	void release(char*pdata)
	{
		PITEM pitem=(PITEM)pdata;
		memset(pitem,0,sizeof(ITEM));
		pitem->next = __item__;
		__item__ = pitem;

#ifdef _DEBUG
		nItems++;
#endif
	}
	void clean(void)
	{
		char*lpData=NULL;
		for(PITEM pnext=NULL;__item__;__item__=pnext)
		{
			pnext = __item__->next;
			lpData = (char*)__item__;
			delete[] lpData;
		}
	}
	template_malloc(void):__item__(NULL)
	{
#ifdef _DEBUG
		nItems = 0;
#endif 
	}
	~template_malloc(void)
	{
		clean();
	}
	PITEM	__item__;
};

#define	__malloc__(T,P)\
	else if(lsize<=T)\
{\
	lpData=P.mlloc();\
	_size = T;\
}
class memory_factory
{
public:
	char*malloc( size_t lsize, size_t* msize )
	{
		char*lpData=NULL;
		size_t _size(0);

		EnterCriticalSection(&__lock__);

		if(lsize<=16)
		{
			lpData = _alloc_16.mlloc();
			_size = 16;
		}
		__malloc__(32,_alloc_32)
		__malloc__(64,_alloc_64)
		__malloc__(128,_alloc_128)
		__malloc__(256,_alloc_256)
		__malloc__(512,_alloc_512)
		__malloc__(1024,_alloc_1k)
		__malloc__(1024*2L,_alloc_2k)
		__malloc__(1024*4L,_alloc_4k)
		__malloc__(1024*8L,_alloc_8k)
		__malloc__(1024*16L,_alloc_16k)
		__malloc__(1024*32L,_alloc_32k)
		__malloc__(1024*64L,_alloc_64k)
		__malloc__(1024*128L,_alloc_128k)
		__malloc__(1024*256L,_alloc_256k)
		__malloc__(1024*512L,_alloc_512k)
		__malloc__(1024*1024L,_alloc_1m)
		//__malloc__(2*1024*1024L,_alloc_2m)
		//__malloc__(3*1024*1024L,_alloc_3m)
		//__malloc__(4*1024*1024L,_alloc_4m)
		//__malloc__(8*1024*1024L,_alloc_8m)
		//__malloc__(16*1024*1024L,_alloc_16m)
		//__malloc__(32*1024*1024L,_alloc_32m)
		else
		{
			_size=lsize;
		}
		LeaveCriticalSection(&__lock__);
		if(!lpData)
		{
			char*lpMalloc=new char[ _size + sizeof( size_t ) ];
			if(!lpMalloc) return(NULL);
			*(size_t*)lpMalloc = _size;
			memset(lpData=lpMalloc + sizeof( size_t ), 0, _size );
		}
#ifdef _DEBUG
		else {
			nCount --;
		}
#endif
		if(msize) *msize = _size;
		return(lpData);
	}
	void release(char*lpData)
	{
		if( lpData == NULL )
			return;

		char* lpMalloc = lpData - sizeof( size_t );
		EnterCriticalSection(&__lock__);
		switch( *( size_t* )lpMalloc )
		{
		case    16:		    _alloc_16.release(lpMalloc); break;
		case    32:		    _alloc_32.release(lpMalloc); break;
		case    64:		    _alloc_64.release(lpMalloc); break;
		case    128:	    _alloc_128.release(lpMalloc); break;
		case    256:	    _alloc_256.release(lpMalloc); break;
		case	512:		_alloc_512.release(lpMalloc); break;
		case	1024:		_alloc_1k.release(lpMalloc); break;
		case	1024*2L:	_alloc_2k.release(lpMalloc); break;
		case	1024*4L:	_alloc_4k.release(lpMalloc); break;
		case	1024*8L:	_alloc_8k.release(lpMalloc); break;
		case	1024*16L:	_alloc_16k.release(lpMalloc); break;
		case	1024*32L:	_alloc_32k.release(lpMalloc); break;
		case	1024*64L:	_alloc_64k.release(lpMalloc); break;
		case	1024*128L:	_alloc_128k.release(lpMalloc); break;
		case	1024*256L:	_alloc_256k.release(lpMalloc); break;
		case	1024*512L:	_alloc_512k.release(lpMalloc); break;
		case	1024*1024L:	_alloc_1m.release(lpMalloc); break;
//		case	2*1024*1024L:	_alloc_2m.release(lpMalloc); break;
//		case	3*1024*1024L:	_alloc_3m.release(lpMalloc); break;
//		case	4*1024*1024L:	_alloc_4m.release(lpMalloc); break;
//		case	8*1024*1024L:	_alloc_8m.release(lpMalloc); break;
//		case	16*1024*1024L:	_alloc_16m.release(lpMalloc); break;
//		case	32*1024*1024L:	_alloc_32m.release(lpMalloc); break;
		default: delete[] lpMalloc;
		}
		LeaveCriticalSection(&__lock__);

#ifdef _DEBUG
		nCount ++;
#endif
	}
	void clean(void)
	{
		EnterCriticalSection(&__lock__);
		_alloc_16.clean();
		_alloc_32.clean();
		_alloc_64.clean();
		_alloc_128.clean();
		_alloc_256.clean();
		_alloc_512.clean();
		_alloc_1k.clean();
		_alloc_2k.clean();
		_alloc_4k.clean();
		_alloc_8k.clean();
		_alloc_16k.clean();
		_alloc_32k.clean();
		_alloc_64k.clean();
		_alloc_128k.clean();
		_alloc_256k.clean();
		_alloc_512k.clean();
		_alloc_1m.clean();
		_alloc_2m.clean();
		_alloc_3m.clean();
		_alloc_4m.clean();
		_alloc_8m.clean();
		_alloc_16m.clean();
		_alloc_32m.clean();

		LeaveCriticalSection(&__lock__);

	}
	memory_factory(void)
	{

		InitializeCriticalSection(&__lock__);

#ifdef _DEBUG
		nCount = 0;;
#endif
	}

	~memory_factory(void)
	{
		clean();
		DeleteCriticalSection(&__lock__);
	}

#ifdef _DEBUG
	int getItemCount(){
		return nCount;
	}
#endif 
	template_malloc<char[16]>				_alloc_16;
	template_malloc<char[32]>				_alloc_32;
	template_malloc<char[64]>				_alloc_64;
	template_malloc<char[128]>				_alloc_128;
	template_malloc<char[256]>				_alloc_256;
	template_malloc<char[512]>				_alloc_512;
	template_malloc<char[1024]>				_alloc_1k;
	template_malloc<char[1024*2L]>			_alloc_2k;
	template_malloc<char[1024*4L]>			_alloc_4k;
	template_malloc<char[1024*8L]>			_alloc_8k;
	template_malloc<char[1024*16L]>			_alloc_16k;
	template_malloc<char[1024*32L]>			_alloc_32k;
	template_malloc<char[1024*64L]>			_alloc_64k;
	template_malloc<char[1024*128L]>		_alloc_128k;
	template_malloc<char[1024*256L]>		_alloc_256k;
	template_malloc<char[1024*512L]>		_alloc_512k;
	template_malloc<char[1024*1024L]>		_alloc_1m;
	template_malloc<char[1024*1024L*2]>		_alloc_2m;
	template_malloc<char[1024*1024L*3]>		_alloc_3m;
	template_malloc<char[1024*1024L*4]>		_alloc_4m;
	template_malloc<char[1024*1024L*8]>		_alloc_8m;
	template_malloc<char[1024*1024L*16]>	_alloc_16m;
	template_malloc<char[1024*1024L*32]>	_alloc_32m;

	CRITICAL_SECTION __lock__;

#ifdef _DEBUG
	int nCount;
#endif

}__memory__;

CBuffers::CBuffers(LPVOID lpBuffer):
bufData((LPSTR)lpBuffer),sizeData(0),sizeMalloc(0)
{
	if(bufData){
		sizeMalloc = *( size_t* )( (char*)lpBuffer - sizeof( size_t ) );
	}
}

CBuffers::~CBuffers(void)
{
	if(bufData)
	{
		__memory__.release(bufData);
		bufData = 0;
	}
}
/////////////////////////////////////////////////////////////////////////////
LPSTR CBuffers::GetBuf(size_t lsize)
{
	if( ( lsize + 1 ) > sizeMalloc )
	{
		if(bufData)
		{
			__memory__.release(bufData);
			bufData = 0;
		}
		bufData=__memory__.malloc( lsize + 1, &sizeMalloc );
	}
	if( bufData && sizeMalloc )
		memset( bufData, 0, sizeMalloc );
	sizeData = lsize;
	return(bufData);
}

void CBuffers::Release(void)
{
	if(bufData)
	{
		__memory__.release(bufData);
		bufData = 0;
	}
	sizeData = sizeMalloc = 0;
}

char * CBuffers::Copy(void * lpData, size_t lsize)
{
	if(!GetBuf(lsize+1)) return(0); //避免字符串等不注意的情形，多分配一点
	if(lsize)
	{
		memcpy(bufData,lpData,lsize);
	}
	sizeData = lsize;
	return(bufData);
}

char *  CBuffers::Append(void * lpData, size_t lsize)
{
	if(lsize)
	{
		if(!Extern(sizeData+lsize+1)) return(0);
		memcpy(bufData+sizeData,lpData,lsize);
		sizeData += lsize;
	}
	return(bufData);
}

char *  CBuffers::Extern( size_t maxSize)
{
	if(maxSize>sizeMalloc)
	{
		size_t sizeNew(0);
		char * bufNew=__memory__.malloc(maxSize, &sizeNew );
		if(!bufNew) return(0);
		if(bufData)
		{
			if(sizeData) memcpy(bufNew,bufData,sizeData);
			if(bufData)
			{
				__memory__.release(bufData);
				bufData = 0;
			}
		}
		bufData = bufNew;
		sizeMalloc = sizeNew;
	}
	return(bufData);
}

CBuffers::operator const char *(void) const
{
	return(bufData);
}

const CBuffers&CBuffers::operator=(const char * lpString)
{
	Copy((void*)lpString,lstrlenA(lpString));
	return(*this);
}

const CBuffers&CBuffers::operator+=(const char * lpString)
{
	Append((void*)lpString,lstrlenA(lpString));
	return(*this);
}

void CBuffers::Attach(CBuffers*pMemory)
{
	if(bufData)
	{
		__memory__.release(bufData);
		bufData = 0;
	}
	sizeData = pMemory->sizeData;
	sizeMalloc = pMemory->sizeMalloc;
	bufData = pMemory->bufData;
	pMemory->sizeData = pMemory->sizeMalloc = 0;
	pMemory->bufData = 0;
}

void CBuffers::Detach()
{
	bufData = NULL;
}
