#include "stdafx.h"

////////////////////////////////////////////////////////////////////////////////////////////////////
// 定数定義
////////////////////////////////////////////////////////////////////////////////////////////////////

#define MAX_TAB 8

enum ANALYZESTEP
{
	AS_NONE				= 0,
	AS_INPUTFILENAME	= 1,
	AS_OUTPUTFILENAME	= 2,
	AS_MAXHORIZ			= 3,
	AS_TAB				= 4,
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// グローバル変数定義
////////////////////////////////////////////////////////////////////////////////////////////////////

wchar_t* g_pInputFileName = NULL;
wchar_t* g_pOutputFileName = NULL;
unsigned int g_MaxHoriz = 16;
unsigned int g_Tab = 0;

////////////////////////////////////////////////////////////////////////////////////////////////////
// 関数定義
////////////////////////////////////////////////////////////////////////////////////////////////////

bool Initialize( int iArgCount, wchar_t* lpszArgList[] );
void Finalize( void );
bool SaveText( void );
bool CloneString( wchar_t** ppDst, wchar_t* pSrc );

////////////////////////////////////////////////////////////////////////////////////////////////////
// 関数
////////////////////////////////////////////////////////////////////////////////////////////////////

int _tmain( int argc, _TCHAR* argv[] )
{
	if( Initialize( argc, argv ) == true )
	{
		::wprintf( _T( "BinToText : \"%s\" -> \"%s\"..." ), g_pInputFileName, g_pOutputFileName );

		if( SaveText() == true )
		{
			::wprintf( _T( "Success\n" ) );
		}
		else
		{
			::wprintf( _T( "Failed\n" ) );
		}

		Finalize();
	}
	else
	{
		::wprintf( _T( "BinToText : Illegal Argument!\n" ) );
	}

	return 0;
}

bool Initialize( int iArgCount, wchar_t* lpszArgList[] )
{
	bool bSuccess = true;
	int iStep = AS_NONE;
	int i;

	for( i = 1; ( i < iArgCount ) && ( bSuccess == true ); i++ )
	{
		switch( iStep )
		{
		case AS_NONE:
			if( ::wcscmp( _T( "/i" ), lpszArgList[i] ) == 0 )
			{
				iStep = AS_INPUTFILENAME;
			}
			else if( ::wcscmp( _T( "/o" ), lpszArgList[i] ) == 0 )
			{
				iStep = AS_OUTPUTFILENAME;
			}
			else if( ::wcscmp( _T( "/h" ), lpszArgList[i] ) == 0 )
			{
				iStep = AS_MAXHORIZ;
			}
			else if( ::wcscmp( _T( "/t" ), lpszArgList[i] ) == 0 )
			{
				iStep = AS_TAB;
			}
			else
			{
				bSuccess = false;
			}
			break;

		case AS_INPUTFILENAME:
			if( g_pInputFileName == NULL )
			{
				if( CloneString( &g_pInputFileName, lpszArgList[i] ) == true )
				{
					iStep = AS_NONE;
				}
				else
				{
					bSuccess = false;
				}
			}
			else
			{
				bSuccess = false;
			}
			break;

		case AS_OUTPUTFILENAME:
			if( g_pOutputFileName == NULL )
			{
				if( CloneString( &g_pOutputFileName, lpszArgList[i] ) == true )
				{
					iStep = AS_NONE;
				}
				else
				{
					bSuccess = false;
				}
			}
			else
			{
				bSuccess = false;
			}
			break;

		case AS_MAXHORIZ:
			g_MaxHoriz = ::_wtoi( lpszArgList[i] );
			if( g_MaxHoriz != 0 )
			{
				iStep = AS_NONE;
			}
			else
			{
				bSuccess = false;
			}
			break;

		case AS_TAB:
			g_Tab = ::_wtoi( lpszArgList[i] );
			if( g_Tab <= MAX_TAB )
			{
				iStep = AS_NONE;
			}
			else
			{
				bSuccess = false;
			}
			break;
		}
	}

	if( ( g_pInputFileName == NULL ) ||
		( g_pOutputFileName == NULL ) )
	{
		bSuccess = false; 
	}

	return bSuccess;
}

void Finalize( void )
{
	if( g_pInputFileName != NULL )
	{
		::free( g_pInputFileName );
	}
	if( g_pOutputFileName != NULL )
	{
		::free( g_pOutputFileName );
	}
}

bool SaveText( void )
{
	FILE* fileIn = NULL;
	FILE* fileOut = NULL;
	long lSize = 0;
	unsigned char* pucSrc = NULL;
	unsigned char* ps = NULL;
	unsigned char* ps_end = NULL;

	if( ::_wfopen_s( &fileIn, g_pInputFileName, _T( "rb" ) ) != 0 )
	{
		return false;
	}
	::fseek( fileIn, 0L, SEEK_END );
	lSize = ::ftell( fileIn );
	::fseek( fileIn, 0L, SEEK_SET );

	pucSrc = reinterpret_cast<unsigned char*>( ::malloc( lSize ) );
	if( pucSrc == NULL )
	{
		::fclose( fileIn );
		return false;
	}
	::fread( pucSrc, 1, lSize, fileIn );
	::fclose( fileIn );

	unsigned int i;
	unsigned short bom = 0xFEFF;
	unsigned int horizCount = 0;
	wchar_t strTab[MAX_TAB];
	wchar_t strValue[6];

	::memset( strTab, 0, sizeof( strTab ) );
	for( i = 0; i < g_Tab; i++ )
	{
		::wcscat_s( strTab, L"\t" );
	}

	if( ::_wfopen_s( &fileOut, g_pOutputFileName, _T( "wb" ) ) != 0 )
	{
		::free( pucSrc );
		return false;
	}

	::fwrite( &bom, sizeof( bom ), 1, fileOut );

	if( g_Tab > 0 )
	{
		::fwrite( &( strTab[0] ), ( ::wcslen( strTab ) << 1 ), 1, fileOut );
	}

	ps = pucSrc;
	ps_end = ( ps + lSize );
	while( ps != ps_end )
	{
		::swprintf( strValue, 6, _T( "0x%02x," ), *ps );
		::fwrite( &( strValue[0] ), sizeof( strValue ) - 2, 1, fileOut );

		horizCount++;
		if( horizCount == g_MaxHoriz )
		{
			::wcscpy_s( strValue, L"\n" );
			::fwrite( &( strValue[0] ), 2, 1, fileOut );

			if( g_Tab > 0 )
			{
				::fwrite( &( strTab[0] ), ( ::wcslen( strTab ) << 1 ), 1, fileOut );
			}

			horizCount = 0;
		}

		ps++;
	}

	::fclose( fileOut );
	::free( pucSrc );

	return true;
}

bool CloneString( wchar_t** ppDst, wchar_t* pSrc )
{
	size_t sizeNum = ( ::wcslen( pSrc ) + 1 );
	size_t sizeArg = ( sizeNum * 2 );
	( *ppDst ) = reinterpret_cast<wchar_t*>( ::malloc( sizeArg ) );
	if( ( *ppDst ) == NULL )
	{
		return false;
	}

	::memset( ( *ppDst ), 0, sizeArg );
	::wcscpy_s( ( *ppDst ), sizeNum, pSrc );

	return true;
}
