www.pudn.com > GGBT.rar > Bdecode.cpp


// Bdecode.cpp: implementation of the CBdecode class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "testBT.h" 
#include "Bdecode.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CBdecode::CBdecode() 
{ 
	m_lsize = 0; 
	m_pBuf = 0; 
} 
 
CBdecode::~CBdecode() 
{ 
 
} 
 
CVal* CBdecode::decode_int(long &lPos) 
{ 
	//* 
	long lOldPos = lPos; 
	for (; lPos m_lsize) 
		return 0; 
 
 
	char* pstrStop = 0; 
	long l = strtol(m_pBuf+lOldPos, &pstrStop, 10); 
 
	if (pstrStop[0] != 'e') 
		return 0; 
 
	return new CVal(l); 
} 
 
 
CVal* CBdecode::decode_string(long &lPos) 
{	 
	long lOldPos = lPos; 
 
	for (; lPos m_lsize) 
		return 0; 
 
	char* pstrStop = 0; 
	long len = strtol(m_pBuf+lOldPos, &pstrStop, 10); 
 
	if (pstrStop[0] != ':') 
		return 0; 
	 
	if ((lPos+len) > m_lsize) 
		return 0; 
 
	CVal* pVal = new CVal(m_pBuf+lPos, len); 
	lPos += len; 
  
	return pVal; 
} 
 
void ClearList(VALLIST* pls) 
{ 
	VALLIST::iterator iter = pls->begin(); 
	while(iter != pls->end()) 
	{		 
		delete *iter; 
		iter++; 
	} 
} 
 
CVal* CBdecode::decode_list(long &lPos) 
{ 
	VALLIST* ls = new VALLIST(); 
 
	for (; lPospush_back(pRet); 
	} 
 
	if (lPos > m_lsize) 
	{		 
		ClearList(ls); 
		delete ls; 
		return 0; 
	} 
 
	return new CVal(ls); 
} 
 
void ClearMap(VALMAP* pmap) 
{ 
	VALMAP::iterator iter = pmap->begin(); 
	while(iter != pmap->end()) 
	{		 
		delete (*iter).second; 
		iter++; 
	} 
} 
 
CVal*  CBdecode::decode_dict(long& lPos) 
{ 
	VALMAP* pmap = new VALMAP(); 
	string strLast; 
 
	for (; lPospstrVal; 
		delete pRet; 
 
		if (strLast.size() > 0) 
		{ 
			if (strCur <= strLast) 
			{ 
				ClearMap(pmap); 
				delete pmap; 
				return 0; 
			} 
		} 
 
		strLast = strCur; 
 
		CVal* pRetVal = bdecode_rec(lPos); 
		if (!pRetVal) 
		{ 
			ClearMap(pmap); 
			delete pmap; 
			return 0; 
		} 
 
		(*pmap)[strLast] = pRetVal; 
	} 
		 
	if (lPos > m_lsize) 
	{ 
		ClearMap(pmap); 
		delete pmap; 
		return 0; 
	} 
 
 
	return new CVal(pmap); 
} 
 
 
CVal* CBdecode::bdecode_rec(long& lPos) 
{ 
	CVal* pRet = 0; 
 
	char t = m_pBuf[lPos]; 
 
	switch (t) 
	{ 
	case 'i': 
		return decode_int(++lPos);		 
 
	case 'l': 
		return decode_list(++lPos);  
 
	case 'd': 
		return decode_dict(++lPos); 
 
	default: 
		return decode_string(lPos); 
	} 
} 
 
CVal* CBdecode::bdecode(char *pbuf, long lsize) 
{ 
	if (lsize <= 0) 
	{ 
		// assert(false); 
		return 0; 
	} 
 
	m_lsize = lsize; 
	m_pBuf = pbuf; 
	long lPos = 0; 
 
	CVal* v = bdecode_rec(lPos); 
 
	if (lPos > m_lsize) 
	{ 
		if (v) 
			delete v; 
 
		return 0; 
	} 
 
	return v; 
} 
 
void CBdecode::bencode(CVal *pVal, memstream& memRet) 
{ 
	bencode_rec(pVal, memRet); 
} 
 
 
void CBdecode::bencode_rec(CVal *pVal, memstream &strRet) 
{ 
	char temp[100] = {0}; 
 
	switch (pVal->vt) 
	{ 
	case VT_LONG: 
		sprintf(temp, "%d", pVal->lVal); 
		strRet += string("i") + temp + "e"; 
		break; 
 
	case VT_PSTR: 
		sprintf(temp, "%d", pVal->lstrLen); 
		strRet += string(temp) + ":"; 
		// strRet += string(temp) + ":" + pVal->pstrVal; 
		strRet.write(pVal->pstrVal, pVal->lstrLen); 
		break; 
 
	case VT_PLIST: 
		{ 
			strRet += "l"; 
			for (int i=0; iplistVal->size(); i++) 
				bencode_rec((*pVal->plistVal)[i], strRet);			 
			strRet += "e"; 
		} 
		break; 
 
	case VT_PMAP: 
		{ 
			strRet += "d";			 
			for (VALMAP::iterator iter=pVal->pmapVal->begin(); iter != pVal->pmapVal->end(); iter++) 
			{ 
				string strKey = (*iter).first; 
				/* 
				char* pstrBuf = new char[strKey.size()+1]; 
				memset(pstrBuf, 0, strKey.size()+1); 
				memcpy(pstrBuf, strKey.data(), strKey.size()); 
				CVal v(pstrBuf, strKey.size()); 
				//*/ 
				CVal v(strKey); 
				bencode_rec(&v, strRet); 
				bencode_rec((*iter).second, strRet); 
			} 
			strRet += "e"; 
		} 
		 
		break; 
		 
	default: 
		assert(false); 
		break; 
	} 
}