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<CBTBaseItem*> m_ListValue;};
class CBTDicItem : public CBTBaseItem{ typedef map<string, CBTBaseItem*> 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; }}