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

📄 tigertree.cpp

📁 p2p软件
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// TigerTree.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 "TigerTree.h"
#include "TigerBoxes.h"

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

#define BLOCK_SIZE		1024
#define STACK_SIZE		64
#define TIGER_SIZE		24

#define NEW_TIGER_ALG	// New "more secure" padded node combination


//////////////////////////////////////////////////////////////////////
// CTigerTree construction

CTigerTree::CTigerTree()
{
	m_nHeight		= 0;
	m_pNode			= NULL;
	m_nNodeCount	= 0;

	m_pStackBase	= NULL;
	m_pStackTop		= NULL;
}

CTigerTree::~CTigerTree()
{
	Clear();

	if ( m_pStackBase != NULL ) delete [] m_pStackBase;
}

//////////////////////////////////////////////////////////////////////
// CTigerTree setup tree

void CTigerTree::SetupAndAllocate(DWORD nHeight, QWORD nLength)
{
	Clear();
	
	QWORD nCount = (DWORD)( nLength / BLOCK_SIZE );
	if ( nLength % BLOCK_SIZE ) nCount++;
	
	DWORD nActualHeight = 1;
	
	for ( DWORD nStep = 1 ; nStep < nCount ; nStep *= 2 ) nActualHeight++;
	
	m_nHeight = min( nActualHeight, nHeight );
	
	m_nBlockCount	= 1;
	m_nBlockPos		= 0;
	
	if ( nActualHeight > nHeight )
	{
		for ( nStep = nActualHeight - nHeight ; nStep ; nStep-- ) m_nBlockCount *= 2;
	}
	
	m_nNodeCount = 1;
	
	for ( nStep = m_nHeight ; nStep ; nStep-- ) m_nNodeCount *= 2;
	
	m_nNodeBase	= ( m_nNodeCount / 2 );
	m_nBaseUsed	= (DWORD)( nCount / m_nBlockCount );
	if ( nCount % m_nBlockCount ) m_nBaseUsed++;
	
	m_pNode		= new CTigerNode[ --m_nNodeCount ];
	m_nNodePos	= 0;
}

void CTigerTree::SetupParameters(QWORD nLength)
{
	QWORD nCount = nLength / BLOCK_SIZE;
	if ( nLength % BLOCK_SIZE ) nCount++;
	
	DWORD nActualHeight = 1;
	for ( DWORD nStep = 1 ; nStep < nCount ; nStep *= 2 ) nActualHeight++;
	
	m_nBlockCount	= 1;
	m_nBlockPos		= 0;
	
	if ( nActualHeight > m_nHeight )
	{
		for ( nStep = nActualHeight - m_nHeight ; nStep ; nStep-- ) m_nBlockCount *= 2;
	}
	
	m_nNodeCount = 1;
	for ( nStep = m_nHeight ; nStep ; nStep-- ) m_nNodeCount *= 2;
	
	m_nNodeBase = ( m_nNodeCount-- / 2 );
	
	m_nBaseUsed	= (DWORD)( nCount / m_nBlockCount );
	if ( nCount % m_nBlockCount ) m_nBaseUsed++;
}

//////////////////////////////////////////////////////////////////////
// CTigerTree clear

void CTigerTree::Clear()
{
	if ( m_pNode != NULL ) delete [] m_pNode;
	
	m_nHeight		= 0;
	m_pNode			= NULL;
	m_nNodeCount	= 0;
}

//////////////////////////////////////////////////////////////////////
// CTigerTree serialize

void CTigerTree::Serialize(CArchive& ar)
{
	CTigerNode* pNode;
	DWORD nStep;
	
	if ( ar.IsStoring() )
	{
		ar << m_nHeight;
		
		if ( m_nHeight == 0 ) return;
		ASSERT( m_pNode != NULL );
		
		pNode = m_pNode;
		
		for ( nStep = m_nNodeCount ; nStep ; nStep--, pNode++ )
		{
			ar.Write( pNode->value, TIGER_SIZE );
			ar << pNode->bValid;
		}
	}
	else
	{
		Clear();
		
		ar >> m_nHeight;
		if ( m_nHeight == 0 ) return;
		
		m_nNodeCount = 1;
		for ( nStep = m_nHeight ; nStep ; nStep-- ) m_nNodeCount *= 2;
		m_nNodeCount --;
		
		m_pNode = pNode = new CTigerNode[ m_nNodeCount ];
		
		for ( nStep = m_nNodeCount ; nStep ; nStep--, pNode++ )
		{
			ar.Read( pNode->value, TIGER_SIZE );
			ar >> pNode->bValid;
		}
	}
}

DWORD CTigerTree::GetSerialSize() const
{
	return 4 + m_nNodeCount * ( TIGER_SIZE + 1 );
}

//////////////////////////////////////////////////////////////////////
// CTigerTree root output

BOOL CTigerTree::GetRoot(TIGEROOT* pTiger) const
{
	if ( m_pNode == NULL ) return FALSE;
	ASSERT( sizeof(TIGEROOT) == TIGER_SIZE );
	CopyMemory( pTiger, &m_pNode->value, TIGER_SIZE );
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CTigerTree string output

CString CTigerTree::RootToString() const
{
	CString str;
	if ( m_pNode != NULL ) str = m_pNode->ToString();
	return str;
}

//////////////////////////////////////////////////////////////////////
// CTigerTree assume

void CTigerTree::Assume(CTigerTree* pSource)
{
	Clear();
	if ( pSource->m_pNode == NULL ) return;

	m_nHeight		= pSource->m_nHeight;
	m_nNodeCount	= pSource->m_nNodeCount;
	m_pNode			= pSource->m_pNode;

	pSource->m_nHeight		= 0;
	pSource->m_nNodeCount	= 0;
	pSource->m_pNode		= NULL;
}

//////////////////////////////////////////////////////////////////////
// CTigerTree create from file

void CTigerTree::BeginFile(DWORD nHeight, QWORD nLength)
{
	ASSERT( ! IsAvailable() );
	
	SetupAndAllocate( nHeight, nLength );
	
	if ( m_pStackBase == NULL ) m_pStackBase = new CTigerNode[ STACK_SIZE ];
	m_pStackTop	= m_pStackBase;
	m_nBlockPos = 0;
}

//////////////////////////////////////////////////////////////////////
// CTigerTree add data to the file

void CTigerTree::AddToFile(LPCVOID pInput, DWORD nLength)
{
	ASSERT( m_pNode != NULL );
	
	LPBYTE pBlock = (LPBYTE)pInput;
	
	while ( nLength > 0 )
	{
		DWORD nBlock = min( nLength, BLOCK_SIZE );
		
		Tiger( pBlock, (WORD64)nBlock, m_pStackTop->value );
		m_pStackTop ++;

		DWORD nCollapse = ++m_nBlockPos;

		while ( ! ( nCollapse & 1 ) )
		{
			Collapse();
			nCollapse >>= 1;
		}

		if ( m_nBlockPos >= m_nBlockCount )
		{
			BlocksToNode();
		}

		pBlock += nBlock;
		nLength -= nBlock;
	}
}

//////////////////////////////////////////////////////////////////////
// CTigerTree finish file

BOOL CTigerTree::FinishFile()
{
	if ( m_pStackTop == NULL ) return FALSE;
	
	BlocksToNode();
	
	if ( m_nNodePos > m_nNodeBase ) return FALSE;
	
	if ( m_pStackBase != NULL ) delete [] m_pStackBase;
	
	m_pStackBase	= NULL;
	m_pStackTop		= NULL;
	
	CTigerNode* pBase = m_pNode + m_nNodeCount - m_nNodeBase;
	
	for ( DWORD nCombine = m_nNodeBase ; nCombine > 1 ; nCombine /= 2 )
	{
		CTigerNode* pIn		= pBase;
		CTigerNode* pOut	= pBase - nCombine / 2;
		
		for ( DWORD nIterate = nCombine / 2 ; nIterate ; nIterate--, pIn += 2, pOut++ )
		{
			if ( pIn[0].bValid && pIn[1].bValid )
			{
				Tiger( NULL, TIGER_SIZE * 2, pOut->value, pIn[0].value, pIn[1].value );
				pOut->bValid = TRUE;
			}
			else if ( pIn[0].bValid )
			{
				*pOut = *pIn;
			}
		}
		
		pBase -= nCombine / 2;
	}
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CTigerTree begin a block test

void CTigerTree::BeginBlockTest()
{
	ASSERT( m_pNode != NULL );
	
	if ( m_pStackBase == NULL ) m_pStackBase = new CTigerNode[ STACK_SIZE ];
	m_pStackTop	= m_pStackBase;
	m_nBlockPos = 0;
}

//////////////////////////////////////////////////////////////////////
// CTigerTree add data to a block test

void CTigerTree::AddToTest(LPCVOID pInput, DWORD nLength)
{
	ASSERT( m_pNode != NULL );
	
	LPBYTE pBlock = (LPBYTE)pInput;
	
	while ( nLength > 0 )
	{
		DWORD nBlock = min( nLength, BLOCK_SIZE );
		
		Tiger( pBlock, (WORD64)nBlock, m_pStackTop->value );
		m_pStackTop ++;
		
		ASSERT( m_nBlockPos < m_nBlockCount );
		
		DWORD nCollapse = ++m_nBlockPos;
		
		while ( ! ( nCollapse & 1 ) )
		{
			Collapse();
			nCollapse >>= 1;
		}
		
		pBlock += nBlock;
		nLength -= nBlock;
	}
}

//////////////////////////////////////////////////////////////////////
// CTigerTree block test finish and compare

BOOL CTigerTree::FinishBlockTest(DWORD nBlock)
{
	ASSERT( nBlock < m_nBaseUsed );
	if ( nBlock >= m_nBaseUsed ) return FALSE;
	
	while ( m_pStackTop - 1 > m_pStackBase ) Collapse();
	
	CTigerNode* pNode = m_pNode + m_nNodeCount - m_nNodeBase + nBlock;
	
	if ( pNode->v1 != m_pStackBase->v1 ) return FALSE;
	if ( pNode->v2 != m_pStackBase->v2 ) return FALSE;
	if ( pNode->v3 != m_pStackBase->v3 ) return FALSE;
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CTigerTree breadth-first serialize

BOOL CTigerTree::ToBytes(BYTE** pOutput, DWORD* pnOutput, DWORD nHeight)
{
	if ( m_pNode == NULL ) return FALSE;
	
	if ( nHeight < 1 || nHeight > m_nHeight ) nHeight = m_nHeight;
	
	DWORD nNodeCount = 1;
	while ( nHeight-- ) nNodeCount *= 2;
	nNodeCount --;
	
	nNodeCount	= min( nNodeCount, m_nNodeCount );
	*pnOutput	= nNodeCount * TIGER_SIZE;
	*pOutput	= new BYTE[ *pnOutput ];
	
	CTigerNode* pNode = m_pNode;
	BYTE* pOut = *pOutput;
	
	for ( DWORD nNode = 0 ; nNode < nNodeCount ; nNode++, pNode++ )
	{
		if ( pNode->bValid )
		{
			CopyMemory( pOut, pNode->value, TIGER_SIZE );
			pOut += TIGER_SIZE;
		}
		else
		{
			*pnOutput -= TIGER_SIZE;
		}
	}
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CTigerTree breadth-first serialize

BOOL CTigerTree::FromBytes(BYTE* pInput, DWORD nInput, DWORD nHeight, QWORD nLength)
{
	SetupAndAllocate( nHeight, nLength );
	
	CTigerNode* pBase = m_pNode + m_nNodeCount - m_nNodeBase;
	
	for ( DWORD nStep = m_nBaseUsed ; nStep ; nStep-- )
	{
		pBase[ nStep - 1 ].bValid = TRUE;
	}
	
	for ( DWORD nCombine = m_nNodeBase ; nCombine > 1 ; nCombine /= 2 )
	{
		CTigerNode* pIn		= pBase;
		CTigerNode* pOut	= pBase - nCombine / 2;
		
		for ( DWORD nIterate = nCombine / 2 ; nIterate ; nIterate--, pIn += 2, pOut++ )
		{
			if ( pIn[0].bValid ) pOut->bValid = TRUE;
		}
		
		pBase -= nCombine / 2;
	}
	
	TIGEROOT* pTiger = (TIGEROOT*)pInput;
	nInput /= TIGER_SIZE;
	
	DWORD nRowPos = 0, nRowCount = 1;
	m_nHeight = 0;
	
	for ( nStep = 0 ; nStep < m_nNodeCount && nInput > 0 ; nStep++ )
	{
		if ( m_pNode[ nStep ].bValid )
		{
			CopyMemory( m_pNode[ nStep ].value, pTiger->w, TIGER_SIZE );
			pTiger ++; nInput --;
		}

		if ( nRowPos == 0 ) m_nHeight ++;

		if ( ++nRowPos == nRowCount )
		{

⌨️ 快捷键说明

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