#include "StdAfx.h"
#include ".\texttools.h"
#include <comutil.h>

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

CString CTextTools::GetFormat(LPCTSTR lpszFormat, ...)
{
	va_list argList;
	CString	str;
	va_start(argList, lpszFormat);
	str.FormatV(lpszFormat,argList);
	va_end(argList);

	return str;
}


__int64 CTextTools::strtoi64(CString str,int base)
{
	char	*err;
	return _strtoi64(str,&err,base);
}



//////////////////////////////////////////////////////////////////////
// ライン切り出し
//////////////////////////////////////////////////////////////////////
int CTextTools::GetLine(CString &str, CString &line)
{
	int index = str.Find("\r\n");

	if(index == -1)
	{
		if(str.IsEmpty())
			return(0);

		line = str;
		str.Empty();
		return(1);
	}
	
	//	切り出し
	line = str.Left(index);

	//	削除
	str = str.Mid(index + 2);
	return(1);
}

//////////////////////////////////////////////////////////////////////
// トークン切り出し
//////////////////////////////////////////////////////////////////////
int CTextTools::GetToken(CString &str, CString &token, CString div, int trim)
{
	int tlen = div.GetLength();
	int index = str.Find(div);

	if(index == -1)
	{
		if(str.IsEmpty())
			return(0);

		token = str;
		if(trim)
			token.Trim();
		str.Empty();
		return(1);
	}
	
	//	切り出し
	token = str.Left(index);
	if(trim)
		token.Trim();

	//	削除
	str = str.Mid(index + tlen);
	return(1);
}


/*!
	トークン全て切り出し
*/
void CTextTools::GetAllToken(CString str, CStringArray &tokens, CString div, int trim)
{
	tokens.RemoveAll();

	CString token;
	while(GetToken(str, token, div))
		tokens.Add(token);
}


//////////////////////////////////////////////////////////////
//	ワイルドカード比較
//////////////////////////////////////////////////////////////
/*!
	ワイルドカードで比較

	\return TRUE->一致
*/
int CTextTools::WildCompare(CString wild, CString str)
{
	//	前処理
	wild.MakeLower();
	str.MakeLower();

	return(StrMatch(wild, str));
}

/*!
	下請け
*/
int CTextTools::StrMatch( const char *Ptn, const char *Str )
{
	switch( *Ptn )
	{
		case '\0':
			return (*Str=='\0');
		case '*':
			return StrMatch( Ptn+1, Str ) || (*Str!='\0') && StrMatch( Ptn, Str+1 );
		case '?':
			return (*Str!='\0') && StrMatch( Ptn+1, Str+1 );
		default:
			return ((unsigned char)*Ptn==(unsigned char)*Str) && StrMatch( Ptn+1, Str+1 );
	}
}


//////////////////////////////////////////////////////////////
//	文字列配列処理
//////////////////////////////////////////////////////////////
/*!
	配列から文字列を検索
*/
int CTextTools::FindStrIndex(CStringArray &list, CString find, int noCase)
{
	for(int i=0;i<list.GetSize();i++)
	{
		if(noCase)
		{
			if(list[i].CompareNoCase(find) == 0)
				return(i);
		}
		else
		{
			if(list[i] == find)
				return(i);
		}
	}

	return(-1);
}

//////////////////////////////////////////////////////////////
//	文字列変換
//////////////////////////////////////////////////////////////
/*!
	Unicodeから、ANSI文字列へ
*/
CStringA CTextTools::WideStrToMultiStr(const wchar_t *str)
{
	CStringA	ret;
	ret = (char *)_bstr_t(str);

	return(ret);
}

/*!
	ANSIから、Unicode文字列へ
*/
CStringW CTextTools::MultiStrToWideStr(const char *str)
{
	CStringW	ret;
	ret = str;

	return(ret);
}

/*!
	ANSIからUTF8へ
*/
CStringA CTextTools::ANSIToUTF8Str(const char *str)
{
	//	UTF16へ変換
	CStringW			utf16(str);

	//	UTF8へ変換
	int mbLen = WideCharToMultiByte(CP_UTF8, 0, utf16.GetBuffer(0), utf16.GetLength(), NULL, 0, NULL, NULL);
	CStringA	utf8;
	WideCharToMultiByte(CP_UTF8, 0, utf16.GetBuffer(0), utf16.GetLength(), utf8.GetBuffer(mbLen + 1), mbLen, NULL, NULL);
	utf8.ReleaseBufferSetLength(mbLen);

	return(utf8);
}

/*!
	UTF8からANSIへ
*/
CStringA CTextTools::UTF8ToANSIStr(const char *str)
{
	//	変換
	CStringW	utf16;
	int wbLen = MultiByteToWideChar(CP_UTF8, 0, str, (int)strlen(str), NULL, 0);
	MultiByteToWideChar(CP_UTF8, 0, str, (int)strlen(str), utf16.GetBuffer(wbLen), wbLen);
	utf16.ReleaseBufferSetLength(wbLen);

	return(CStringA(utf16));
}

/*!
	UnicodeからUTF8へ
*/
CStringA CTextTools::WideStrToUTF8Str(const wchar_t *str)
{
	//	UTF16
	CStringW			utf16(str);

	//	UTF8へ変換
	int mbLen = WideCharToMultiByte(CP_UTF8, 0, utf16.GetBuffer(0), utf16.GetLength(), NULL, 0, NULL, NULL);
	CStringA	utf8;
	WideCharToMultiByte(CP_UTF8, 0, utf16.GetBuffer(0), utf16.GetLength(), utf8.GetBuffer(mbLen + 1), mbLen, NULL, NULL);
	utf8.ReleaseBufferSetLength(mbLen);

	return(utf8);
}

/*!
	文字列をUTF8へ
*/
CStringA CTextTools::StrToUTF8(CString str)
{
#ifdef _UNICODE
	return WideStrToUTF8Str(str);
#else
	return ANSIToUTF8Str(str);
#endif
}



///////////////////////////////////////////////////////////////////////////
//	文字列のエスケープ
///////////////////////////////////////////////////////////////////////////
/*!
	エスケープの実行
*/
CString CTextEscape::Escape(CString src)
{
	CString	ret;

	int	curPos = 0;
	while(1)
	{
		int	findIndex;
		int itemIndex = MultiFind(curPos, findIndex, src, m_escape);

		if(itemIndex != -1)
		{
			//	切り出し
			if(findIndex > curPos)
				ret += src.Mid(curPos, findIndex - curPos);

			//	置き換え
			ret += m_escape[itemIndex].m_escape;
			curPos = findIndex + m_escape[itemIndex].m_token.GetLength();
		}
		else
		{
			return(ret + src.Mid(curPos));
		}
	}
}

/*!
	エスケープの解除
*/
CString CTextEscape::UnEscape(CString escaped)
{
	CString	ret;

	int	curPos = 0;
	while(1)
	{
		int	findIndex;
		int itemIndex = MultiFind(curPos, findIndex, escaped, m_unescape);

		if(itemIndex != -1)
		{
			//	切り出し
			if(findIndex > curPos)
				ret += escaped.Mid(curPos, findIndex - curPos);

			//	置き換え
			ret += m_unescape[itemIndex].m_escape;
			curPos = findIndex + m_unescape[itemIndex].m_token.GetLength();
		}
		else
		{
			return(ret + escaped.Mid(curPos));
		}
	}
}

/*!
	追加
*/
void CTextEscape::AddEscape(CString token, CString escape)
{
	m_escape.Add(CTextEscapeItem(token, escape));
	m_unescape.Add(CTextEscapeItem(escape, token));
}

/*!
	クリア
*/
void CTextEscape::Clear()
{
	m_escape.RemoveAll();
	m_unescape.RemoveAll();
}


/*!
	一番最初に見つかったインデックスを取得
*/
int CTextEscape::MultiFind(int startIndex, int &findIndex, CString &src, CArray<CTextEscapeItem> &items)
{
	findIndex = src.GetLength() + 1;
	int	itemIndex = -1;
	for(int i=0;i<items.GetCount();i++)
	{
		int index = src.Find(items[i].m_token, startIndex);
		if(index != -1)
		{
			if(itemIndex == -1 || findIndex > index)
			{
				itemIndex = i;
				findIndex = index;
			}
		}
	}

	return(itemIndex);
}
