//********************************************************************************************
/**
 * @file		togeGrep.cpp
 * @brief		まとめてGREP
 *
 *	このファイルの詳細説明
 *
 * @date		2010/11/02	hk-taken	新規作成.
 */
//********************************************************************************************

#define	SW_MODULE_TOGEGREP						///< この機能を切り離したい時はコメントアウト.


#ifdef	SW_MODULE_TOGEGREP
//------------------------------------------------------------------
/**
	スクリプトコマンドクラス.
*/
//------------------------------------------------------------------
class TOGEGREP
{
	BOOL		m_bInitialized;
	BOOL		m_bImplemented;
	BOOL		m_bFullInit;
	
	void		Initialize( LPCTSTR _pGrepListName );
	
	TCHAR		m_sGrepList[ 1024 ][ 64 ];
	Int32		m_iEntry;
	
public:
	int			Func( LPCTSTR _sParamString );
	void		Quit( BOOL _bExit );
	
	TOGEGREP();
	~TOGEGREP();
	
};

///	アプリケーション起動時.
TOGEGREP::TOGEGREP()
	: m_bFullInit( FALSE )
	, m_bInitialized( FALSE )
	, m_bImplemented( FALSE )
	, m_iEntry( 0 )
{
	
}
///	アプリケーション終了時.
TOGEGREP::~TOGEGREP(){
}

static const TCHAR	s_sTogeFileExt[] = TEXT(".togeGrep");							///< 一時ファイルの拡張子.

//==============================================================================================================================================
/**
	初期化と開放.
		1ファイルに1つの処理でコンプリートするような場合は修正する必要ありません
		注釈となっている Message_printf を有効にして sample.swb を実行すると動きがよく分かると思います。
*/
//==============================================================================================================================================

//------------------------------------------------------------------
/**
	スクリプトコマンドの初期化.
		(特に必要ないなら変更の必要なし)
*/
//------------------------------------------------------------------
void	TOGEGREP::Initialize( LPCTSTR _pGrepListName )
{
	if( m_bInitialized == TRUE )	return;
	m_bInitialized = TRUE;	//	初期済みフラグ
	
	if( m_bFullInit == FALSE ){
		m_bFullInit = TRUE;
		//	全体を通して一度しか行わない初期化
		TCHAR	*mem = NULL;
		int		iLength = 0;
		
		Message_printf( TEXT("GrepList:%s"), _pGrepListName );
		
		iLength = MEM_TextRead( &mem, _pGrepListName );							///< UNICODEの場合 UTF16に変換されて読まれます.
		
		Int32	jj = 0;
		for( Int32 ii=0 ; ii<iLength ; ii++ )
		{
#ifndef _UNICODE
			if( STRING_IsMultiByte( mem + ii ) )
			{
				m_sGrepList[ m_iEntry ][ jj++ ] = *(mem + ii);
				ii++;
			}
			else
#endif
			if( ' ' > *(mem + ii) )
			{
				m_sGrepList[ m_iEntry ][ jj ] = 0;
				if( 0 < STRING_len( m_sGrepList[ m_iEntry ] ) )	m_iEntry++;
				jj = 0;
				continue;
			}
			m_sGrepList[ m_iEntry ][ jj++ ] = *(mem + ii);
		}
		
	//	for( Int32 ii=0 ; ii<m_iEntry ; ii++ )	_printf( TEXT("%d:%s\r\n"), ii, m_sGrepList[ ii ] );
		
		mem_del( mem );
	}
	
	//	初期化処理
	//	１つのバッチに同じスクリプトが２度指定されていたならここには２度来る
	//Message_printf("初期化");
	
}

//------------------------------------------------------------------
/**
	スクリプトコマンドの終了.
		(特に必要ないなら変更の必要なし)
*/
//------------------------------------------------------------------
void	TOGEGREP::Quit(BOOL _bExit)
{
	//	ここにはスクリプトを使っていなくても来るので注意
	
	if( m_bImplemented == FALSE )	return;		///<変換処理が実行されていないなら帰還.
	m_bImplemented = FALSE;
	m_bInitialized = FALSE;
	
	///	終了処理.
	//Message_printf("完了");
	
	if( _bExit == TRUE ){
		//	次のスクリプトは存在しない、完全な終了
		//	１つのバッチに同じスクリプトに別パラメータを渡しての処理で
		//	逐一結果を出さず、全体で統合して結果を出したい場合などはここで
		
		//Message_printf("終了");
		
		TCHAR	szName[ 256 ];
#if 0
		const TCHAR	c_sResultFileName[] = TEXT("result.txt");
		FILE_delete( c_sResultFileName );
#endif
		
		/// 一時ファイルをマージ.
		for( Int32 iIdx=0 ; iIdx<m_iEntry ; iIdx++ )
		{
			TCHAR	*mem = NULL;
			
			wsprintf( szName, /*256, */TEXT("%d%s%s"), iIdx, m_sGrepList[ iIdx ], s_sTogeFileExt );
			
			Int32	iLength = MEM_TextRead( &mem, szName );							///< UNICODEの場合 UTF16に変換されて読まれます.
			
			if( 0 < iLength )
			{
#if 0
				FILE_TextWriteMerge( c_sResultFileName , m_sGrepList[ iIdx ] );
				FILE_TextWriteMerge( c_sResultFileName , TEXT("\r\n") );
				
				FILE_TextWriteMerge( c_sResultFileName , mem );
				
				FILE_TextWriteMerge( c_sResultFileName , TEXT("\r\n") );
#else
				Message_printf( TEXT("%s"), m_sGrepList[ iIdx ] );
				Message_printf( TEXT("%s"), mem );
#endif
			}
			
			mem_del( mem );
			
			FILE_delete( szName );
		}
#if 0
		if( 0 < FILE_GetFileSize( c_sResultFileName ) )
		{
			Message_printf( TEXT("output %s"), c_sResultFileName );
		}else{
			Message_printf( TEXT("no Hit") );
		}
#endif
	}
	
}







//==============================================================================================================================================
//	変換処理部分
//==============================================================================================================================================

#define	TOGEGREP_OUTAREA		2	///< 変換後の容量は仮に元の倍取っている　内容によって変更して下さい.

//********************************************************************************************
/**
 * @brief		まとめてGREP変換フィルターサンプル　機能:無変換(ファイルコピー)
 *				テキストデータを取り扱うサンプル.
 *				変換せず調査だけなら out に関する部分は不要.
 *
 * @param[in]	LPCTSTR	_sParamString	引数文字列(内容は書き換えられる)  ターゲットファイル名 + スクリプトで指定する引数.
 *
 * @return		int	TRUE:成 / FALSE:否(デフォルト)
 */
//********************************************************************************************
int		TOGEGREP::Func( LPCTSTR _sParamString )
{
	/// 単語境界.
	const TCHAR	c_sBorderChar[] = TEXT(".,-+/*=;:<>()[] \"\t\r\n\0");
	LPCTSTR		sBorderChar;
	
	CSwbParam	cParam( _sParamString );							///< パラメータ処理.
	
	TCHAR	sLineString[ 1024 ];
	TCHAR	szName[ 256 ];
	TCHAR	*mem = NULL;
	LPTSTR	pLineTop = NULL;
	int		ii, iLine, iSourceLength;
	LPCTSTR	szFileName, szGrepListName;
	Bool	bWordSearch = FALSE;
	
	/// 引数の取り出し.
	szFileName = cParam.GetPath();								///< ターゲットファイル (GetString(0)としても同じ).
	szGrepListName  = cParam.GetString( 1 );					///< リストファイル.
	bWordSearch = cParam.GetInt( 2 );							///< 単語検索かフラグ.
	
	Initialize( szGrepListName );
	
	
	/// 元データ読み込み(関数内部でmemに領域を確保している).
	iSourceLength = MEM_TextRead( &mem, szFileName );							///< UNICODEの場合 UTF16に変換されて読まれます.
	if(iSourceLength == 0){
		/** エラーメッセージの表示　処理はMessage_printfと同じ、Message_errorを使用すると自動終了しなくなります */
		Message_error( TEXT("file not found:%s"), szFileName );
		return FALSE;						///< ファイルがない.
	}
	
	m_bImplemented = TRUE;					///<	実行済みフラグon.
	
	if( bWordSearch )	sBorderChar = c_sBorderChar;
	else				sBorderChar = NULL;
	
	ii = 0;
	iLine = 1;
	pLineTop = (mem + ii);
	
	/// 検索処理部分.
	while( ii < iSourceLength )
	{
		LPTSTR	pPtr = mem + ii;
		
		if( *(pPtr) == '\n' )
		{
			iLine++;
			ii++;
			pLineTop = (mem + ii);
			continue;
		}
		
		/// 先頭または単語の先頭か.
		if( sBorderChar == NULL || ( ii==0 || 0 <= STRING_CheckChar( *(pPtr-1), sBorderChar ) ) )
		{
			for( Int32 iIdx=0 ; iIdx<m_iEntry ; iIdx++ )
			{
				if( STRING_buffcmp( pPtr, m_sGrepList[ iIdx ], sBorderChar ) )
				{
					/// 行文字列を取得.
					Int32	jj = 0;
					while( *(pLineTop + jj) != '\r' && *(pLineTop + jj) != '\n' && jj<1024 )
					{
						sLineString[ jj ] = *(pLineTop + jj);
						jj++;
					}
					sLineString[ jj ] = 0;
					
					wsprintf( szName, /*256, */TEXT("%d%s%s"), iIdx, m_sGrepList[ iIdx ], s_sTogeFileExt );
					FILE_printf( szName, TEXT("%s(%d): %s\r\n"), szFileName, iLine, sLineString );
					
				//	Message_printf( TEXT("Hit:%s"), szFileName );
				}
			}
		}
		
#ifndef	_UNICODE
		if( STRING_IsMultiByte(pPtr) )	ii++;
#endif
		ii++;
		CHECK_LOOPOVER(32000);	///< 無限ループ安全処理	引数で指定した回数 ii が更新されないとbreakして処理停止.
	}
	
	
	/// メモリを開放.
	mem_del(mem);
	
	return TRUE;
}


TOGEGREP	*pC_togeGrep = NULL;

#endif	// SW_MODULE_TOGEGREP
