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

📄 matchobjects.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// MatchObjects.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 "MatchObjects.h"
#include "QuerySearch.h"
#include "QueryHit.h"
#include "Library.h"
#include "SharedFile.h"
#include "Schema.h"
#include "Security.h"
#include "ShellIcons.h"
#include "VendorCache.h"
#include "Downloads.h"
#include "Transfers.h"
#include "XML.h"

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

#include "CtrlMatch.h"
#include "LiveList.h"

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

#define MAP_SIZE		256
#define BUFFER_GROW		64


//////////////////////////////////////////////////////////////////////
// CMatchList construction

CMatchList::CMatchList()
{
	m_bFilterBusy		= ( Settings.Search.FilterMask & ( 1 << 0 ) ) > 0;
	m_bFilterPush		= ( Settings.Search.FilterMask & ( 1 << 1 ) ) > 0;
	m_bFilterUnstable	= ( Settings.Search.FilterMask & ( 1 << 2 ) ) > 0;
	m_bFilterReject		= ( Settings.Search.FilterMask & ( 1 << 3 ) ) > 0;
	m_bFilterLocal		= ( Settings.Search.FilterMask & ( 1 << 4 ) ) > 0;
	m_bFilterBogus		= ( Settings.Search.FilterMask & ( 1 << 5 ) ) > 0;
	m_nFilterMinSize	= 1;
	m_nFilterMaxSize	= 0;
	m_nFilterSources	= 1;
	m_nSortColumn		= -1;
	m_bSortDir			= 1;
	m_pSchema			= NULL;
	m_bNew				= FALSE;
	
	m_pFiles			= NULL;
	m_nFiles			= 0;
	m_nItems			= 0;
	m_nFilteredFiles	= 0;
	m_nFilteredHits		= 0;
	
	m_nBuffer	= 0;
	m_pSizeMap	= new CMatchFile*[ MAP_SIZE ];
	m_pMapSHA1	= new CMatchFile*[ MAP_SIZE ];
	m_pMapTiger	= new CMatchFile*[ MAP_SIZE ];
	m_pMapED2K	= new CMatchFile*[ MAP_SIZE ];
	m_pszFilter	= NULL;
	m_pColumns	= NULL;
	m_nColumns	= 0;
	
	ClearUpdated();
	
	ZeroMemory( m_pSizeMap, 4 * MAP_SIZE );
	ZeroMemory( m_pMapSHA1, 4 * MAP_SIZE );
	ZeroMemory( m_pMapTiger, 4 * MAP_SIZE );
	ZeroMemory( m_pMapED2K, 4 * MAP_SIZE );
	
	SetSortColumn( MATCH_COL_COUNT, TRUE );
}

CMatchList::~CMatchList()
{
	Clear();
	
	if ( m_pColumns ) delete [] m_pColumns;
	
	if ( m_pszFilter ) delete [] m_pszFilter;
	
	delete [] m_pMapED2K;
	delete [] m_pMapTiger;
	delete [] m_pMapSHA1;
	delete [] m_pSizeMap;
	
	if ( m_pFiles ) delete [] m_pFiles;
}

//////////////////////////////////////////////////////////////////////
// CMatchList add hits

void CMatchList::AddHits(CQueryHit* pHit, CQuerySearch* pFilter, BOOL bRequire)
{
	CSingleLock pLock( &m_pSection, TRUE );
	CMatchFile **pMap, *pSeek;
	
	while ( pHit )
	{
		CQueryHit* pNext = pHit->m_pNext;
		
		if ( Security.IsDenied( &pHit->m_pAddress, pHit->m_sName ) )
		{
			delete pHit;
			pHit = pNext;
			continue;
		}
		
		pHit->m_bNew = m_bNew;
		
		if ( pFilter != NULL )
		{
			pHit->m_bMatched = pFilter->Match(
				pHit->m_sName, pHit->m_nSize, pHit->m_sSchemaURI, pHit->m_pXML,
				pHit->m_bSHA1 ? &pHit->m_pSHA1 : NULL,
				pHit->m_bTiger ? &pHit->m_pTiger : NULL,
				pHit->m_bED2K ? &pHit->m_pED2K : NULL );
			
			if ( bRequire && ! pHit->m_bMatched )
			{
				delete pHit;
				pHit = pNext;
				continue;
			}
			
			if ( Settings.Search.SchemaTypes && pFilter->m_pSchema && ! pHit->m_bBogus )
			{
				if ( pFilter->m_pSchema->CheckURI( pHit->m_sSchemaURI ) )
				{
					pHit->m_bBogus = FALSE;
				}
				else
				{
					pHit->m_bBogus = ! pFilter->m_pSchema->FilterType( pHit->m_sName, TRUE );
				}
			}
		}
		else
		{
			pHit->m_bMatched = TRUE;
		}
		
		FilterHit( pHit );
		
		CMatchFile* pFile	= NULL;
		BOOL bHadSHA1		= FALSE;
		BOOL bHadTiger		= FALSE;
		BOOL bHadED2K		= FALSE;
		int nHadCount		= 0;
		int nHadFiltered	= 0;
		BOOL bHad[3];
		
		if ( pHit->m_bSHA1 )
		{
			pMap = m_pMapSHA1 + ( pHit->m_pSHA1.n[0] );
			
			for ( pSeek = *pMap ; pSeek ; pSeek = pSeek->m_pNextSHA1 )
			{
				if ( pSeek->m_pSHA1 == pHit->m_pSHA1 )
				{
					nHadCount		= pSeek->GetItemCount();
					nHadFiltered	= pSeek->m_nFiltered;
					
					bHad[0] = pSeek->m_bSHA1; bHad[1] = pSeek->m_bTiger; bHad[2] = pSeek->m_bED2K;
					
					if ( pSeek->Add( pHit, TRUE ) )
					{
						pFile		 = pSeek;
						bHadSHA1	|= bHad[0];
						bHadTiger	|= bHad[1];
						bHadED2K	|= bHad[2];
						break;
					}
				}
			}
		}
		if ( pFile == NULL && pHit->m_bTiger )
		{
			pMap = m_pMapTiger + ( pHit->m_pTiger.n[0] );
			
			for ( pSeek = *pMap ; pSeek ; pSeek = pSeek->m_pNextTiger )
			{
				if ( pSeek->m_pTiger == pHit->m_pTiger )
				{
					nHadCount		= pSeek->GetItemCount();
					nHadFiltered	= pSeek->m_nFiltered;
					
					bHad[0] = pSeek->m_bSHA1; bHad[1] = pSeek->m_bTiger; bHad[2] = pSeek->m_bED2K;
					
					if ( pSeek->Add( pHit, TRUE ) )
					{
						pFile		 = pSeek;
						bHadSHA1	|= bHad[0];
						bHadTiger	|= bHad[1];
						bHadED2K	|= bHad[2];
						break;
					}
				}
			}
		}
		if ( pFile == NULL && pHit->m_bED2K )
		{
			pMap = m_pMapED2K + ( pHit->m_pED2K.n[0] );
			
			for ( pSeek = *pMap ; pSeek ; pSeek = pSeek->m_pNextED2K )
			{
				if ( pSeek->m_pED2K == pHit->m_pED2K )
				{
					nHadCount		= pSeek->GetItemCount();
					nHadFiltered	= pSeek->m_nFiltered;
					
					bHad[0] = pSeek->m_bSHA1; bHad[1] = pSeek->m_bTiger; bHad[2] = pSeek->m_bED2K;
					
					if ( pSeek->Add( pHit, TRUE ) )
					{
						pFile		 = pSeek;
						bHadSHA1	|= bHad[0];
						bHadTiger	|= bHad[1];
						bHadED2K	|= bHad[2];
						break;
					}
				}
			}
		}
		
		if ( pFile == NULL && ( ( ! pHit->m_bSHA1 && ! pHit->m_bTiger && ! pHit->m_bED2K ) || ! Settings.General.HashIntegrity ) )
		{
			pMap = m_pSizeMap + (DWORD)( pHit->m_nSize & 0xFF );

			for ( pSeek = *pMap ; pSeek ; pSeek = pSeek->m_pNextSize )
			{
				if ( pSeek->m_nSize == pHit->m_nSize )
				{
					bHadSHA1		= pSeek->m_bSHA1;
					bHadTiger		= pSeek->m_bTiger;
					bHadED2K		= pSeek->m_bED2K;
					nHadCount		= pSeek->GetItemCount();
					nHadFiltered	= pSeek->m_nFiltered;

					if ( pSeek->Add( pHit ) )
					{
						pFile = pSeek;
						break;
					}
				}
			}
			
			if ( ! pFile ) bHadSHA1 = bHadTiger = bHadED2K = FALSE;
		}
		
		if ( pFile != NULL )
		{
			pMap = m_pFiles;
			
			for ( DWORD nCount = m_nFiles ; nCount ; nCount--, pMap++ )
			{
				if ( *pMap == pFile )
				{
					if ( m_nSortColumn >= 0 )
					{
						UpdateRange( m_nFiles - nCount );
						MoveMemory( pMap, pMap + 1, ( nCount - 1 ) << 2 );
						m_nFiles--;
						InsertSorted( pFile );
					}
					else
					{
						UpdateRange( m_nFiles - nCount, m_nFiles - nCount );
					}
					
					break;
				}
			}
			
			if ( nHadCount )
			{
				m_nItems -= nHadCount;
				m_nFilteredFiles --;
				m_nFilteredHits -= nHadFiltered;
			}
		}
		else
		{
			pFile = new CMatchFile( this, pHit );
			pFile->m_bNew = m_bNew;
			
			pMap = m_pSizeMap + (DWORD)( pFile->m_nSize & 0xFF );
			pFile->m_pNextSize = *pMap;
			*pMap = pFile;
			
			if ( m_nFiles + 1 > m_nBuffer )
			{
				m_nBuffer += BUFFER_GROW;
				CMatchFile** pFiles = new CMatchFile*[ m_nBuffer ];
				
				if ( m_pFiles )
				{
					CopyMemory( pFiles, m_pFiles, m_nFiles << 2 );
					delete [] m_pFiles;
				}
				
				m_pFiles = pFiles;
			}
			
			if ( m_nSortColumn >= 0 )
			{
				InsertSorted( pFile );
			}
			else
			{
				UpdateRange( m_nFiles );
				m_pFiles[ m_nFiles++ ] = pFile;
			}
		}
		
		if ( ! bHadSHA1 && pFile->m_bSHA1 )
		{
			pMap = m_pMapSHA1 + ( pFile->m_pSHA1.n[0] );
			pFile->m_pNextSHA1 = *pMap;
			*pMap = pFile;
		}
		if ( ! bHadTiger && pFile->m_bTiger )
		{
			pMap = m_pMapTiger + ( pFile->m_pTiger.n[0] );
			pFile->m_pNextTiger = *pMap;
			*pMap = pFile;
		}
		if ( ! bHadED2K && pFile->m_bED2K )
		{
			pMap = m_pMapED2K + ( pFile->m_pED2K.n[0] );
			pFile->m_pNextED2K = *pMap;
			*pMap = pFile;
		}
		
		nHadCount = pFile->GetItemCount();
		
		if ( nHadCount )
		{
			m_nItems += nHadCount;
			m_nFilteredFiles ++;
			m_nFilteredHits += pFile->m_nFiltered;
		}
		
		pHit = pNext;
	}
}

//////////////////////////////////////////////////////////////////////
// CMatchList insert to a sorted array

void CMatchList::InsertSorted(CMatchFile* pFile)
{
	for ( int nFirst = 0, nLast = m_nFiles - 1 ; nLast >= nFirst ; )
	{
		DWORD nMiddle = ( nFirst + nLast ) >> 1;

		if ( pFile->Compare( m_pFiles[ nMiddle ] ) == m_bSortDir )
		{
			nFirst = nMiddle + 1;
		}
		else
		{
			nLast = nMiddle - 1;
		}
	}

	MoveMemory( m_pFiles + nFirst + 1, m_pFiles + nFirst, ( m_nFiles - nFirst ) << 2 );
	m_pFiles[ nFirst ] = pFile;
	m_nFiles++;
	UpdateRange( nFirst );
}

//////////////////////////////////////////////////////////////////////
// CMatchList searching

DWORD CMatchList::FileToItem(CMatchFile* pFile)
{
	CSingleLock pLock( &m_pSection, TRUE );

	CMatchFile** pLoop = m_pFiles;

	for ( DWORD nCount = 0 ; nCount < m_nFiles ; nCount++, pLoop++ )
	{
		if ( *pLoop == pFile ) return nCount;
	}

	return 0xFFFFFFFF;
}

//////////////////////////////////////////////////////////////////////
// CMatchList clear

void CMatchList::Clear()
{
	CSingleLock pLock( &m_pSection, TRUE );

	if ( m_pFiles )
	{
		CMatchFile** pLoop = m_pFiles;

		for ( DWORD nCount = m_nFiles ; nCount ; nCount--, pLoop++ )
		{
			if ( *pLoop ) delete (*pLoop);
		}
	}

	m_nFiles			= 0;
	m_nItems			= 0;
	m_nFilteredFiles	= 0;
	m_nFilteredHits		= 0;

	m_pSelectedFiles.RemoveAll();
	m_pSelectedHits.RemoveAll();

	ZeroMemory( m_pSizeMap, 4 * MAP_SIZE );
	ZeroMemory( m_pMapSHA1, 4 * MAP_SIZE );
	ZeroMemory( m_pMapTiger, 4 * MAP_SIZE );
	ZeroMemory( m_pMapED2K, 4 * MAP_SIZE );

	UpdateRange();
}

//////////////////////////////////////////////////////////////////////
// CMatchList selection

BOOL CMatchList::Select(CMatchFile* pFile, CQueryHit* pHit, BOOL bSelected)
{
	if ( pHit != NULL )
	{
		if ( pHit->m_bSelected == bSelected ) return FALSE;
		pHit->m_bSelected = bSelected;

		if ( bSelected )
			m_pSelectedHits.AddTail( pHit );
		else
			m_pSelectedHits.RemoveAt( m_pSelectedHits.Find( pHit ) );
	}
	else
	{
		if ( pFile->m_bSelected == bSelected ) return FALSE;
		pFile->m_bSelected = bSelected;

		if ( bSelected )
			m_pSelectedFiles.AddTail( pFile );
		else
			m_pSelectedFiles.RemoveAt( m_pSelectedFiles.Find( pFile ) );
	}
	
	if ( pFile != NULL )
	{
		DWORD nIndex = FileToItem( pFile );
		UpdateRange( nIndex, nIndex );
	}
	
	return TRUE;
}

CMatchFile* CMatchList::GetSelectedFile(BOOL bFromHit) const
{
	if ( m_pSelectedFiles.GetCount() != 1 )
	{
		if ( bFromHit == FALSE ) return NULL;
		
		CQueryHit* pHit = GetSelectedHit();
		if ( pHit == NULL ) return NULL;
		
		CMatchFile** pLoop = m_pFiles;
		
		for ( DWORD nCount = m_nFiles ; nCount ; nCount--, pLoop++ )
		{
			if ( (*pLoop)->Check( pHit ) ) return *pLoop;
		}
		
		return NULL;
	}
	
	return (CMatchFile*)m_pSelectedFiles.GetHead();
}

CQueryHit* CMatchList::GetSelectedHit() const
{
	if ( m_pSelectedHits.GetCount() != 1 )
	{
		if ( m_pSelectedFiles.GetCount() != 1 ) return NULL;
		CMatchFile* pFile = (CMatchFile*)m_pSelectedFiles.GetHead();
		return pFile->m_nFiltered == 1 ? pFile->m_pHits : NULL;
	}
	
	return (CQueryHit*)m_pSelectedHits.GetHead();
}

int CMatchList::GetSelectedCount() const
{
	return m_pSelectedFiles.GetCount() + m_pSelectedHits.GetCount();
}

BOOL CMatchList::ClearSelection()
{
	CSingleLock pLock( &m_pSection, TRUE );
	
	CMatchFile** pLoop = m_pFiles;
	BOOL bChanged = FALSE;
	
	for ( DWORD nCount = 0 ; nCount < m_nFiles ; nCount++, pLoop++ )
	{
		if ( (*pLoop)->m_bSelected )
		{

⌨️ 快捷键说明

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