
/*!
@file filefind.hpp
@brief ファイル探索
@since 2004/03/17 2004/12/02
@author d金魚

*/


#ifndef DKUTIL_FILESYSTEM_FILEFIND_HPP
#define DKUTIL_FILESYSTEM_FILEFIND_HPP

#include <string>
#include <list>
#include <dkutil_c/dkc.h>
#include <dkutil/filesystem/interface.hpp>
#include <dkutil/filesystem/utility.hpp>
#include <dkutil/output.hpp>
#include <dkutil/boost/scoped_ptr.hpp>
#include <dkutil/filesystem/ext.hpp>

namespace dkutil{

namespace policy{
struct find_file_policy_base{
protected:
public:
	///この構造体データをファイルに保存（シリアライズ）しないでください。
	struct FILE_PROPERTY{
		///ファイルのサイズ
		ULONGLONG mSize;
		///ディレクトリです。
		bool mDirectory;
		///読取専用です。
		bool mReadOnly;
		///システムファイルです。
		//bool mSystem;
		///普通のファイルです。
		bool mNormal;
	};
	typedef FILE_PROPERTY file_property_type;
	//typedef std::pair<std::string,FILE_PROPERTY> DATA_TYPE;
	
	virtual ~find_file_policy_base(){}

	virtual bool find_first(const char *dir,const char *target) = 0;
	virtual bool find_next() = 0; 
	virtual bool find_close() = 0;
	virtual const std::string filename()const = 0;
	virtual const std::string full_filename()const = 0;
	virtual const std::string extension()const = 0;
	virtual bool is_normal()const = 0;
	virtual bool is_readonly()const = 0;
	virtual bool is_directory()const = 0;
	virtual ULONGLONG filesize()const = 0;
	virtual bool is_dot()const = 0;
	virtual const file_property_type property()const = 0;

	virtual bool is_error()const = 0;
	///無事に終了したのならTRUE
	virtual bool is_end_process()const = 0;
	///find_first()を呼び出して検索中ならTRUE
	virtual bool is_searching()const = 0;
};
/*!
汎用型FirstFindFile：file_listup()のポリシー
*/
class generic_find_file_policy : public  find_file_policy_base
{
	DKC_FINDFILE *pff;
	std::string mDir;
	bool mInited;
	int mError;
public:
	typedef find_file_policy_base base_type;
	typedef generic_find_file_policy self_type;
	typedef base_type::FILE_PROPERTY file_property_type;

	generic_find_file_policy(){
		mInited = false;
		mError = edk_SUCCEEDED;
		pff = dkcAllocFindFile();
	}
	~generic_find_file_policy(){
		find_close();
		dkcFreeFindFile(&pff);
	}
	bool find_first(const char *dir,const char *target){
		if(is_searching()==true){
			find_close();
		}
		{
			std::string t = dir;
			DirectoryPlusFileName(t,target);
			if( DKUTIL_FAILED(mError = dkcFindFirstFile(pff,t.c_str() ) ))
			{
				return false;
			}
		}
		mDir = dir;

		mInited = true;
		return true;
	}

	bool find_next(){
		dkcmNOT_ASSERT(is_searching()==false);
		return DKUTIL_SUCCEEDED(mError = dkcFindNextFile(pff));
	}
	bool find_close(){
		if(is_searching()==false)
			return false;
		bool ret = DKUTIL_SUCCEEDED(mError = dkcFindClose(pff));
		mDir.clear();
		mInited = false;//しっかり倒す。
		return ret;
	}
	const std::string filename()const{
		char buff[MAX_PATH];
		dkcFindFileGetFileName(pff,buff,sizeof(buff));
		return std::string(buff);
	}
	const std::string full_filename()const{
		std::string full = mDir;
		//printf(full.c_str());
		DirectoryPlusFileName(full,filename().c_str());
		return full;
	}
	const std::string extension()const{
		std::string ts = full_filename(),dest;
		//printf(ts.c_str());
		GetFileExtension(dest,ts.c_str());
		//printf("\nOK");
		return dest;
	}
	bool is_normal()const{
		return TRUE==dkcFindFileIsNormalFile(pff);
	}
	bool is_readonly()const{
		return TRUE==dkcFindFileIsReadOnly(pff);
	}
	bool is_directory()const{
		return TRUE==dkcFindFileIsFolder(pff);
	}
	ULONGLONG filesize()const{
		ULONG h,l;
		dkcFindFileSize(pff,&h,&l);
		return (ULONGLONG)((h << 32) + l);
	}
	bool is_dot()const{
		return TRUE==dkcFindFileIsDot(pff);
	}
	const file_property_type property()const{
		file_property_type t;
		t.mSize = filesize();
		t.mNormal = is_normal();
		t.mReadOnly = is_readonly();
		t.mDirectory = is_directory();
		return t;
	}
	///エラーならTRUE
	bool is_error()const{
		return (mError==edk_FAILED);
	}
	///無事に終了したのならTRUE
	bool is_end_process()const{
		return (mError==edk_EndProcess);
	}
	bool is_searching()const{
		return mInited;
	}

};

#if 0

/*!Windows NT系列用 Win32 Find DATA */
class winnt_find_file_policy : public  find_file_policy_base{
	//generic_find_file_policy mGeneric;
	
	///ディレクトリ
	std::string mDir;
	
	HANDLE mHandle;
	WIN32_FIND_DATAW mFindData;

	int mError;

	bool mNT;
	bool isNT()const{return mNT;}
public:
	//typedef std::wstring string_type;
	typedef find_file_policy_base base_type;
	typedef winnt_find_file_policy self_type;
	typedef base_type::FILE_PROPERTY file_property_type;

	winnt_find_file_policy(){
		mHandle = INVALID_HANDLE_VALUE;
		mError = edk_SUCCEEDED;
		
	}
	~winnt_find_file_policy(){
		find_close();
	}

	bool find_first(const char *dir,const char *target){
		if(is_searching()){
			find_close();
		}
		char w[]={'\\','\\','?','\\','\0'};
		/*
		Windows NT/2000/XP：
		Unicode 版関数（ FindFirstFileW 関数）を使用し、パス名の前に "\\?\" または "\\?\UNC" を付けることで、 260 (MAX_PATH) 文字よりも長い文字列を
		<b>指定</b>することができます。
		つまり、取得できると言う事では無いようだ。
		*/

		std::string t = w;
		t += dir;
		DirectoryPlusFileName(t,target);
		std::wstring wt = to_unicode(t);  

		mHandle = ::FindFirstFileW( wt.c_str() , &mFindData );
		if(mHandle == INVALID_HANDLE_VALUE){
			return false;
		}

		mDir = dir;

		return true;
	}
	bool find_next(){
		dkcmNOT_ASSERT(is_searching()==false);

		if ( 0 == ::FindNextFileW( mHandle, &mFindData ))
		{
			if ( ::GetLastError() == ERROR_NO_MORE_FILES )
			{//なんだ、もう無いじゃん。
				mError = edk_EndProcess;
			}
			else//最悪のパターン
			{
				mError = edk_FAILED;
			}
			return false;
		}
		return true;
	}
	bool find_close(){
		if(false==is_searching())
			return false;
		if(INVALID_HANDLE_VALUE == mHandle){
			return false;
		}
		::FindClose(mHandle);
		mHandle = INVALID_HANDLE_VALUE;//しっかりリセット
		return true;
	}
	const std::string filename()const{
		return to_sjis(std::wstring(mFindData.cFileName));
	}
	const std::string full_filename()const{
		std::string full = mDir;
		DirectoryPlusFileName(full,filename().c_str());
		return full;
	}
	bool is_normal()const{
		return TRUE==(mFindData.dwFileAttributes & FILE_ATTRIBUTE_NORMAL);
	}
	bool is_readonly()const{
		return TRUE==(mFindData.dwFileAttributes & FILE_ATTRIBUTE_READONLY);
	}
	bool is_directory()const{
		return (
			mFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
			&& !is_dot()
			);
	}
	ULONGLONG filesize()const{
		ULONG High = mFindData.nFileSizeHigh;
		ULONG Low = mFindData.nFileSizeLow;
		return (ULONGLONG)((High << 32) + Low);
	}
	bool is_dot()const{
		return (
			wcscmp(mFindData.cFileName,L"..") == 0 || 
			wcscmp(mFindData.cFileName,L".") == 0
		);
	}
	const file_property_type property()const{
		file_property_type t;
		t.mSize = filesize();
		t.mNormal = is_normal();
		t.mReadOnly = is_readonly();
		t.mDirectory = is_directory();
		return t;
	}
	///エラーならTRUE
	bool is_error()const{
		return (mError==edk_FAILED);
	}
	///無事に終了したのならTRUE
	bool is_end_process()const{
		return (mError==edk_EndProcess);
	}
	bool is_searching()const{
		return (mHandle!=INVALID_HANDLE_VALUE);
	}

};

#endif

///ファイルをリストアップするときの状態
struct listup_state{
		listup_state() : mLimitCount(0){}
		size_t mLimitCount;
};

template<class FIND_TYPE,class CONTAINER__>
struct listup_file_functor{
	
	inline bool find_limit(CONTAINER__ &c,const char *dir,const char *target,bool bSubDir,size_t limit){
		listup_state state;
		if(dkcIsAbsolutelyPath(target)){
			DKUTIL_THROW(std::runtime_error("argument:absolutely path target"));
			return false;
		}
		return find_limit_ex(&state,c,dir,target,bSubDir,limit);
	}
	///@param limit[in] 検索する最大値を指定 
	inline bool find_limit_ex(listup_state *state,CONTAINER__ &c,const char *dir,const char *target,bool bSubDir,size_t limit)
	{
		boost::scoped_ptr<FIND_TYPE> pff(new FIND_TYPE);
		const std::string NowDir = dir;
		{
#define DKUTIL_SUBDIR_FUNC
#ifdef DKUTIL_SUBDIR_FUNC
			if(bSubDir){//サブディレクトリも念入りに検査するときに
				if( false == pff->find_first(dir,"*.*") )
				{
					goto Error;
				}
			}else{
				// 検索情報を取得する 
				if( false == pff->find_first(dir,target) )
				{
					goto Error;
				}
			}
				goto Success;
			Error:
#	ifdef DEBUG
				{
					std::string str = "find_limit_ex() : ";
					str += GetWin32LastErrorString();
					dODS(str);
				}
#	endif
				//atError(pff.get(),dir,target,bSubDir);
				return false;
			Success:;
			
#else
			// 検索情報を取得する 
			if( false == pff->find_first(dir,target) )
			{
				dODS(GetWin32LastErrorString());
				//VISUAL_LASTERROR();
				return false;
			}
#endif
		}
		//インクリメントぉ
		state->mLimitCount++;

		//int result;
		do{
			if(limit < state->mLimitCount){//リミットを超えたら終了
				break;
			}
			// 現在のディレクトリ（フォルダ）と親ディレクトリは排除 
			if( false == pff->is_dot() ){ 
				if( pff->is_directory() ){ 
					if(bSubDir)
					{//再帰検索好きじゃないけどやるしかない･･･。
						std::string ts = pff->full_filename();
						if(ts != dir)
						{//同じではない時。
							listup_file_functor func;
							func.find_limit_ex(state,c,ts.c_str(),target,bSubDir,limit);

						}
					}
				}else{//それ以外
#ifdef DKUTIL_SUBDIR_FUNC
					if(bSubDir){//サブディレクトリも検索のとき
						if(pff->filename()==target){//しっかりファイル名あたっとる
							c.push_back(pff->full_filename());
						}else{
							size_t len = strlen(target);
							if(len >= 3){
								std::string tex = pff->extension();
								std::string tar = &target[2];
								
								//todo ココの条件を?のwild cardでもOKにする。(かなり限定的なので・・・）
								if(tex == tar || tar=="*" || 
									(tar=="?" && tex.size() == 1))
								{
									c.push_back(pff->full_filename());
								}
							}
						}
					}else{
						c.push_back(pff->full_filename());
					}
#else
					c.push_back(pff->full_filename());
#endif
				}
			}
			//カウンタをインクリメント
			state->mLimitCount++;
			
		}while(pff->find_next());//成功する限りループをまわす。

		if(pff->is_error()){
			dODS(GetWin32LastErrorString());
			//VISUAL_LASTERROR();
			return false;
		}
		return true;

	}
	inline bool operator()(CONTAINER__ &c,const char *dir,const char *target,bool bSubDir = true)
	{
		boost::scoped_ptr<FIND_TYPE> pff(new FIND_TYPE);
		const std::string NowDir = dir;
		{

			// 検索情報を取得する 
			if( false == pff->find_first(dir,target) )
			{
				dODS(GetWin32LastErrorString());
				//VISUAL_LASTERROR();
				return false;
			}
		}


		//int result;
		do{

			// 現在のディレクトリ（フォルダ）と親ディレクトリは排除 
			if( false == pff->is_dot() ){ 
				if( pff->is_directory() ){ 
					if(bSubDir)
					{//再帰検索好きじゃないけどやるしかない･･･。
						std::string ts = pff->full_filename();
						if(ts != dir)
						{//同じではない時。
							listup_file_functor func;
							func(c,ts.c_str(),target,bSubDir);
							//listup_file(c,ts.c_str(),target,bSubDir);
						}
						/*if(false==find_logic(dir,target)){
							return false;
						}*/
					}
				}else{//それ以外
					c.push_back(pff->full_filename());
				}
			}
			
		}while(pff->find_next());//成功する限りループをまわす。

		if(pff->is_error()){
			dODS(GetWin32LastErrorString());
			//VISUAL_LASTERROR();
			return false;
		}
		return true;
	}

};//end of functor


}//end of policy namespace


class findfile_base{
public:
	typedef policy::listup_state listup_state;
	typedef policy::generic_find_file_policy find_policy;

	//findfile_base(){}
	virtual ~findfile_base(){}
	///エラーのとき
	virtual bool atError(find_policy *,const char *,const char *,bool ){
		dODS(GetWin32LastErrorString());
		return true;
	}
	///ディレクトリのとき
	virtual bool atDirectory(find_policy *,const char *,const char *t,bool){
		return true;
		}
	///ファイルのとき
	virtual bool atFile(find_policy *,const char *,const char *t,bool){
		return true;
		}
	///ドットのとき
	virtual bool atDot(find_policy *,const char *,const char *t,bool){
		return true;
	}


	virtual bool find(const char *dir,const char *target,bool bSubDir = true)
	{
		boost::scoped_ptr<find_policy> pff(new find_policy);
		//const std::string NowDir = dir;
		{

			// 検索情報を取得する 
			if( false == pff->find_first(dir,target) )
			{
				dODS(GetWin32LastErrorString());
				atError(pff.get(),dir,target,bSubDir);
				return false;
			}
		}


		//int result;
		do{
			// 現在のディレクトリ（フォルダ）と親ディレクトリは排除 
			if( false == pff->is_dot() ){ 
				if( pff->is_directory() ){ 
					atDirectory(pff.get(),dir,target,bSubDir);
				}else{//それ以外
					atFile(pff.get(),dir,target,bSubDir);
				}
			}else{
				atDot(pff.get(),dir,target,bSubDir);
			}
		}while(pff->find_next());//成功する限りループをまわす。

		if(pff->is_error()){
			dODS(GetWin32LastErrorString());
			atError(pff.get(),dir,target,bSubDir);
			return false;
		}
		return true;
	}

};


#if 0
/*!
@param CONTAINER__[in] std::stringが指定されているコンテナ
@param c[in][out] std::stringが指定されているコンテナ
@param dir[in] ディレクトリ
@param target[in] ターゲット名(*.*とか??.cppとかtarget.hppとか)
@param bSubDir[in] TRUEだとサブディレクトリも検索
*/
template<class CONTAINER__>
bool listup_file(CONTAINER__ &c,const char *dir,const char *target,bool bSubDir = true)
{
	bool r;
	/*if(isOSNT()){
		policy::listup_file_functor<policy::winnt_find_file_policy,CONTAINER__> func;
		r = func(c,dir,target,bSubDir);
	}else{
		policy::listup_file_functor<policy::generic_find_file_policy,CONTAINER__> func;
		r = func(c,dir,target,bSubDir);
	}*/
	policy::listup_file_functor<policy::generic_find_file_policy,CONTAINER__> func;
	r = func(c,dir,target,bSubDir);

	return r;
}

#endif

/**
	@note
	<h5>reset時に渡して良いtarget引数</h5>
	*  failed  /  *.* succeeded
	?  failed  /  a? succeeded 
	*/
class file_listup_container{
public:
	
	//typedef std::list<std::pair<std::string,FILE_PROPERTY> > CONTAINER_TYPE;
	typedef std::list<std::string> list_type;
	typedef list_type::iterator iterator;
	typedef list_type::const_iterator const_iterator;
	typedef list_type::size_type size_type;

	typedef file_listup_container self_type;

	///拡張子を元にいろいろと検索する奴 @note non thread safe
	template<class CONTAINER_T=std::list<std::string> >
	class file_ext_listupper : protected findfile_base{
	public:
		typedef CONTAINER_T list_type;
		typedef findfile_base base_type;
		typedef file_ext_listupper self_type;

	private:
		///拡張子コンテナ
		list_type mExtList;
		///コンテナ
		list_type *mc;
		///フラグ
		UINT mFlag;
		///リミット
		size_t mLimit;
	public:
	
		///拡張子を入れる @return*や *.*を入れるとfalse
		bool store_ext(parm_string ext){
			

			std::string ts = ext.c_str();
			if(ts=="*" || ts=="*.*")
			{
				/*DKUTIL_THROW_OR_NOTICE(
					filesystem_error("file_ext_listupper::store_ext() extension is * or *.*")
				);*/
				return false;
			}
			
			ts.clear();

			if(false==GetFileExtension(ts,ext.c_str())){
				ts = ext.c_str();
			}
			mExtList.push_back(ts);
			return true;
		}
		/**
		@return store_ext()の戻り値と同じ
		*/
		///コンテナからsotre_ext()
		template<class T>
		bool store_container(const T &x)
		{
			T::const_iterator it = x.begin();
			clear();
			for(;it != x.end();it++)
			{
				if(false==store_ext((*it)))
				{
					return false;
				}
			}
			return true;
		}
		///内部に貯めた拡張子を破棄
		void clear(){
			mExtList.clear();
		}
		
		file_ext_listupper(list_type *ac,UINT flag,size_t limit) : mFlag(flag) , mLimit(limit)
		{
			setContainer(ac);
		}
		void setContainer(list_type *ac){
			mc = ac;
		}
		virtual ~file_ext_listupper(){
		
		}
		virtual bool atDirectory(find_policy *p,const char *dir,const char *target,bool subdir){
			bool r = !subdir;
			if(subdir){
				//ここのmLimitあたりがスレッドセーフではない･･･(´Д⊂ｸﾞｽﾝ
				r = find_limit(p->full_filename(),subdir,mLimit);
			}
			return r;
		}
		virtual bool atFile(find_policy *p,const char *dir,const char *target,bool subdir)
		{
			/*std::string tt = target;
			if(tt=="*" || tt=="*.*"){
				goto PushEnd;
			}*/
			#ifdef DEBUG
				dODS(p->filename());
				//dODS(p->extension().c_str());
			#endif
			{
				list_type::iterator it;
				for(it = mExtList.begin();it != mExtList.end();it++)
				{

					if( (*it) == p->extension() )
					{//拡張子が合っているなら
						goto PushEnd;
					}
				}
			}
		End:
			return true;
		PushEnd:
			mc->push_back(p->full_filename());//ぶち込む
			goto End;
		}
		inline bool find_limit(const char *dir,const char *target,bool bSubDir,size_t limit)
		{
			listup_state state;
			return find_limit_ex(&state,dir,target,bSubDir,limit);
		}

		///@param limit[in] 検索する最大値を指定 
		virtual bool find_limit_ex(listup_state *state,const char *dir,const char *target,bool bSubDir,size_t limit)
		{
			boost::scoped_ptr<find_policy> pff(new find_policy);
			//const std::string NowDir = dir;
			{
//#define DKUTIL_SUBDIR_FUNC2
#ifdef DKUTIL_SUBDIR_FUNC2
				if(bSubDir){//サブディレクトリも念入りに検査するときに
					if( false == pff->find_first(dir,"*.*") )
					{
						goto Error;
					}
				}else{
					// 検索情報を取得する 
					if( false == pff->find_first(dir,target) )
					{
						goto Error;
					}
					
				}
				goto Success;
			Error:
				dODS(GetWin32LastErrorString());
				atError(pff.get(),dir,target,bSubDir);
				return false;
			Success:
#else
				// 検索情報を取得する 
				if( false == pff->find_first(dir,target) )
				{
					dODS(GetWin32LastErrorString());
					atError(pff.get(),dir,target,bSubDir);
					return false;
				}
#endif
			}
			//インクリメントぉ
			state->mLimitCount++;

			//int result;
			do{
				if(limit < state->mLimitCount){//リミットを超えたら終了
					break;
				}
				// 現在のディレクトリ（フォルダ）と親ディレクトリは排除 
				if( false == pff->is_dot() ){ 
					if( pff->is_directory() ){ 
						atDirectory(pff.get(),dir,target,bSubDir);
					}else{//それ以外
#ifdef DKUTIL_SUBDIR_FUNC2
						if(bSubDir){//サブディレクトリも検索のとき
							if(pff->filename()==target){//しっかりファイル名あたっとる
								atFile(pff.get(),dir,target,bSubDir);
							}else{
								size_t len = strlen(target);
								if(len >= 3){
									if(pff->extension()==&target[2]){
										atFile(pff.get(),dir,target,bSubDir);
									}
								}
							}
						}else{
							atFile(pff.get(),dir,target,bSubDir);
						}
#else
						atFile(pff.get(),dir,target,bSubDir);
#endif
					}
				}else{
					atDot(pff.get(),dir,target,bSubDir);
				}
				//インクリメントぉ
				state->mLimitCount++;
			}while(pff->find_next());//成功する限りループをまわす。

			if(pff->is_error()){
				dODS(GetWin32LastErrorString());
				atError(pff.get(),dir,target,bSubDir);
				return false;
			}
			return true;

		}
		/*bool find(parm_string dir,bool subdir)
		{
			return base_type::find(dir.c_str(),"*.*",subdir);
		}*/
		bool find_limit(parm_string dir,bool subdir,size_t limit){
			return find_limit(dir.c_str(),"*.*",subdir,limit);
		}
	};



	//typedef std::deque<std::string> FOLDER_QUEUE;
private:
		typedef list_type CONTAINER_TYPE;
	/*
	///こいつはフォルダーだ！と断定する
	bool isFolder(WIN32_FIND_DATA &FindFileData){
		return (
			FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
			&& !isDot(FindFileData)
			);
	}
	bool isDot(const char *target){
		return (strcmp(target,"..")==0 ||
			 strcmp(target,".")==0 );
	}
	bool isDot(WIN32_FIND_DATA &FindFileData){
		return isDot(FindFileData.cFileName);
	}
	*/
	list_type mTargetList;

	std::string mDir;
	///フラグ
	UINT mFlag;
	///検索数のリミット
	size_type mLimit;


	list_type mFileList;

	//FOLDER_QUEUE mFolderQueue;

/*	bool find_logic(const char *dir,const char *target,bool subdir){
		
	
		policy::listup_file_functor<policy::generic_find_file_policy,CONTAINER_TYPE> func;
		
	
			
			return func(mFileList,dir,target,subdir);
		}
		if(isWildCard(target)){
			file_ext_listupper a(mFileList;
			return a.find(dir,target,subdir);
		}
		return func(mFileList,dir,target,subdir);
		

		

		
		//return listup_file(mFileList,dir,target,mbSubDir);
	}
	*/
public:
	enum{
		///サブディレクトリも検索する
		search_sub_directory = 1,
		//途中でエラーが起こっても　まだ処理が完了していない場合は できる限り検索する。
		search_as_much_as_possible = 2,
		///デフォルトの設定
		search_default = 
			search_sub_directory | search_as_much_as_possible,
	};
	file_listup_container(){
		mFlag = search_sub_directory;
		mLimit = 1010720;
	}
	virtual ~file_listup_container()
	{

	}
/*
class default_listup_file_functor{
public:
	typedef std::list<std::string> container_type;
	typedef file_listup_functor<policy::generic_find_file_policy,container_type> functor_type;
	
	bool operator()(container_type &x,parm_string dir,parm_string target,bool subdir,size_t limit)
	{
		

	}

};
*/
	std::string target()const{
		return *(mTargetList.begin());
	}
	list_type targets()const{
		return mTargetList;
	}
	/**
	@param target[in] ターゲットのファイル名（ワイルドカード可）
	@param dir[in] 検索を開始するディレクトリ
	@param flag[in] このクラス内に定義されているフラグを指定。デフォルトでssearch_default
	*/
	bool reset(parm_string target,parm_string dir,UINT flag = search_default)
	{
		mTargetList.clear();
		mTargetList.push_back(std::string(target.c_str()));
		mDir = dir.c_str();
		mFlag = flag;
		mFileList.clear();
		//mFolderQueue.clear();
		return true;
	}
	/**
	@param c[in] 中に拡張子とかが入っているコンテナ
	@param dir[in] ディレクトリ
	@param flag[in] @see reset()
	*/
	template<class T>
	bool reset_for_container(const T &c,parm_string dir,UINT flag = search_default){
		mTargetList.clear();

		T::const_iterator it = c.begin();
		for(;it != c.end();it++){
			mTargetList.push_back((*it));
		}
		
		mDir = dir;
		mFlag = flag;
		mFileList.clear();
		return true;
	}

	bool find()
	{
		bool r = false;
		bool subdir = (mFlag & search_sub_directory) != 0;
		bool amap = (mFlag & search_as_much_as_possible) != 0;
		
		mFileList.clear();

		file_ext_listupper<list_type> a(&mFileList,mFlag,mLimit);

		//a.setContainer(&mFileList);

		if(mTargetList.empty())
		{
			return false;
		}
		if(mTargetList.size()!=1)
		{
			if(false==	a.store_container(mTargetList))
			{//なんか全検索指定が入っていたようで･･･(´Д⊂ｸﾞｽﾝ
				return false;
			}
			r = a.find_limit(mDir.c_str(),subdir,mLimit);
		}else{
			//残りは１個のみ。
			policy::listup_file_functor<policy::generic_find_file_policy,CONTAINER_TYPE> func;
			r = func.find_limit(mFileList,mDir.c_str(),
				(*mTargetList.begin()).c_str(),subdir,
				mLimit);
		}
		if(amap && false==r && !mFileList.empty())
		{//とりあえず、途中までは成功
			return true;
		}

		return r;

		/*
		for(list_type::iterator it = mTargetList.begin();it != mTargetList.end();it++)
		{
			
			r = find_logic(mDir.c_str(),(*it).c_str(),subdir);
			if(false==r)
			{
				if(!mDir.empty() && *(mDir.end() - 1)==dkcdPATH_SEP)
				{//もしかしたら後ろについているPATH SEPARATORがダメなのかも？
					std::string td = mDir;
					td.erase(td.end() - 1);
					r = find_logic(td.c_str(),(*it).c_str(),subdir);
					if(r){
						//なんか上手くいったっぽいので 更新。
						mDir = td;
					}
				}
				if(false==amap && false==r){//上手く行かないときは問答無用でエラーとする。
					return r;
				}
			}
		}*/
	}//end of find()

	iterator begin(){
		return mFileList.begin();
	}
	const_iterator begin()const{
		return mFileList.begin();
	}
	iterator end(){
		return mFileList.end();
	}
	const_iterator end()const{
		return mFileList.end();
	}
	size_type size()const{
		return mFileList.size();
	}
	CONTAINER_TYPE &get_container(){
		return mFileList;
	}
	const CONTAINER_TYPE &get_contaienr()const{
		return  mFileList;;
	}
	///@param limit[in] 検索して格納する数の最大値
	void setLimit(size_type limit){
		//1310720
		mLimit = limit;
	}
	size_type getLimit()const{
		return mLimit;
	}

};

/**
検索したファイルを蓄えるインターフェイス 
@todo（ぶっちゃけ不毛なクラスなので削除予定だが･･･）
*/
template<class Container__>
class file_listup_accumulate_base{
public:
	typedef typename Container__ container_type;

	file_listup_accumulate_base(){
		reset(NULL);
	}

	bool reset(container_type *p,UINT flag = file_listup_container::search_default){
		mpc = p;
		mFlag = flag;
		return true;
	}
	bool find(parm_string appoint){
		PathSplit sp;
		sp.reset(appoint);
		std::string dir = sp.mDrive + sp.mDir;
		std::string ap = sp.mFname + sp.mExt;
		return find(dir,ap);
	}
	bool find(parm_string dir,parm_string target){
		container_type f;
		{//沢山の拡張子が指定されている場合
			std::string t;
			for(size_t i=0;i<target.size();i++)
			{
				if(target[i] == ';'){
					f.push_back(t);
					t.clear();
					continue;
				}
				t += target[i];
			}
		}
		//検索結果を元に指定分を探す。
		container_type::iterator it = f.begin();
		bool r = false;
		for(;it != f.end();it++)
		{
			r = find_base(dir,(*it));
			if(r==false && mFlag != file_listup_container::search_as_much_as_possible )
			{
				return false;
			}
		}
		return r;
	}
	container_type *getContainerPointer(){
		return mpc;
	}
protected:
	container_type *mpc;
	UINT mFlag;
	file_listup_container mC;
	bool find_base(	parm_string dir,parm_string target)
	{
		if(NULL==mpc){
			DKUTIL_THROW_OR_NOTICE(filesystem_error("file_listup_accumulate_base null container pointer"));
			return false;
		}
		DKUTIL_RETURN_FALSE(mC.reset(target,dir));
		DKUTIL_RETURN_FALSE(mC.find());
		file_listup_container::iterator it = mC.begin();
		for(;it != mC.end();it++){
			mpc->push_back((*it));
		}
		return true;
	}
};

typedef file_listup_accumulate_base<std::list<std::string> > file_listup_accumulate;

}//end of dkutil namespace








#endif //end of include once 
