// Buffer.cpp: CBuffer クラスのインプリメンテーション
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Buffer.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

#define	GROW_SIZE	32768

//////////////////////////////////////////////////////////////////////
// 構築/消滅
//////////////////////////////////////////////////////////////////////

CBuffer::CBuffer(int size)
{
	Init();
	Alloc(size);
}

CBuffer::CBuffer(CBuffer &other)
{
	Init();
	Alloc(other.GetSize());
	memmove(m_buffer,other.GetPtr(),other.GetSize());
}

CBuffer::~CBuffer()
{
	delete m_buffer;
	Init();
}

//	初期化
void CBuffer::Init()
{
	m_buffer = NULL;
	m_bufferSize = 0;
	m_usingSize = 0;
	SetGrowSize(GROW_SIZE);
}


//	確保
void CBuffer::Alloc(int size)
{
	if(size > m_bufferSize)
	{
		unsigned char *temp = new unsigned char[size + m_growSize];
		int	transSize = m_bufferSize;

		if(m_buffer)
		{
			if(m_bufferSize > size)
				transSize = size;

			memmove(temp,m_buffer,transSize);
			delete m_buffer;
		}

		m_buffer = temp;
		m_bufferSize = size + m_growSize;
		m_usingSize = size;
	}
}


//////////////////////////////////////////////////////////////////////
// 追加
//////////////////////////////////////////////////////////////////////
void CBuffer::Append(char *data, int size)
{
	int	oldSize = GetSize();
	ReSize(size + oldSize);

	memmove(GetPtr() + oldSize,data,size);	
}


//////////////////////////////////////////////////////////////////////
// サイズ変更
//////////////////////////////////////////////////////////////////////
void CBuffer::ReSize(int size)
{
	if(size > m_bufferSize)
	{
		Alloc(size);
	}
	m_usingSize = size;
}

//////////////////////////////////////////////////////////////////////
// 削除
//////////////////////////////////////////////////////////////////////
void CBuffer::Remove(int start,int size)
{
	if(start < 0 || size < 0 || start + size > m_usingSize)
		return;

	memmove(GetPtr() + start,GetPtr() + size,m_usingSize - (start + size));
	m_usingSize = m_usingSize - size;
}

//////////////////////////////////////////////////////////////////////
// 取得
//////////////////////////////////////////////////////////////////////
char * CBuffer::GetPtr()
{
	return((char *)m_buffer);
}

CBuffer::operator char*()
{
	return((char *)m_buffer);
}

CBuffer::operator CString()
{
	CString ret;
	char * buf = ret.GetBuffer(m_usingSize + 1);
	memcpy(buf,m_buffer,m_usingSize);
	buf[m_usingSize] = 0;
	ret.ReleaseBuffer();

	return(ret);
}

CBuffer::operator unsigned char*()
{
	return(m_buffer);
}

int CBuffer::GetSize()
{
	return(m_usingSize);
}

void CBuffer::operator =(CString other)
{
	ReSize(other.GetLength());
	memmove(m_buffer,other.GetBuffer(0),m_usingSize);
}

void CBuffer::operator =(CBuffer &other)
{
	ReSize(other.GetSize());
	memmove(m_buffer,other.GetPtr(),m_usingSize);
}

void CBuffer::operator +=(CString other)
{
	Append(other.GetBuffer(0),other.GetLength());
}

void CBuffer::operator +=(CBuffer &other)
{
	Append(other.GetPtr(),other.GetSize());
}

void CBuffer::operator +=(char *other)
{
	int	len = (int)strlen(other);
	Append(other,len);
}

void CBuffer::operator +=(char other)
{
	Append(&other,1);
}


//////////////////////////////////////////////////////////////////////
// データコピー
//////////////////////////////////////////////////////////////////////
void CBuffer::BlockCopy(int offset, char *data, int len)
{
	if(offset + len >= m_usingSize)
		ReSize(offset + len);
	memmove(m_buffer + offset,data,len);
}

//////////////////////////////////////////////////////////////////////
// 設定
//////////////////////////////////////////////////////////////////////
void CBuffer::SetGrowSize(int size)
{
	m_growSize = size;
}

//////////////////////////////////////////////////////////////////////
// 保存
//////////////////////////////////////////////////////////////////////
/*!
	ファイルへ保存

	\param path		パス
*/
int CBuffer::SaveToFile(CString path)
{
	FILE	*out;
	if(fopen_s(&out ,path,"wb") != 0)
		return(-1);

	fwrite(GetPtr(),GetSize(),1,out);
	fclose(out);
	return(0);
}

/*!
	ファイルから読み出し

	\param path		パス
*/
int CBuffer::LoadFromFile(CString path)
{
	FILE	*out;
	if(fopen_s(&out ,path,"rb") != 0)
		return(-1);
	
	fseek(out,0,SEEK_END);
	long	len = ftell(out);
	fseek(out,0,SEEK_SET);

	ReSize(len);
	fread(GetPtr(),GetSize(),1,out);
	fclose(out);
	return(0);
}