Torrent文件采用Bencode编码,Bencode编码由以下四种类型组成
对于字符串,首先是一个字符串的长度,然后是冒号,后面跟着实际的字符串,例如:4:spam,就是“ spam”
整数编码如下,以 ‘i’ 开始,然后10进制的整数值,最后以’e’结尾。例如,i3e表示3,I-3e表示-3。整数没有大小限制。I-0e是无效的。除了 i0e外,所以以0起始的整数都无效。I0e当然表示0。
列表编码如下,以’l’开始,接下来是列表值的编码(也采用bencoded编码),最后以’e’结束。例如:l4:spam4:eggse 表示 [‘spam’, ‘eggs’]。
字典编码如下,以’d’开始,接下来是可选的keys和它对应的值,最户以’e’结束。例如:d3:cow3:moo4:spam4:eggse,表示{‘cow’:’moo’,’spam’:’eggs’},而d4:spaml1:al:bee 表示 {‘spam’:[‘a’,’b’]}。键值必须是字符串,而且已经排序(并非是按照字母顺序排序,而是根据原始的字符串进行排序)。
enum BTItemType
{
BT_ITEEM_UNKNOWN = 0,
BT_ITEEM_INT,
BT_ITEEM_STR,
BT_ITEEM_LIST,
BT_ITEEM_DIC,
};
class CBTBaseItem
{
public:
CBTBaseItem( );
virtual ~CBTBaseItem();
public:
void SetItemType(BTItemType ItemType);
BTItemType GetItemType();
protected:
BTItemType m_ItemType;
};
class CBTIntItem : public CBTBaseItem
{
public:
CBTIntItem(BTItemType ItemType);
~CBTIntItem();
public:
int GetValue();
void SetValue(int iValue);
private:
int m_Value;
};
class CBTStrItem : public CBTBaseItem
{
public:
CBTStrItem(BTItemType ItemType);
~CBTStrItem();
public:
string GetValue();
void SetValue(string strVal);
private:
string m_strValue;
};
class CBTListItem : public CBTBaseItem
{
public:
CBTListItem(BTItemType ItemType);
~CBTListItem();
public:
int GetSize();
CBTBaseItem* GetValue(int index);
void AddValue(CBTBaseItem* pBaseItem);
private:
void Destroy();
private:
vector
};
class CBTDicItem : public CBTBaseItem
{
typedef map
public:
CBTDicItem(BTItemType ItemType);
~CBTDicItem();
public:
int GetSize();
CBTBaseItem* GetValue(string strKey);
void AddValue(string strKey, CBTBaseItem* pBaseItem);
private:
void Destroy();
private:
Map m_MapValue;
};
实现就很简单了
CBTBaseItem::CBTBaseItem()
{
}
CBTBaseItem::~CBTBaseItem()
{
}
void CBTBaseItem::SetItemType(BTItemType ItemType)
{
m_ItemType = ItemType;
}
BTItemType CBTBaseItem::GetItemType()
{
return m_ItemType;
}
CBTIntItem::CBTIntItem(BTItemType ItemType)
{
m_ItemType = ItemType;
m_Value = 0;
}
CBTIntItem::~CBTIntItem()
{
}
int CBTIntItem::GetValue()
{
return m_Value;
}
void CBTIntItem::SetValue(int iValue)
{
m_Value = iValue;
}
//////////////////////////////////////////////////////////////////////////////////////
CBTStrItem ::CBTStrItem(BTItemType ItemType)
{
m_ItemType = ItemType;
m_strValue = string("");
}
CBTStrItem::~CBTStrItem()
{
}
void CBTStrItem::SetValue(string strVal)
{
m_strValue = strVal;
}
string CBTStrItem::GetValue()
{
return m_strValue;
}
CBTListItem::CBTListItem(BTItemType ItemType)
{
m_ItemType = ItemType;
}
CBTListItem::~CBTListItem()
{
Destroy();
}
int CBTListItem::GetSize()
{
return m_ListValue.size();
}
CBTBaseItem* CBTListItem::GetValue(int index)
{
if (index < 0 || index >= GetSize())
return NULL;
return m_ListValue[index];
}
void CBTListItem::AddValue(CBTBaseItem* pBaseItem)
{
if (NULL != pBaseItem)
m_ListValue.push_back(pBaseItem);
}
void CBTListItem::Destroy()
{
for (int index = 0; index < m_ListValue.size(); ++index)
{
CBTBaseItem* pItem = m_ListValue[index];
if (pItem)
delete pItem;
}
}
CBTDicItem::CBTDicItem(BTItemType ItemType)
{
m_ItemType = ItemType;
}
CBTDicItem::~CBTDicItem()
{
Destroy();
}
int CBTDicItem::GetSize()
{
return m_MapValue.size();
}
CBTBaseItem* CBTDicItem::GetValue(string strKey)
{
Map::iterator pos = m_MapValue.find(strKey);
if (pos != m_MapValue.end())
return pos->second;
return NULL;
}
void CBTDicItem::AddValue(string strKey, CBTBaseItem* pBaseItem)
{
if (strKey.size() > 0 && pBaseItem)
m_MapValue.insert(make_pair(strKey, pBaseItem));
}
void CBTDicItem::Destroy()
{
Map::iterator pos = m_MapValue.begin();
for (; pos != m_MapValue.end(); ++pos)
{
CBTBaseItem* pItem = pos->second;
if (pItem)
delete pItem;
}
}