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;
}
}