#include "Mix/String.h"

namespace Mix{

/////////////////////////////////////////////////////////////////////////////////////////////////////////
// StringW 文字列クラス( ユニコード )
/////////////////////////////////////////////////////////////////////////////////////////////////////////

wchar_t StringW::empty = 0;

StringW::StringW( void ) :
m_pStr( NULL ),
m_Num( 0 ),
m_Size( 0 ),
m_AllocateSize( 0 ),
m_Capacity( 0 )
{
}

StringW::StringW( const char* pStr ) :
m_pStr( NULL ),
m_Num( 0 ),
m_Size( 0 ),
m_AllocateSize( 0 ),
m_Capacity( 0 )
{
	Convert( pStr );
}

StringW::StringW( const wchar_t* pStr ) :
m_pStr( NULL ),
m_Num( 0 ),
m_Size( 0 ),
m_AllocateSize( 0 ),
m_Capacity( 0 )
{
	Copy( pStr );
}

StringW::StringW( const wchar_t* pStr, UIntT SizeInWords ) :
m_pStr( NULL ),
m_Num( 0 ),
m_Size( 0 ),
m_AllocateSize( 0 ),
m_Capacity( 0 )
{
	Copy( pStr, SizeInWords );
}

StringW::StringW( const StringW& Str ) :
m_pStr( NULL ),
m_Num( 0 ),
m_Size( 0 ),
m_AllocateSize( 0 ),
m_Capacity( 0 )
{
	Copy( Str.m_pStr );
}

StringW::~StringW( void )
{
	if( m_pStr != NULL )
	{
		MIX_LIB_FREE( m_pStr );
		m_pStr = NULL;
	}
}

void StringW::Allocate( UIntT num )
{
	MIX_ASSERT( num >= 0 );

	UIntT size = num * 2;
	UIntT allocSize = size + 2;

	if( m_pStr == NULL )
	{
		m_pStr = static_cast<wchar_t*>( MIX_LIB_MALLOC( Mix::Memory::SECTION_GENERAL, allocSize ) );
		MIX_ASSERT( m_pStr != NULL );

		m_Capacity = allocSize;
	}
	else
	{
		if( m_Capacity < allocSize )
		{
			void* pTemp = MIX_LIB_REALLOC( m_pStr, allocSize );
			MIX_ASSERT( pTemp != NULL );

			m_pStr = static_cast<wchar_t*>( pTemp );
			m_Capacity = allocSize;
		}
	}

	m_Num = num;
	m_Size = size;
	m_AllocateSize = allocSize;
}

void StringW::Copy( const wchar_t* pStr )
{
	Copy( pStr, ( pStr == NULL )? ( 0 ) : ( wcslen( pStr ) ) );
}

void StringW::Copy( const wchar_t* pStr, UIntT num )
{
	Allocate( num );

	if( m_Size > 0 )
	{
		Mix::Memory::Copy( m_pStr, pStr, m_Size );
	}

	m_pStr[m_Num] = L'\0';
}

void StringW::Convert( const char* pStr )
{
	//変換後の長さを取得
	Int32 length = MultiByteToWideChar( CP_ACP, 0, pStr, -1, NULL, 0 );

	if( length > 0 )
	{
		//リサイズ
		Allocate( length - 1 );

		//変換
		if( MultiByteToWideChar( CP_ACP, 0, pStr, static_cast<Int32>( strlen( pStr ) ), m_pStr, static_cast<Int32>( m_Num ) ) > 0 )
		{
			m_pStr[m_Num] = L'\0';
		}
	}
}

void StringW::Add( const wchar_t* pStr )
{
	if( pStr == NULL )
	{
		return;
	}

	UIntT oldNum = m_Num;
	UIntT addNum = wcslen( pStr );
	UIntT addSize = addNum * 2;

	Allocate( oldNum + addNum );

	Mix::Memory::Copy( m_pStr + oldNum, pStr, addSize );
	m_pStr[m_Num] = L'\0';
}

wchar_t& StringW::operator [] ( UIntT index )
{
	MIX_ASSERT( m_pStr != NULL );
	MIX_ASSERT( m_Num > index );

	return m_pStr[index];
}

Boolean StringW::operator == ( const StringW& Str ) const
{
	if( ( m_pStr == NULL ) && ( Str.m_pStr == NULL ) )
	{
		return False;
	}
	else if( ( m_pStr == NULL ) || ( Str.m_pStr == NULL ) )
	{
		return True;
	}

	return ( wcscmp( m_pStr, Str.m_pStr ) == 0 );
}

Boolean StringW::operator == ( const wchar_t* pStr ) const
{
	if( ( m_pStr == NULL ) && ( pStr == NULL ) )
	{
		return True;
	}
	else if( ( m_pStr == NULL ) || ( pStr == NULL ) )
	{
		return False;
	}

	return ( wcscmp( m_pStr, pStr ) == 0 );
}

Boolean StringW::operator == ( wchar_t code ) const
{
	if( m_pStr == NULL )
	{
		return False;
	}

	if( m_pStr[0] == code )
	{
		return True;
	}

	return False;
}

Boolean StringW::operator == ( UIntT NullValue ) const
{
	return ( m_pStr == NULL );
}

Boolean StringW::operator != ( const StringW& str ) const
{
	if( ( m_pStr == NULL ) && ( str.m_pStr == NULL ) )
	{
		return False;
	}
	else if( ( m_pStr == NULL ) || ( str.m_pStr == NULL ) )
	{
		return True;
	}

	return ( wcscmp( m_pStr, str.m_pStr ) != 0 );
}

Boolean StringW::operator != ( const wchar_t* pStr ) const
{
	if( ( m_pStr == NULL ) && ( pStr == NULL ) )
	{
		return False;
	}
	else if( ( m_pStr == NULL ) || ( pStr == NULL ) )
	{
		return True;
	}

	return ( wcscmp( m_pStr, pStr ) != 0 );
}

Boolean StringW::operator != ( UIntT NullValue ) const
{
	return ( m_pStr != NULL );
}

StringW& StringW::operator = ( const StringW& str )
{
	Copy( str.m_pStr );

	return *this;
}

StringW& StringW::operator = ( const wchar_t* pStr )
{
	Copy( pStr );

	return *this;
}

StringW& StringW::operator = ( const char* pStr )
{
	Convert( pStr );

	return *this;
}

StringW& StringW::operator = ( const wchar_t code )
{
	wchar_t tmp[2] = { code, L'\0' };

	Copy( tmp );

	return *this;
}

StringW& StringW::operator = ( UIntT nullValue )
{
#if 1
	Allocate( 0 );
#else
	Release();
#endif

	return *this;
}

StringW& StringW::operator += ( const wchar_t* pStr )
{
	Add( pStr );

	return *this;
}

StringW& StringW::operator += ( const StringW& Str )
{
	Add( Str.m_pStr );

	return *this;
}

StringW& StringW::operator += ( const wchar_t code )
{
	wchar_t tmp[2] = { code, L'\0' };

	Add( tmp );

	return *this;
}

StringW StringW::operator + ( const StringW& Str )
{
	StringW tempStr( m_pStr );

	tempStr.Add( Str.m_pStr );

	return tempStr;
}

Float64 StringW::ToDouble( Boolean* pbRet ) const
{
	if( m_pStr == NULL )
	{
		if( pbRet != NULL )
		{
			*pbRet = False;
		}

		return 0.0;
	}

	wchar_t* pStopString = NULL;
	Float64 retValue = wcstod( m_pStr, &pStopString );

	if( *pStopString != 0 )
	{
		if( pbRet != NULL )
		{
			*pbRet = False;
		}
		return 0.0;
	}

	if( pbRet != NULL )
	{
		*pbRet = True;
	}

	return retValue;
}

Float32 StringW::ToFloat( Boolean* pbRet ) const
{
	if( m_pStr == NULL )
	{
		if( pbRet != NULL )
		{
			*pbRet = False;
		}
		return 0.0f;
	}

	wchar_t* pStopString = NULL;
	Float32 retValue = static_cast<Float32>( wcstod( m_pStr, &pStopString ) );

	if( *pStopString != 0 )
	{
		if( pbRet != NULL )
		{
			*pbRet = False;
		}

		return 0.0f;
	}

	if( pbRet != NULL )
	{
		*pbRet = True;
	}

	return retValue;
}

Int32 StringW::ToInt( Boolean* pbRet ) const
{
	if( m_pStr == NULL )
	{
		if( pbRet != NULL )
		{
			*pbRet = False;
		}
		return 0;
	}

	wchar_t* pStopString = NULL;
	Int32 retValue = static_cast<Int32>( wcstol( m_pStr, &pStopString, 0 ) );

	if( *pStopString != 0 )
	{
		if( pbRet != NULL )
		{
			*pbRet = False;
		}

		return 0;
	}

	if( pbRet != NULL )
	{
		*pbRet = True;
	}

	return retValue;
}

UInt32 StringW::ToUInt( Boolean* pbRet ) const
{
	if( m_pStr == NULL )
	{
		if( pbRet != NULL )
		{
			*pbRet = False;
		}
		return 0;
	}

	wchar_t* pStopString = NULL;
	UInt32 retValue = static_cast<UInt32>( wcstoul( m_pStr, &pStopString, 0 ) );

	if( *pStopString != 0 )
	{
		if( pbRet != NULL )
		{
			*pbRet = False;
		}

		return 0;
	}

	if( pbRet != NULL )
	{
		*pbRet = True;
	}

	return retValue;
}

StringW StringW::ToUpper( void )
{
	Mix::StringW temp = *this;

	temp.Upper();

	return temp;
}

StringW StringW::ToLower( void )
{
	Mix::StringW temp = *this;

	temp.Lower();

	return temp;
}

void StringW::Upper( void )
{
	if( m_pStr != NULL )
	{
		wchar_t* pc = &( m_pStr[0] );

		while( *pc != L'\0' )
		{
			// A〜Z( 0x0041〜0x005A )
			// a〜z( 0x0061〜0x007A )
			if( ( *pc >= 0x0061 ) &&
				( *pc <= 0x007A ) )
			{
				*pc = *pc - 0x0061 + 0x0041;
			}

			pc++;
		}
	}
}

void StringW::Lower( void )
{
	if( m_pStr != NULL )
	{
		wchar_t* pc = &( m_pStr[0] );

		while( *pc != L'\0' )
		{
			// A〜Z( 0x0041〜0x005A )
			// a〜z( 0x0061〜0x007A )
			if( ( *pc >= 0x0041 ) &&
				( *pc <= 0x005A ) )
			{
				*pc = *pc - 0x0041 + 0x0061;
			}

			pc++;
		}
	}
}

wchar_t* StringW::Sprintf( const wchar_t* format, ... )
{
	MIX_ASSERT( format != NULL );

#if 1

	wchar_t tmp[Mix::StringW::VA_TEMP_NUM] = { L'\0' };
	va_list args;

	va_start( args, format );
	_vsnwprintf_s( tmp, Mix::StringW::VA_TEMP_NUM, _TRUNCATE, format, args );
	va_end( args );

	Copy( tmp, wcslen( tmp ) );

#else

	Release();

	UIntT Num = ( wcslen( Format ) + Mix::StringW::SPF_PLUS_SIZE );
	UIntT AllocateSize = Num * 2;

	m_pStr = ( wchar_t* )MIX_LIB_MALLOC( AllocateSize );
	MIX_ASSERT( m_pStr != NULL );
	if( m_pStr == NULL )
	{
		Release();
		return NULL;
	}
	ZeroMemory( m_pStr, AllocateSize );

	va_list Args;
	va_start( Args, Format );
	_vsnwprintf_s( m_pStr, Num, _TRUNCATE, Format, Args );
	va_end( Args );

	m_Num = wcslen( m_pStr );
	m_Size = m_Num * 2;
	m_AllocateSize = AllocateSize;

#endif

	return m_pStr;
} 

StringW StringW::Left( UIntT num )
{
	return StringW( m_pStr, ( m_Num < num )? ( m_Num ) : ( num ) );
}

StringW StringW::Right( UIntT num )
{
	UIntT offset = 0;
	UIntT size = 0;

	if( m_Num < num )
	{
		offset = 0;
		size = m_Num;
	}
	else
	{
		offset = ( m_Num - num );
		size = num;
	}

	return StringW( m_pStr + offset, size );
}

StringW StringW::Mid( UIntT startPos, UIntT num )
{
	StringW ret;
	UIntT offset = 0;
	UIntT size = 0;

	if( m_Num <= startPos )
	{
		return ret;
	}

	offset = startPos;

	if( m_Num < ( offset + num ) )
	{
		size = m_Num - offset;
	}
	else
	{
		size = num;
	}

	ret.Copy( m_pStr + offset, size );

	return ret;
}

UIntT StringW::IndexOf( wchar_t value )
{
	if( m_pStr == NULL )
	{
		return SIZE_MAX;
	}

	for( UIntT i = 0; m_pStr[i] != L'\0'; i++ )
	{
		if( m_pStr[i] == value )
		{
			return i;
		}
	}

	return SIZE_MAX;
}

UIntT StringW::LastIndexOf( wchar_t value )
{
	if( m_pStr == NULL )
	{
		return SIZE_MAX;
	}

	for( UIntT i = ( m_Num - 1 ); i >= 0; i-- )
	{
		if( m_pStr[i] == value )
		{
			return i;
		}
	}

	return SIZE_MAX;
}

wchar_t* StringW::GetPtr( void ) const
{
	return m_pStr;
}

const wchar_t* StringW::GetConstPtr( void ) const
{
	return m_pStr;
}

UIntT StringW::GetNum( void ) const
{
	return m_Num;
}

UIntT StringW::GetSize( void ) const
{
	return m_Size;
}

UIntT StringW::GetAllocateSize( void ) const
{
	return m_AllocateSize;
}

UIntT StringW::GetCapacity( void ) const
{
	return m_Capacity;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////
// StringA 文字列クラス( マルチバイト )
/////////////////////////////////////////////////////////////////////////////////////////////////////////

char StringA::empty = 0;

StringA::StringA( void ) :
m_pStr( NULL ),
m_Num( 0 ),
m_Size( 0 ),
m_AllocateSize( 0 ),
m_Capacity( 0 )
{
}

StringA::StringA( const wchar_t* pStr ) :
m_pStr( NULL ),
m_Num( 0 ),
m_Size( 0 ),
m_AllocateSize( 0 ),
m_Capacity( 0 )
{
	Convert( pStr );
}

StringA::StringA( const char* pStr ) :
m_pStr( NULL ),
m_Num( 0 ),
m_Size( 0 ),
m_AllocateSize( 0 ),
m_Capacity( 0 )
{
	Copy( pStr );
}

StringA::StringA( const char* pStr, UIntT Size ) :
m_pStr( NULL ),
m_Num( 0 ),
m_Size( 0 ),
m_AllocateSize( 0 ),
m_Capacity( 0 )
{
	Copy( pStr, Size );
}

StringA::StringA( const StringA& Str ) :
m_pStr( NULL ),
m_Num( 0 ),
m_Size( 0 ),
m_AllocateSize( 0 ),
m_Capacity( 0 )
{
	Copy( Str.m_pStr );
}

StringA::~StringA( void )
{
	if( m_pStr != NULL )
	{
		MIX_LIB_FREE( m_pStr );
		m_pStr = NULL;
	}
}

void StringA::Allocate( UIntT num )
{
	UIntT allocSize = num + 1;

	if( m_pStr == NULL )
	{
		m_pStr = static_cast<char*>( MIX_LIB_MALLOC( Mix::Memory::SECTION_GENERAL, allocSize ) );
		MIX_ASSERT( m_pStr != NULL );

		m_Capacity = allocSize;
	}
	else
	{
		if( m_Capacity < allocSize )
		{
			void* pTemp = MIX_LIB_REALLOC( m_pStr, allocSize );
			MIX_ASSERT( pTemp != NULL );

			m_pStr = static_cast<char*>( pTemp );
			m_Capacity = allocSize;
		}
	}

	m_AllocateSize = allocSize;
}

void StringA::Copy( const char* pStr )
{
	Copy( pStr, ( pStr == NULL )? ( 0 ) : ( strlen( pStr ) ) );
}

void StringA::Copy( const char* pStr, UIntT num )
{
	if( pStr != NULL )
	{
		Allocate( num );

		m_Num = CalcStrNum( pStr );
		m_Size = num;

		Mix::Memory::Copy( m_pStr, pStr, m_Size );
		m_pStr[m_Size] = '\0';
	}
}

void StringA::Convert( const wchar_t* pStr )
{
	//変換後の長さを取得
	Int32 length = WideCharToMultiByte( CP_ACP, 0, pStr, -1, NULL, 0, NULL, NULL );

	if( length > 0 )
	{
		UIntT size = length - 1;

		Allocate( size );

		if( WideCharToMultiByte( CP_ACP, 0, pStr, static_cast<Int32>( wcslen( pStr ) ), m_pStr, static_cast<Int32>( size ), NULL, NULL ) > 0 )
		{
			m_pStr[size] = L'\0';

			m_Num = CalcStrNum( m_pStr );
			m_Size = size;
		}
	}
}

void StringA::Add( const char* pStr )
{
	if( pStr != NULL )
	{
		UIntT oldSize = m_Size;
		UIntT addNum = CalcStrNum( pStr );
		UIntT addSize = strlen( pStr );

		Allocate( oldSize + addSize );

		m_Num += addNum;
		m_Size += addSize;

		Mix::Memory::Copy( m_pStr + oldSize, pStr, addSize );
		m_pStr[m_Size] = '\0';
	}
}

UIntT StringA::CalcStrNum( const char* pStr )
{
	UIntT count = 0;
	const char* pc = &( pStr[0] );

	for( ;; )
	{
		BYTE c = ( BYTE )( *pc );
		if( c == 0x00 )
		{
			break;
		}

		if( c >= 0x80 )
		{
			pc++;
		}
		pc++;

		count++;
	}

	return count;
}

char& StringA::operator [] ( UIntT index )
{
	MIX_ASSERT( m_pStr != NULL );
	MIX_ASSERT( m_Size > index );

	return m_pStr[index];
}

Boolean StringA::operator == ( const StringA& Str ) const
{
	if( ( m_pStr == NULL ) && ( Str.m_pStr == NULL ) )
	{
		return True;
	}
	else if( ( m_pStr == NULL ) || ( Str.m_pStr == NULL ) )
	{
		return False;
	}

	return ( strcmp( m_pStr, Str.m_pStr ) == 0 );
}

Boolean StringA::operator == ( const char* pStr ) const
{
	if( ( m_pStr == NULL ) && ( pStr == NULL ) )
	{
		return True;
	}
	else if( ( m_pStr == NULL ) || ( pStr == NULL ) )
	{
		return False;
	}

	return ( strcmp( m_pStr, pStr ) == 0 );
}

Boolean StringA::operator == ( char code ) const
{
	if( m_pStr == NULL )
	{
		return False;
	}

	if( m_pStr[0] == code )
	{
		return True;
	}

	return False;
}

Boolean StringA::operator == ( UIntT NullValue ) const
{
	return ( m_pStr == NULL );
}

Boolean StringA::operator != ( const StringA& str ) const
{
	if( ( m_pStr == NULL ) && ( str.m_pStr == NULL ) )
	{
		return False;
	}
	else if( ( m_pStr == NULL ) || ( str.m_pStr == NULL ) )
	{
		return True;
	}

	return ( strcmp( m_pStr, str.m_pStr ) != 0 );
}

Boolean StringA::operator != ( const char* pStr ) const
{
	if( ( m_pStr == NULL ) && ( pStr == NULL ) )
	{
		return False;
	}
	else if( ( m_pStr == NULL ) || ( pStr == NULL ) )
	{
		return True;
	}

	return ( strcmp( m_pStr, pStr ) != 0 );
}

Boolean StringA::operator != ( UIntT nullValue ) const
{
	return ( m_pStr != NULL );
}

StringA& StringA::operator = ( const StringA& Str )
{
	Copy( Str.m_pStr );

	return *this;
}

StringA& StringA::operator = ( const char* pStr )
{
	Copy( pStr );

	return *this;
}

StringA& StringA::operator = ( const wchar_t* pStr )
{
	Convert( pStr );

	return *this;
}

StringA& StringA::operator = ( char Code )
{
	char Tmp[2];

	Tmp[0] = Code;
	Tmp[1] = 0;

	Copy( Tmp );

	return *this;
}

StringA& StringA::operator += ( const char* pStr )
{
	Add( pStr );

	return *this;
}

StringA& StringA::operator += ( const StringA& str )
{
	Add( str.m_pStr );

	return *this;
}

StringA StringA::operator + ( const StringA& str )
{
	StringA tmpStr( m_pStr );

	tmpStr.Add( str.m_pStr );

	return tmpStr;
}

StringA& StringA::operator += ( char code )
{
	char tmp[2] = { code, '\0' };

	Add( tmp );

	return *this;
}

Float64 StringA::ToDouble( Boolean* pbRet ) const
{
	if( m_pStr == NULL )
	{
		if( pbRet != NULL )
		{
			*pbRet = False;
		}
		return 0.0;
	}

	char* pStopString = NULL;
	Float64 retValue = strtod( m_pStr, &pStopString );

	if( *pStopString != 0 )
	{
		if( pbRet != NULL )
		{
			*pbRet = False;
		}

		return 0.0;
	}

	if( pbRet != NULL )
	{
		*pbRet = True;
	}

	return retValue;
}

Float32 StringA::ToFloat( Boolean* pbRet ) const
{
	if( m_pStr == NULL )
	{
		if( pbRet != NULL )
		{
			*pbRet = False;
		}
		return 0.0f;
	}

	char* pStopString = NULL;
	Float32 retValue = static_cast<Float32>( strtod( m_pStr, &pStopString ) );

	if( *pStopString != 0 )
	{
		if( pbRet != NULL )
		{
			*pbRet = False;
		}

		return 0.0f;
	}

	if( pbRet != NULL )
	{
		*pbRet = True;
	}

	return retValue;
}

Int32 StringA::ToInt( Boolean* pbRet ) const
{
	if( m_pStr == NULL )
	{
		if( pbRet != NULL )
		{
			*pbRet = False;
		}
		return 0;
	}

	char* pStopString = NULL;
	Int32 retValue = static_cast<Int32>( strtol( m_pStr, &pStopString, 0 ) );

	if( *pStopString != 0 )
	{
		if( pbRet != NULL )
		{
			*pbRet = False;
		}
		return 0;
	}

	if( pbRet != NULL )
	{
		*pbRet = True;
	}

	return retValue;
}

UInt32 StringA::ToUInt( Boolean* pbRet ) const
{
	if( m_pStr == NULL )
	{
		if( pbRet != NULL )
		{
			*pbRet = False;
		}
		return 0;
	}

	char* pStopString = NULL;
	UInt32 retValue = static_cast<UInt32>( strtoul( m_pStr, &pStopString, 0 ) );

	if( *pStopString != 0 )
	{
		if( pbRet != NULL )
		{
			*pbRet = False;
		}

		return 0;
	}

	if( pbRet != NULL )
	{
		*pbRet = True;
	}

	return retValue;
}

StringA StringA::ToUpper( void )
{
	Mix::StringA temp = *this;

	temp.Upper();

	return temp;
}

StringA StringA::ToLower( void )
{
	Mix::StringA temp = *this;

	temp.Lower();

	return temp;
}

void StringA::Upper( void )
{
	if( m_pStr == NULL )
	{
		return;
	}

	char* pc = &( m_pStr[0] );

	while( *pc != L'\0' )
	{
		// A〜Z( 0x41〜0x5A )
		// a〜z( 0x61〜0x7A )
		if( ( *pc >= 0x61 ) &&
			( *pc <= 0x7A ) )
		{
			*pc = *pc - 0x61 + 0x41;
		}

		pc++;
	}
}

void StringA::Lower( void )
{
	if( m_pStr == NULL )
	{
		return;
	}

	char* pc = &( m_pStr[0] );

	while( *pc != L'\0' )
	{
		// A〜Z( 0x41〜0x5A )
		// a〜z( 0x61〜0x7A )
		if( ( *pc >= 0x41 ) &&
			( *pc <= 0x5A ) )
		{
			*pc = *pc - 0x41 + 0x61;
		}

		pc++;
	}
}

char* StringA::Sprintf( const char* format, ... )
{
	MIX_ASSERT( format != NULL );

#if 1

	char temp[Mix::StringA::VA_TEMP_NUM] = { '\0' };
	va_list args;

	va_start( args, format );
	vsnprintf_s( m_pStr, Mix::StringA::VA_TEMP_NUM, _TRUNCATE, format, args );
	va_end( args );

	Copy( temp, strlen( temp ) );

#else

	Release();

	UIntT AllocateSize = strlen( format ) + Mix::StringA::SPF_PLUS_SIZE;

	m_pStr = ( char* )MIX_LIB_MALLOC( AllocateSize );
	MIX_ASSERT( m_pStr != NULL );
	if( m_pStr == NULL )
	{
		Release();
		return NULL;
	}
	ZeroMemory( m_pStr, AllocateSize );

	va_list Args;
	va_start( Args, format );
	vsnprintf_s( m_pStr, AllocateSize, _TRUNCATE, format, Args );
	va_end( Args );

	m_Num = CalcStrNum( m_pStr );
	m_Size = strlen( m_pStr );
	m_AllocateSize = AllocateSize;

#endif

	return m_pStr;
}

StringA StringA::Left( UIntT Size )
{
	return StringA( m_pStr, ( m_Size < Size )? ( m_Size ) : ( Size ) );
}

StringA StringA::Right( UIntT Size )
{
	UIntT offset = 0;
	UIntT size = 0;

	if( m_Size < Size )
	{
		offset = 0;
		size = m_Size;
	}
	else
	{
		offset = ( m_Size - Size );
		size = Size;
	}

	return StringA( m_pStr + offset, size );
}

StringA StringA::Mid( UIntT startPos, UIntT size )
{
	StringA tmpStr;
	UIntT offset = 0;
	UIntT copySize = 0;

	if( m_Size <= startPos )
	{
		return tmpStr;
	}

	offset = startPos;

	if( m_Size < ( offset + size ) )
	{
		copySize = m_Size - offset;
	}
	else
	{
		copySize = size;
	}

	tmpStr.Copy( m_pStr + offset, copySize );

	return tmpStr;
}

UIntT StringA::IndexOf( char value )
{
	if( m_pStr == NULL )
	{
		return SIZE_MAX;
	}

	for( UIntT i = 0; m_pStr[i] != '\0'; i++ )
	{
		if( m_pStr[i] == value )
		{
			return i;
		}
	}

	return SIZE_MAX;
}

UIntT StringA::LastIndexOf( char value )
{
	if( m_pStr == NULL )
	{
		return SIZE_MAX;
	}

	for( UIntT i = ( m_Num - 1 ); i >= 0; i-- )
	{
		if( m_pStr[i] == value )
		{
			return i;
		}
	}

	return SIZE_MAX;
}

char* StringA::GetPtr( void ) const
{
	return m_pStr;
}

const char* StringA::GetConstPtr( void ) const
{
	return m_pStr;
}

UIntT StringA::GetNum( void ) const
{
	return m_Num;
}

UIntT StringA::GetSize( void ) const
{
	return m_Size;
}

UIntT StringA::GetAllocateSize( void ) const
{
	return m_AllocateSize;
}

UIntT StringA::GetCapacity( void ) const
{
	return m_Capacity;
}

}
