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

📄 librarydictionary.cpp

📁 p2p软件
💻 CPP
字号:
//
// LibraryDictionary.cpp
//
// Copyright (c) Shareaza Development Team, 2002-2004.
// This file is part of SHAREAZA (www.shareaza.com)
//
// Shareaza 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.
//
// Shareaza 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 Shareaza; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//

#include "StdAfx.h"
#include "Shareaza.h"
#include "Settings.h"
#include "Library.h"
#include "LibraryMaps.h"
#include "LibraryDictionary.h"
#include "SharedFile.h"

#include "QueryHashTable.h"
#include "QuerySearch.h"

#include "Schema.h"
#include "XML.h"

#include "SHA.h"
#include "ED2K.h"
#include "TigerTree.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

CLibraryDictionary LibraryDictionary;


//////////////////////////////////////////////////////////////////////
// CLibraryDictionary construction

CLibraryDictionary::CLibraryDictionary() : m_pWords( 64 )
{
	m_pTable = NULL;
	m_bTable = FALSE;
	
	m_nSearchCookie = 1;
}

CLibraryDictionary::~CLibraryDictionary()
{
	Clear();
	if ( m_pTable ) delete m_pTable;
}

//////////////////////////////////////////////////////////////////////
// CLibraryDictionary add and remove

void CLibraryDictionary::Add(CLibraryFile* pFile)
{
	ProcessFile( pFile, TRUE );
	
	if ( ( pFile->m_bSHA1 || pFile->m_bED2K ) && ! BuildHashTable() )
	{
		if ( pFile->m_bSHA1 )
		{
			m_pTable->AddString( CSHA::HashToString( &pFile->m_pSHA1, TRUE ) );
		}
		if ( pFile->m_bED2K )
		{
			m_pTable->AddString( CED2K::HashToString( &pFile->m_pED2K, TRUE ) );
		}
	}
}

void CLibraryDictionary::Remove(CLibraryFile* pFile)
{
	ProcessFile( pFile, FALSE );
	
	// TODO: Always invalidate the table when removing a hashed
	// file... is this wise???  It will happen all the time.
	
	if ( pFile->m_bSHA1 || pFile->m_bED2K ) m_bTable = FALSE;
}

//////////////////////////////////////////////////////////////////////
// CLibraryDictionary file and and remove

void CLibraryDictionary::ProcessFile(CLibraryFile* pFile, BOOL bAdd)
{
	ProcessPhrase( pFile, pFile->GetSearchName(), bAdd, FALSE );
	
	if ( pFile->m_pMetadata )
	{
		ProcessWord( pFile, pFile->m_pSchema->m_sURI, bAdd );
		ProcessPhrase( pFile, pFile->GetMetadataWords(), bAdd );
	}
}

//////////////////////////////////////////////////////////////////////
// CLibraryDictionary phrase parser

int CLibraryDictionary::ProcessPhrase(CLibraryFile* pFile, const CString& strPhrase, BOOL bAdd, BOOL bLowercase)
{
	LPCTSTR pszPtr = strPhrase;
	CString strWord;
	int nCount = 0;
	
	for ( int nStart = 0, nPos = 0 ; *pszPtr ; nPos++, pszPtr++ )
	{
		if ( ! IsCharacter( *pszPtr ) )
		{
			if ( nStart < nPos && IsWord( strPhrase, nStart, nPos - nStart ) )
			{
				strWord = strPhrase.Mid( nStart, nPos - nStart );
				if ( bLowercase ) strWord.MakeLower();
				ProcessWord( pFile, strWord, bAdd );
				nCount++;
				
				if ( nPos - nStart >= 5 && Settings.Library.PartialMatch )
				{
					strWord = strPhrase.Mid( nStart, nPos - nStart - 1 );
					if ( bLowercase ) strWord.MakeLower();
					ProcessWord( pFile, strWord, bAdd );
					nCount++;
					
					strWord = strPhrase.Mid( nStart, nPos - nStart - 2 );
					if ( bLowercase ) strWord.MakeLower();
					ProcessWord( pFile, strWord, bAdd );
					nCount++;
				}
			}
			nStart = nPos + 1;
		}
	}
	
	if ( nStart < nPos && IsWord( strPhrase, nStart, nPos - nStart ) )
	{
		strWord = strPhrase.Mid( nStart, nPos - nStart );
		if ( bLowercase ) strWord.MakeLower();
		ProcessWord( pFile, strWord, bAdd );
		nCount++;
		
		if ( nPos - nStart >= 5 && Settings.Library.PartialMatch )
		{
			strWord = strPhrase.Mid( nStart, nPos - nStart - 1 );
			if ( bLowercase ) strWord.MakeLower();
			ProcessWord( pFile, strWord, bAdd );
			nCount++;
			
			strWord = strPhrase.Mid( nStart, nPos - nStart - 2 );
			if ( bLowercase ) strWord.MakeLower();
			ProcessWord( pFile, strWord, bAdd );
			nCount++;
		}
	}
	
	return nCount;
}

//////////////////////////////////////////////////////////////////////
// CLibraryDictionary word add and remove

void CLibraryDictionary::ProcessWord(CLibraryFile* pFile, const CString& strWord, BOOL bAdd)
{
	CLibraryWord* pWord;
	
	if ( m_pWords.Lookup( strWord, (void*&)pWord ) )
	{
		if ( bAdd )
		{
			pWord->Add( pFile );
		}
		else
		{
			if ( ! pWord->Remove( pFile ) )
			{
				m_pWords.RemoveKey( strWord );
				delete pWord;
				m_bTable = FALSE;
			}
		}
	}
	else if ( bAdd )
	{
		pWord = new CLibraryWord();
		pWord->Add( pFile );
		m_pWords.SetAt( strWord, pWord );

		if ( ! BuildHashTable() ) m_pTable->AddString( strWord );
	}
}

//////////////////////////////////////////////////////////////////////
// CLibraryDictionary build hash table

BOOL CLibraryDictionary::BuildHashTable()
{
	if ( m_pTable == NULL )
	{
		m_pTable = new CQueryHashTable();
		m_pTable->Create();
	}
	
	if ( m_bTable ) return FALSE;
	
	m_pTable->Clear();
	
	for ( POSITION pos = m_pWords.GetStartPosition() ; pos ; )
	{
		CLibraryWord* pWord;
		CString strWord;
		
		m_pWords.GetNextAssoc( pos, strWord, (void*&)pWord );
		m_pTable->AddString( strWord );
	}
	
	for ( pos = LibraryMaps.GetFileIterator() ; pos ; )
	{
		CLibraryFile* pFile = LibraryMaps.GetNextFile( pos );
		
		if ( pFile->m_bSHA1 )
		{
			m_pTable->AddString( CSHA::HashToString( &pFile->m_pSHA1, TRUE ) );
		}
		if ( pFile->m_bED2K )
		{
			m_pTable->AddString( CED2K::HashToString( &pFile->m_pED2K, TRUE ) );
		}
	}
	
	m_bTable = TRUE;
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CLibraryDictionary retreive hash table

CQueryHashTable* CLibraryDictionary::GetHashTable()
{
	if ( ! Library.Lock( 500 ) ) return NULL;
	
	BuildHashTable();
	
	return m_pTable;
}

//////////////////////////////////////////////////////////////////////
// CLibraryDictionary clear

void CLibraryDictionary::Clear()
{
	for ( POSITION pos = m_pWords.GetStartPosition() ; pos ; )
	{
		CLibraryWord* pWord;
		CString strWord;
		
		m_pWords.GetNextAssoc( pos, strWord, (void*&)pWord );
		delete pWord;
	}
	
	m_pWords.RemoveAll();
	
	if ( m_pTable != NULL )
	{
		m_pTable->Clear();
		m_bTable = TRUE;
	}
}

//////////////////////////////////////////////////////////////////////
// CLibraryDictionary search

CPtrList* CLibraryDictionary::Search(CQuerySearch* pSearch, int nMaximum, BOOL bLocal)
{
	BuildHashTable();
	
	if ( ! m_pTable->Check( pSearch ) ) return NULL;
	
	DWORD nCookie = m_nSearchCookie++;
	
	CLibraryFile* pHit = NULL;
	
	LPCTSTR* pWordPtr	= pSearch->m_pWordPtr;
	DWORD* pWordLen		= pSearch->m_pWordLen;
	
	for ( int nWord = pSearch->m_nWords ; nWord > 0 ; nWord--, pWordPtr++, pWordLen++ )
	{
		if ( **pWordPtr == '-' ) continue;
		
		LPTSTR pszNull = (LPTSTR)(*pWordPtr) + *pWordLen;
		TCHAR cNull = *pszNull;
		*pszNull = 0;
		
		CLibraryWord* pWord;
		
		if ( m_pWords.Lookup( *pWordPtr, (void*&)pWord ) )
		{
			CLibraryFile** pFiles	= pWord->m_pList;
			CLibraryFile* pLastFile	= NULL;
			
			for ( DWORD nFileCount = pWord->m_nCount ; nFileCount ; nFileCount--, pFiles++ )
			{
				CLibraryFile* pFile = *pFiles;
				
				if ( pFile == pLastFile ) continue;
				pLastFile = pFile;
				
				if ( ! bLocal && ! pFile->IsShared() ) continue;
				
				if ( pFile->m_nSearchCookie == nCookie )
				{
					pFile->m_nSearchWords ++;
				}
				else
				{
					pFile->m_nSearchCookie	= nCookie;
					pFile->m_nSearchWords	= 1;
					pFile->m_pNextHit		= pHit;
					pHit = pFile;
				}
			}
		}
		
		*pszNull = cNull;
	}
	
	DWORD nLowerBound = pSearch->m_nWords >= 3 ? pSearch->m_nWords * 2 / 3 : pSearch->m_nWords;
	
	CPtrList* pHits = NULL;
	int nCount = 0;
	
	for ( ; pHit ; pHit = pHit->m_pNextHit )
	{
		if ( pHit->m_nSearchCookie == nCookie && pHit->m_nSearchWords >= nLowerBound )
		{
			if ( pSearch->Match( pHit->GetSearchName(), pHit->m_nSize,
					pHit->m_pSchema ? (LPCTSTR)pHit->m_pSchema->m_sURI : NULL,
					pHit->m_pMetadata,
					pHit->m_bSHA1 ? &pHit->m_pSHA1 : NULL,
					pHit->m_bTiger ? &pHit->m_pTiger : NULL,
					pHit->m_bED2K ? &pHit->m_pED2K : NULL ) )
			{
				if ( ! pHits ) pHits = new CPtrList();
				pHits->AddTail( pHit );
				
				if ( ! bLocal )
				{
					pHit->m_nHitsToday++;
					pHit->m_nHitsTotal++;
				}
				
				if ( pHit->m_nCollIndex )
				{
					if ( CLibraryFile* pCollection = LibraryMaps.LookupFile( pHit->m_nCollIndex, FALSE, ! bLocal, TRUE ) )
					{
						if ( pCollection->m_nSearchCookie != nCookie )
						{
							pCollection->m_nSearchCookie = nCookie;
							pHits->AddHead( pCollection );
						}
					}
					else
					{
						pHit->m_nCollIndex = 0;
					}
				}
				
				if ( nMaximum && ++nCount >= nMaximum ) break;
			}
		}
	}
	
	return pHits;
}


//////////////////////////////////////////////////////////////////////
// CLibraryWord construction

CLibraryWord::CLibraryWord()
{
	m_pList		= NULL;
	m_nCount	= 0;
}

CLibraryWord::~CLibraryWord()
{
	if ( m_pList ) delete [] m_pList;
}

//////////////////////////////////////////////////////////////////////
// CLibraryWord add and remove

void CLibraryWord::Add(CLibraryFile* pFile)
{
	CLibraryFile** pList = new CLibraryFile*[ m_nCount + 1 ];
	
	if ( m_pList )
	{
		CopyMemory( pList, m_pList, m_nCount * sizeof(CLibraryFile*) );
		delete [] m_pList;
	}
	
	m_pList = pList;
	m_pList[ m_nCount++ ] = pFile;
}

BOOL CLibraryWord::Remove(CLibraryFile* pFile)
{
	CLibraryFile** pSearch = m_pList;
	
	for ( DWORD nSearch = m_nCount ; nSearch ; nSearch--, pSearch++ )
	{
		if ( *pSearch == pFile )
		{
			for ( m_nCount--, nSearch-- ; nSearch ; nSearch--, pSearch++ )
			{
				*pSearch = pSearch[1];
			}
			break;
		}
	}
	
	return ( m_nCount > 0 );
}

⌨️ 快捷键说明

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