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

📄 filefragment.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
字号:
//
// FileFragment.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 "FileFragment.h"

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

CFileFragmentPool	FileFragmentPool;


//////////////////////////////////////////////////////////////////////
// CFileFragment serialize

void CFileFragment::Serialize(CArchive& ar, BOOL bInt64)
{
	if ( ar.IsStoring() )
	{
		ar << m_nOffset;
		ar << m_nLength;
	}
	else if ( bInt64 )
	{
		ar >> m_nOffset;
		ar >> m_nLength;
	}
	else
	{
		DWORD nInt32;
		ar >> nInt32; m_nOffset = nInt32;
		ar >> nInt32; m_nLength = nInt32;
	}
}

//////////////////////////////////////////////////////////////////////
// CFileFragment copy fragments

CFileFragment* CFileFragment::CreateCopy()
{
	CFileFragment* pFirst = NULL;
	CFileFragment* pLast = NULL;
	
	for ( CFileFragment* pFragment = this ; pFragment ; pFragment = pFragment->m_pNext )
	{
		CFileFragment* pCopy = New( pLast, NULL, pFragment->m_nOffset, pFragment->m_nLength );
		if ( ! pFirst ) pFirst = pCopy;
		if ( pLast ) pLast->m_pNext = pCopy;
		pLast = pCopy;
	}
	
	return pFirst;
}

//////////////////////////////////////////////////////////////////////
// CFileFragment invert fragments

CFileFragment* CFileFragment::CreateInverse(QWORD nSize)
{
	CFileFragment* pFirst	= NULL;
	CFileFragment* pLast	= NULL;
	QWORD nLast = 0;
	
	for ( CFileFragment* pFragment = this ; pFragment ; pFragment = pFragment->m_pNext )
	{
		if ( pFragment->m_nOffset > nLast )
		{
			CFileFragment* pCopy = New( pLast, NULL, nLast, pFragment->m_nOffset - nLast );
			if ( ! pFirst ) pFirst = pCopy;
			if ( pLast ) pLast->m_pNext = pCopy;
			pLast = pCopy;
		}
		
		nLast = pFragment->m_nOffset + pFragment->m_nLength;
	}
	
	if ( nSize > nLast )
	{
		CFileFragment* pCopy = New( pLast, NULL, nLast, nSize - nLast );
		if ( ! pFirst ) pFirst = pCopy;
		if ( pLast ) pLast->m_pNext = pCopy;
		pLast = pCopy;
	}
	
	return pFirst;
}

//////////////////////////////////////////////////////////////////////
// CFragmentedFile and fragments

CFileFragment* CFileFragment::CreateAnd(CFileFragment* pAvailable)
{
	CFileFragment* pFirst	= NULL;
	CFileFragment* pLast	= NULL;
	
	for ( CFileFragment* pFragment = this ; pFragment ; pFragment = pFragment->m_pNext )
	{
		for ( CFileFragment* pOther = pAvailable ; pOther ; pOther = pOther->m_pNext )
		{
			QWORD nOffset, nLength;
			
			if ( pOther->m_nOffset <= pFragment->m_nOffset &&
				 pOther->m_nOffset + pOther->m_nLength >= pFragment->m_nOffset + pFragment->m_nLength )
			{
				nOffset = pFragment->m_nOffset;
				nLength = pFragment->m_nLength;
			}
			else if (	pOther->m_nOffset > pFragment->m_nOffset &&
						pOther->m_nOffset + pOther->m_nLength < pFragment->m_nOffset + pFragment->m_nLength )
			{
				nOffset = pOther->m_nOffset;
				nLength = pOther->m_nLength;
			}
			else if (	pOther->m_nOffset + pOther->m_nLength > pFragment->m_nOffset &&
						pOther->m_nOffset + pOther->m_nLength < pFragment->m_nOffset + pFragment->m_nLength )
			{
				nOffset = pFragment->m_nOffset;
				nLength = pOther->m_nLength - ( pFragment->m_nOffset - pOther->m_nOffset );
			}
			else if (	pOther->m_nOffset > pFragment->m_nOffset &&
						pOther->m_nOffset < pFragment->m_nOffset + pFragment->m_nLength )
			{
				nOffset = pOther->m_nOffset;
				nLength = pFragment->m_nOffset + pFragment->m_nLength - pOther->m_nOffset;
			}
			else
			{
				continue;
			}
			
			CFileFragment* pCopy = New( pLast, NULL, nOffset, nLength );
			if ( pFirst == NULL ) pFirst = pCopy;
			if ( pLast != NULL ) pLast->m_pNext = pCopy;
			pLast = pCopy;
		}
	}
	
	return pFirst;
}

//////////////////////////////////////////////////////////////////////
// CFileFragment count the fragments in the list

int CFileFragment::GetCount()
{
	int nCount = 0;
	for ( CFileFragment* pCount = this ; pCount ; pCount = pCount->m_pNext ) nCount++;
	return nCount;
}

//////////////////////////////////////////////////////////////////////
// CFileFragment find random fragment

CFileFragment* CFileFragment::GetRandom(BOOL bPreferZero)
{
	if ( this == NULL ) return NULL;
	
	int nCount = 0;
	
	for ( CFileFragment* pCount = this ; pCount ; pCount = pCount->m_pNext )
	{
		if ( bPreferZero && pCount->m_nOffset == 0 ) return pCount;
		nCount++;
	}
	
	ASSERT( nCount > 0 );
	
	nCount = rand() % nCount;
	
	for ( pCount = this ; pCount ; pCount = pCount->m_pNext )
	{
		if ( nCount-- == 0 ) return pCount;
	}
	
	return NULL;
}

//////////////////////////////////////////////////////////////////////
// CFileFragment find largest fragment

CFileFragment* CFileFragment::GetLargest(CPtrList* pExcept, BOOL bZeroIsLargest)
{
	if ( this == NULL ) return NULL;
	
	if ( bZeroIsLargest && m_nOffset == 0 )
	{
		if ( ! pExcept || pExcept->Find( (LPVOID)this ) == NULL ) return this;
	}
	
	CFileFragment* pLargest = NULL;
	
	for ( CFileFragment* pFragment = this ; pFragment ; )
	{
		if ( ! pLargest || pFragment->m_nLength > pLargest->m_nLength )
		{
			if ( ! pExcept || pExcept->Find( pFragment ) == NULL ) pLargest = pFragment;
		}

		pFragment = pFragment->m_pNext;
	}
	
	return pLargest;
}

//////////////////////////////////////////////////////////////////////
// CFileFragment subtract fragments

QWORD CFileFragment::Subtract(CFileFragment** ppFragments, CFileFragment* pSubtract)
{
	QWORD nCount = 0;
	
	for ( ; pSubtract ; pSubtract = pSubtract->m_pNext )
	{
		if ( ppFragments == NULL || *ppFragments == NULL ) break;
		nCount += Subtract( ppFragments, pSubtract->m_nOffset, pSubtract->m_nLength );
	}
	
	return nCount;
}

QWORD CFileFragment::Subtract(CFileFragment** ppFragments, QWORD nOffset, QWORD nLength)
{
	if ( ppFragments == NULL || *ppFragments == NULL ) return 0;
	
	QWORD nCount = 0;
	
	for ( CFileFragment* pFragment = *ppFragments ; pFragment ; )
	{
		CFileFragment* pNext = pFragment->m_pNext;
		
		if ( nOffset <= pFragment->m_nOffset &&
			 nOffset + nLength >= pFragment->m_nOffset + pFragment->m_nLength )
		{
			if ( pFragment->m_pPrevious )
				pFragment->m_pPrevious->m_pNext = pNext;
			else
				*ppFragments = pNext;
			
			if ( pNext )
				pNext->m_pPrevious = pFragment->m_pPrevious;
		//	else
		//		m_pLast = pFragment->m_pPrevious;
			
			nCount += pFragment->m_nLength;
			
			pFragment->DeleteThis();
		}
		else if (	nOffset > pFragment->m_nOffset &&
					nOffset + nLength < pFragment->m_nOffset + pFragment->m_nLength )
		{
			CFileFragment* pNew = New( pFragment, pNext );
			pNew->m_nOffset	= nOffset + nLength;
			pNew->m_nLength	= pFragment->m_nOffset + pFragment->m_nLength - pNew->m_nOffset;
			
			pFragment->m_nLength	= nOffset - pFragment->m_nOffset;
			pFragment->m_pNext		= pNew;
			nCount					+= nLength;
			
			if ( pNext )
				pNext->m_pPrevious = pNew;
		//	else
		//		m_pLast = pNew;
			
			break;
		}
		else if (	nOffset + nLength > pFragment->m_nOffset &&
					nOffset + nLength < pFragment->m_nOffset + pFragment->m_nLength )
		{
			QWORD nFragment	= nLength - ( pFragment->m_nOffset - nOffset );
			
			pFragment->m_nOffset	+= nFragment;
			pFragment->m_nLength	-= nFragment;
			nCount					+= nFragment;
		}
		else if (	nOffset > pFragment->m_nOffset &&
					nOffset < pFragment->m_nOffset + pFragment->m_nLength )
		{
			QWORD nFragment	= pFragment->m_nOffset + pFragment->m_nLength - nOffset;
			
			pFragment->m_nLength	-= nFragment;
			nCount					+= nFragment;
		}
		
		pFragment = pNext;
	}
	
	return nCount;
}

//////////////////////////////////////////////////////////////////////
// CFileFragment add and merge a fragment

void CFileFragment::AddMerge(CFileFragment** ppFragments, QWORD nOffset, QWORD nLength)
{
	if ( ppFragments == NULL || nLength == 0 ) return;
	
	for ( CFileFragment* pFragment = *ppFragments ; pFragment ; pFragment = pFragment->m_pNext )
	{
		if ( pFragment->m_nOffset + pFragment->m_nLength == nOffset )
		{
			pFragment->m_nLength += nLength;
			break;
		}
		else if ( nOffset + nLength == pFragment->m_nOffset )
		{
			pFragment->m_nOffset -= nLength;
			pFragment->m_nLength += nLength;
			break;
		}
	}
	
	if ( pFragment == NULL )
	{
		CFileFragment* pFragment = New( NULL, *ppFragments, nOffset, nLength );
		if ( *ppFragments != NULL ) (*ppFragments)->m_pPrevious = pFragment;
		*ppFragments = pFragment;
		return;
	}
	
	for ( CFileFragment* pOther = *ppFragments ; pOther ; pOther = pOther->m_pNext )
	{
		if ( pFragment == pOther )
		{
			continue;
		}
		else if ( pFragment->m_nOffset + pFragment->m_nLength == pOther->m_nOffset )
		{
			pFragment->m_nLength += pOther->m_nLength;
		}
		else if ( pOther->m_nOffset + pOther->m_nLength == pFragment->m_nOffset )
		{
			pFragment->m_nOffset -= pOther->m_nLength;
			pFragment->m_nLength += pOther->m_nLength;
		}
		else
		{
			continue;
		}
		
		if ( pOther->m_pPrevious )
			pOther->m_pPrevious->m_pNext = pOther->m_pNext;
		else
			*ppFragments = pOther->m_pNext;

		if ( pOther->m_pNext )
			pOther->m_pNext->m_pPrevious = pOther->m_pPrevious;
		
		pOther->DeleteThis();
		break;
	}
}
	

//////////////////////////////////////////////////////////////////////
// CFileFragmentPool construction

CFileFragmentPool::CFileFragmentPool()
{
	m_pFree = NULL;
	m_nFree = 0;
}

CFileFragmentPool::~CFileFragmentPool()
{
	Clear();
}

//////////////////////////////////////////////////////////////////////
// CFileFragmentPool clear

void CFileFragmentPool::Clear()
{
	for ( POSITION pos = m_pPools.GetHeadPosition() ; pos ; )
	{
		CFileFragment* pPool = (CFileFragment*)m_pPools.GetNext( pos );
		delete [] pPool;
	}
	
	m_pPools.RemoveAll();
	m_pFree = NULL;
	m_nFree = 0;
}

//////////////////////////////////////////////////////////////////////
// CFileFragmentPool new pool setup

void CFileFragmentPool::NewPool()
{
	int nSize = 2048;
	
	CFileFragment* pPool = new CFileFragment[ nSize ];
	m_pPools.AddTail( pPool );
	
	while ( nSize-- > 0 )
	{
		pPool->m_pNext = m_pFree;
		m_pFree = pPool++;
		m_nFree++;
	}
}

⌨️ 快捷键说明

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