#include "StdAfx.h"
#include "BinaryData.h"

#pragma comment(lib, "comsuppw.lib")

//	標準拡張サイズ
#define	DEFAULT_GROW_SIZE	32768

////////////////////////////////////////////////////////////////////////////////////////
//	初期化
////////////////////////////////////////////////////////////////////////////////////////
/*!
	標準初期化
*/
CBinaryData::CBinaryData(int allocSize)
{
	SetCoreInterface(&m_core);
	ReSize(allocSize);
}

/*!
	コピー
*/
CBinaryData::CBinaryData(CBinaryData &other)
{
	SetCoreInterface(&m_core);
	ReSize(other.GetSize());

	memmove(GetPtr(), other.GetPtr(), other.GetSize());
}

/*!
	インタフェース設定
*/
CBinaryData::CBinaryData(IBinaryDataPtr other)
{
	SetCoreInterface(other);
}

/*!
	デストラクタ
*/
CBinaryData::~CBinaryData(void)
{
}


////////////////////////////////////////////////////////////////////////////////////////
//	削除
////////////////////////////////////////////////////////////////////////////////////////
/*!
	削除
*/
int CBinaryData::Remove(int start, int size)
{
	if(start < 0 || size < 0 || start + size > GetSize())
		return(-1);

	memmove(GetPtr() + start,GetPtr() + size, GetSize() - (start + size));
	ReSize(GetSize() - size);
	return(0);
}

////////////////////////////////////////////////////////////////////////////////////////
//	書き込み
////////////////////////////////////////////////////////////////////////////////////////
/*!
	上書き(必要ならば、バッファ追加)
*/
void CBinaryData::OverwriteData(int startOffset, char *data, int len)
{
	if(startOffset + len >= GetSize())
		ReSize(startOffset + len);

	memmove(GetPtr() + startOffset, data, len);
}

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

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



////////////////////////////////////////////////////////////////////////////////////////
//	変換
////////////////////////////////////////////////////////////////////////////////////////
/*!
	CStringへ
*/
CString CBinaryData::GetCString()
{
	CString ret;
	memcpy(ret.GetBuffer(GetSize()), GetPtr(), GetSize());
	ret.ReleaseBufferSetLength(GetSize());

	return(ret);
}

/*!
	UTF16->UTF8
*/
void CBinaryData::UTF16ToUTF8(_bstr_t &utf16, CBinaryData &uft8)
{
	//	UTF8へ変換
	int mbLen = WideCharToMultiByte(CP_UTF8, 0, utf16.GetBSTR(), utf16.length(), NULL, 0, NULL, NULL);

	uft8.ReSize(mbLen);
	WideCharToMultiByte(CP_UTF8, 0, utf16.GetBSTR(), utf16.length(), uft8.GetPtr(), uft8.GetSize(), NULL, NULL);
}

/*!
	UTF8->UTF16
*/
void CBinaryData::UTF8ToUTF16(CBinaryData &uft8, _bstr_t &utf16)
{
	int mbLen = MultiByteToWideChar(CP_UTF8, 0, uft8.GetPtr(), uft8.GetSize(), NULL,0);

	wchar_t	*wstr = new wchar_t[mbLen + 1];
	MultiByteToWideChar(CP_UTF8, 0, uft8.GetPtr(), uft8.GetSize(), wstr, mbLen);
	wstr[mbLen] = 0;

	utf16 = wstr;
}

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

	\param path		パス
*/
int CBinaryData::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 CBinaryData::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);
}


////////////////////////////////////////////////////////////////////////////////////////
//	CBinaryDataCore
////////////////////////////////////////////////////////////////////////////////////////
CBinaryData::CBinaryDataCore::CBinaryDataCore()
{
	InitInternal();
}

CBinaryData::CBinaryDataCore::~CBinaryDataCore()
{
	if(m_buffer)
		delete m_buffer;
	InitInternal();
}

/*!
	サイズ変更
*/
void CBinaryData::CBinaryDataCore::ReSize(int size)
{
	//	クリア
	if(size == 0)
	{
		if(m_buffer)
			delete m_buffer;
		m_buffer = NULL;
		m_bufferSize = 0;
		m_usingSize = 0;
		return;
	}

	//	確保
	if(m_buffer == NULL || size > m_bufferSize)
	{
		int allocSize = (size / m_growSize + 1) * m_growSize;
		char *temp = new char[allocSize];
		int	transSize = m_bufferSize;

		//	転送
		if(m_buffer != NULL)
		{
			if(m_bufferSize > size)
				transSize = size;

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

		//	設定
		m_buffer = temp;
		m_bufferSize = allocSize;
	}
	m_usingSize = size;
}

/*!
	サイズ取得
*/
int CBinaryData::CBinaryDataCore::GetSize()
{
	return m_usingSize;
}

/*!
	保持しているデータポインタを取得
*/
char *CBinaryData::CBinaryDataCore::GetPtr()
{
	return m_buffer;
}

/*!
	内部初期化
*/
void CBinaryData::CBinaryDataCore::InitInternal()
{
	m_buffer = NULL;
	m_bufferSize = 0;
	m_usingSize = 0;
	SetGrowSize(DEFAULT_GROW_SIZE);
}
