📄 matchobjects.cpp
字号:
//
// 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 + -