// ffsco.cpp: implementation of the helper_coffs::ffsco class.
//
//////////////////////////////////////////////////////////////////////
/*
 * Copyright 2004, ??? (www.???.com). All rights reserved.
 * Copyright 1990-2004, ???.
 *
 * See the COPYING file for the terms of usage and distribution.
 */
//////////////////////////////////////////////////////////////////////
// ...
// create@2004-03-17
// by ???
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"	//--i want remove it
#include "ffsco.h"
#include <windows.h>
namespace helper_coffs {
	//////////////////////////////////////////////////////////////////////
	// Construction/Destruction
	//////////////////////////////////////////////////////////////////////

	ffsco::ffsco(): _limit(def_limit), _dirs(0)
	{

	}

	ffsco::~ffsco()
	{

	}

	//////////////////////////////////////////////////////////////////////
	tstring ffsco::_uppercase_(tstring s)
	{
		const char aazz = 'z' - 'Z';
		tstring rs;
		for (tstring::iterator it = s.begin();s.end() != it; it++)
		{
			if ('a' <= *it && *it <= 'z') rs.append(1, *it - aazz);
			else rs.append(1, *it);
		}
		return rs;
	}
	//////////////////////////////////////////////////////////////////////

	int ffsco::match(tstring fext_, tstring file_)
	{
		tstring fext = _uppercase_(fext_);
		tstring file = _uppercase_(file_);

		int pos = file.find_last_of('.');
		if (tstring::npos != pos) file = file.substr(pos);

		return (tstring::npos != fext.find(file));
	}

	void ffsco::limit(int limit_)
	{
		if (limit_ < 1) _limit = def_limit;
		if (limit_ < max_limit) _limit = limit_;
	}

	int ffsco::dir(tstring s)
	{
		return (FILE_ATTRIBUTE_DIRECTORY == GetFileAttributes(s.c_str()));
	}

	int ffsco::find(tstring path_, tstring fext_)
	{
		_co_file.clear();
		_co_dir.clear();
		_co.clear();

		tstring path = path_;
		if (path.size() > 0 && c_pathSeparator != path[path.size() - 1])
			path.append(s_pathSeparator);

		_co_dir.push_back(path);

		tstring fext = fext_;
		if (0 == fext.compare(_T("*")) || 0 == fext.compare(_T("*.*"))) 
			fext = _T("");

		//string file = fext;
		tstring file = _T("*");

		tstring s = path + file;

		WIN32_FIND_DATA fileinfo = { 0 };
		HANDLE handle = FindFirstFile(s.c_str(), &fileinfo);

		if (NULL != handle && INVALID_HANDLE_VALUE != handle)
		{

			do {

				if (checkcount()) break;	//--limit test

				if ('.' != fileinfo.cFileName[0])	//--skip./..
				if ((FILE_ATTRIBUTE_DIRECTORY & fileinfo.dwFileAttributes) == FILE_ATTRIBUTE_DIRECTORY)	//--Ŀ¼
				{
					if (!checkcount()	//--limit test
						//&& 0 == fext.size()
						) _co_dir.push_back(path + fileinfo.cFileName + s_pathSeparator);

					if (0 != dirs())
					{
						ffsco o;
						o.dirs(dirs());
						o.find(path + fileinfo.cFileName, fext);
						//--dir
						typeT o_dir = o.co_dir();
						for (typeT::iterator it_dir = o_dir.begin();
							o_dir.end() != it_dir && !checkcount();	//--limit test
							it_dir++) _co_dir.push_back(*it_dir);
						//--file
						typeT o_file = o.co_file();
						for (typeT::iterator it_file = o_file.begin();
							o_file.end() != it_file && !checkcount();	//--limit test
							it_file++) _co_file.push_back(*it_file);
					}
				}
				else
				{
					if (!checkcount()	//--limit test
						&& (0 == fext.size() || match(fext, fileinfo.cFileName))
						) _co_file.push_back(path + fileinfo.cFileName);
				}

			} while (FindNextFile(handle, &fileinfo));

			FindClose(handle);
		}

		//--dir
		for (typeT::iterator it_dir = _co_dir.begin();
			_co_dir.end() != it_dir;
			it_dir++) _co.push_back(*it_dir);
		//--file
		for (typeT::iterator it_file = _co_file.begin();
			_co_file.end() != it_file;
			it_file++) _co.push_back(*it_file);

		return count();
	}

	//--example
	void ffsco::test()
	{
		TCHAR win32sys_path[MAX_PATH] = { 0 };
		::GetSystemDirectory(win32sys_path, MAX_PATH);

		tstring path = win32sys_path;
		tstring fext = _T("*.dll; *.exe; *.ini; *.sys");
		//string fext;

		ffsco o;
		//o.dirs(1);	//--������Ŀ¼
		o.limit(100);	//--������100��
		int count = o.find(path, fext);
		//int count = o.find(path);
		int count_dir = o.co_dir().size();
		int count_file = o.co_file().size();

		//--first
		::MessageBox(NULL, o.get().data(), _T("ffsco.test.path"), MB_OK);

		ffsco::typeT coo;
		ffsco::typeT::iterator it;
		tstring s;
#ifdef UNICODE
		wstringstream ss;
#else
		stringstream ss;
#endif

		//--all
		coo = o.co();
		s.erase();
		ss.str(_T(""));
		ss << coo.size();
		s.append(_T("list = ") + ss.str() + _T("\r\n"));
		for (it = coo.begin(); coo.end() != it; it++)
		{
			s.append(*it);
			s.append(_T("\r\n"));
		}
		::MessageBox(NULL, s.c_str(), _T("ffsco.test.all"), MB_OK);

		//--dir
		coo = o.co_dir();
		s.erase();
		ss.str(_T(""));
		ss << coo.size();
		s.append(_T("list = ") + ss.str() + _T("\r\n"));
		for (it = coo.begin(); coo.end() != it; it++)
		{
			s.append(*it);
			s.append(_T("\r\n"));
		}
		::MessageBox(NULL, s.c_str(), _T("ffsco.test.dir"), MB_OK);

		//--file
		coo = o.co_file();
		s.erase();
		ss.str(_T(""));
		ss << coo.size();
		s.append(_T("list = ") + ss.str() + _T("\r\n"));
		for (it = coo.begin(); coo.end() != it; it++)
		{
			s.append(*it);
			s.append(_T("\r\n"));
		}
		::MessageBox(NULL, s.c_str(), _T("ffsco.test.file"), MB_OK);
	}

};	//--namespace helper_coffs