⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adlsearch.h

📁 p2p技术C源代码.rar
💻 H
字号:
/* 
 * Copyright (C) 2001-2003 Jacek Sieka, j_s@telia.com
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/*
 * Automatic Directory Listing Search
 * Henrik Engstr鰉, henrikengstrom@home.se
 */

#if !defined(__ADLSEARCH_H__)
#define __ADLSEARCH_H__

#if _MSC_VER > 1000
#pragma once
#endif

#include "Util.h"

#include "SettingsManager.h"
#include "StringSearch.h"
#include "StringTokenizer.h"

///////////////////////////////////////////////////////////////////////////////
//
//	Class that represent an ADL search
//
///////////////////////////////////////////////////////////////////////////////
class ADLSearch
{
public:

	// Constructor
	ADLSearch() : searchString("<Enter string>"), isActive(true), sourceType(OnlyFile), 
		minFileSize(-1), maxFileSize(-1), destDir("ADLSearch"), ddIndex(0), typeFileSize(SizeBytes) {}

	// Prepare search
		void Prepare(StringMap& params)
		{
			// Prepare quick search of substrings
			stringSearchList.clear();

			// Replace parameters such as %[nick]
			string stringParams = Util::formatParams(searchString, params);

			// Split into substrings
			StringTokenizer st(stringParams, ' ');
			for(StringList::iterator i = st.getTokens().begin(); i != st.getTokens().end(); ++i)
			{
				if(i->size() > 0)
				{
					// Add substring search
					stringSearchList.push_back(StringSearch(*i));
				}
			}
		}

	// The search string
	string searchString;									 

	// Active search
	bool isActive;

	// Search source type
	enum SourceType
	{
		TypeFirst = 0,
		OnlyFile = TypeFirst,
		OnlyDirectory,
		FullPath,
		TypeLast
	} sourceType;
	SourceType StringToSourceType(const string& s)
	{
		if(Util::stricmp(s.c_str(), "Filename") == 0)
		{
			return OnlyFile;
		}
		else if(Util::stricmp(s.c_str(), "Directory") == 0)
		{
			return OnlyDirectory;
		}
		else if(Util::stricmp(s.c_str(), "Full Path") == 0)
		{
			return FullPath;
		}
		else
		{
			return OnlyFile;
		}
	}
	string SourceTypeToString(SourceType t)
	{
		switch(t)
		{
		default:
		case OnlyFile:		return "Filename";
		case OnlyDirectory:	return "Directory";
		case FullPath:		return "Full Path";
		}
	}

	// Maximum & minimum file sizes (in bytes). 
	// Negative values means do not check.
	int64_t minFileSize;
	int64_t maxFileSize;
	enum SizeType
	{
		SizeBytes     = TypeFirst,
		SizeKiloBytes,
		SizeMegaBytes,
		SizeGigaBytes
	};
	SizeType typeFileSize;
	SizeType StringToSizeType(const string& s)
	{
		if(Util::stricmp(s.c_str(), "B") == 0)
		{
			return SizeBytes;
		}
		else 
		if(Util::stricmp(s.c_str(), "kB") == 0)
		{
			return SizeKiloBytes;
		}
		else 
		if(Util::stricmp(s.c_str(), "MB") == 0)
		{
			return SizeMegaBytes;
		}
		else 
		if(Util::stricmp(s.c_str(), "GB") == 0)
		{
			return SizeGigaBytes;
		}
		else
		{
			return SizeBytes;
		}
	}
	string SizeTypeToString(SizeType t)
	{
		switch(t)
		{
		default:
		case SizeBytes:		return "B";
		case SizeKiloBytes:	return "kB";
		case SizeMegaBytes:	return "MB";
		case SizeGigaBytes:	return "GB";
		}
	}
	string SizeTypeToStringInternational(SizeType t)
	{
		switch(t)
		{
		default:
		case SizeBytes:		return CSTRING(B);
		case SizeKiloBytes:	return CSTRING(KB);
		case SizeMegaBytes:	return CSTRING(MB);
		case SizeGigaBytes:	return CSTRING(GB);
		}
	}
	int64_t GetSizeBase()
	{
		switch(typeFileSize)
		{
		default:
		case SizeBytes:		return (int64_t)1;
		case SizeKiloBytes:	return (int64_t)1024;
		case SizeMegaBytes:	return (int64_t)1024 * (int64_t)1024;
		case SizeGigaBytes:	return (int64_t)1024 * (int64_t)1024 * (int64_t)1024;
		}
	}

	// Name of the destination directory (empty = 'ADLSearch') and its index
	string destDir;
	unsigned long ddIndex;

	// Search for file match 
	bool MatchesFile(const string& f, const string& fp, int64_t size)
	{
		// Check status
		if(!isActive)
		{
			return false;
		}

		// Check size for files
		if(size >= 0 && (sourceType == OnlyFile || sourceType == FullPath))
		{
			if(minFileSize >= 0 && size < minFileSize * GetSizeBase())
			{
				// Too small
				return false;
			}
			if(maxFileSize >= 0 && size > maxFileSize * GetSizeBase())
			{
				// Too large
				return false;
			}
		}

		// Do search
		switch(sourceType)
		{
		default:
		case OnlyDirectory:	return false;
		case OnlyFile:		return SearchAll(f);
		case FullPath:		return SearchAll(fp);
		}
	}

	// Search for directory match 
	bool MatchesDirectory(const string& d)
	{
		// Check status
		if(!isActive)
		{
			return false;
		}
		if(sourceType != OnlyDirectory)
		{
			return false;
		}

		// Do search
		return SearchAll(d);
	}

private:

	// Substring searches
	StringSearch::List stringSearchList;
	bool SearchAll(const string& s)
	{
		// Match all substrings
		for(StringSearch::Iter i = stringSearchList.begin(); i != stringSearchList.end(); ++i)
		{
			if(!i->match(s))
			{
				return false;
			}
		}
		return (stringSearchList.size() != 0);
	}
};

///////////////////////////////////////////////////////////////////////////////
//
//	Class that holds all active searches
//
///////////////////////////////////////////////////////////////////////////////
#include "DirectoryListing.h"
class ADLSearchManager : public Singleton<ADLSearchManager>
{
public:

	// Constructor/destructor
	ADLSearchManager() { Load(); }
	virtual ~ADLSearchManager() { Save(); }

	// Search collection
	typedef vector<ADLSearch> SearchCollection;
	SearchCollection collection;

	// Load/save search collection to XML file
	void Load();
	void Save();

	// Settings
	GETSET(bool, breakOnFirst, BreakOnFirst);		

	// Search for file match
	void MatchesFile(DirectoryListing::File *currentFile, string& fullPath)
	{
		// Add to any substructure being stored
		for(vector<DestDir>::iterator id = destDirVector.begin(); id != destDirVector.end(); ++id)
		{
			if(id->subdir != NULL)
			{
				DirectoryListing::File *copyFile = new DirectoryListing::File(*currentFile);
				copyFile->setAdls(true);
				id->subdir->files.push_back(copyFile);
			}
			id->fileAdded = false;	// Prepare for next stage
		}

		// Prepare to match searches
		if(currentFile->getName().size() < 1)
		{
			return;
		}

		string filePath = fullPath + "\\" + currentFile->getName();
		// Match searches
		for(SearchCollection::iterator is = collection.begin(); is != collection.end(); ++is)
		{
			if(destDirVector[is->ddIndex].fileAdded)
			{
				continue;
			}
			if(is->MatchesFile(currentFile->getName(), filePath, currentFile->getSize()))
			{
				DirectoryListing::File *copyFile = new DirectoryListing::File(*currentFile);
				copyFile->setAdls(true);
				destDirVector[is->ddIndex].dir->files.push_back(copyFile);
				destDirVector[is->ddIndex].fileAdded = true;
				if(breakOnFirst)
				{
					// Found a match, search no more
					break;
				}
			}
		}
	}

	// Search for directory match
	void MatchesDirectory(DirectoryListing::Directory* currentDir, string& fullPath)
	{
		// Add to any substructure being stored
		for(vector<DestDir>::iterator id = destDirVector.begin(); id != destDirVector.end(); ++id)
		{
			if(id->subdir != NULL)
			{
				DirectoryListing::Directory* newDir = 
					new DirectoryListing::AdlDirectory(fullPath, id->subdir, currentDir->getName());
				id->subdir->directories.push_back(newDir);
				id->subdir = newDir;
			}
		}

		// Prepare to match searches
		if(currentDir->getName().size() < 1)
		{
			return;
		}

		// Match searches
		for(SearchCollection::iterator is = collection.begin(); is != collection.end(); ++is)
		{
			if(destDirVector[is->ddIndex].subdir != NULL)
			{
				continue;
			}
			if(is->MatchesDirectory(currentDir->getName()))
			{
				destDirVector[is->ddIndex].subdir = 
					new DirectoryListing::AdlDirectory(fullPath, destDirVector[is->ddIndex].dir, currentDir->getName());
				destDirVector[is->ddIndex].dir->directories.push_back(destDirVector[is->ddIndex].subdir);
				if(breakOnFirst)
				{
					// Found a match, search no more
					break;
				}
			}
		}
	}

	// Step up directory
	void StepUpDirectory()
	{
		for(vector<DestDir>::iterator id = destDirVector.begin(); id != destDirVector.end(); ++id)
		{
			if(id->subdir != NULL)
			{
				id->subdir = id->subdir->getParent();
				if(id->subdir == id->dir)
				{
					id->subdir = NULL;
				}
			}
		}
	}

	// Prepare destination directory indexing
	void PrepareDestinationDirectories(DirectoryListing::Directory* root, StringMap& params)
	{
		// Load default destination directory (index = 0)
		destDirVector.clear();
		vector<DestDir>::iterator id = destDirVector.insert(destDirVector.end());
		id->name = "ADLSearch";
		id->dir  = new DirectoryListing::Directory(root, "<<<" + id->name + ">>>", true);

		// Scan all loaded searches
		for(SearchCollection::iterator is = collection.begin(); is != collection.end(); ++is)
		{
			// Check empty destination directory
			if(is->destDir.size() == 0)
			{
				// Set to default
				is->ddIndex = 0;
				continue;
			}

			// Check if exists
			bool isNew = true;
			long ddIndex = 0;
			for(id = destDirVector.begin(); id != destDirVector.end(); ++id, ++ddIndex)
			{
				if(Util::stricmp(is->destDir.c_str(), id->name.c_str()) == 0)
				{
					// Already exists, reuse index
					is->ddIndex = ddIndex;
					isNew = false;
					break;
				}
			}
			if(isNew)
			{
				// Add new destination directory
				id = destDirVector.insert(destDirVector.end());
				id->name = is->destDir;
				id->dir  = new DirectoryListing::Directory(root, "<<<" + id->name + ">>>", true);
				is->ddIndex = ddIndex;
			}
		}
		// Prepare all searches
		for(SearchCollection::iterator ip = collection.begin(); ip != collection.end(); ++ip)
		{
			ip->Prepare(params);
		}
	}

	// Finalize destination directories
	void FinalizeDestinationDirectories(DirectoryListing::Directory* root)
	{
		string szDiscard = "<<<" + STRING(ADL_DISCARD) + ">>>";

		// Add non-empty destination directories to the top level
		for(vector<DestDir>::iterator id = destDirVector.begin(); id != destDirVector.end(); ++id)
		{
			if(id->dir->files.size() == 0 && id->dir->directories.size() == 0)
			{
				delete (id->dir);
			}
			else
			if(Util::stricmp(id->dir->getName(), szDiscard) == 0)
			{
				delete (id->dir);
			}
			else
			{
				root->directories.push_back(id->dir);
			}
		}
	}

private:

	// Destination directory indexing
	struct DestDir
	{
		string name;
		DirectoryListing::Directory* dir;
		DirectoryListing::Directory* subdir;
		bool fileAdded;
		DestDir() : name(""), dir(NULL), subdir(NULL) {}
	};
	vector<DestDir> destDirVector;
};


#endif

/**
 * @file
 * $Id: ADLSearch.h,v 1.6 2003/07/15 14:53:10 arnetheduck Exp $
 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -