织梦CMS - 轻松建站从此开始!

罗索

bencoding编码解析器

落鹤生 发布于 2012-05-30 21:44 点击:次 
BT客户端开始一个下载首先要处理的就是torrent文件.而torrent文件使用bencoding编码.所以实现bencoding编码的解析器,就是第一步工作.
TAG:

BT客户端开始一个下载首先要处理的就是torrent文件.
而torrent文件使用bencoding编码.
所以实现bencoding编码的解析器,就是第一步工作.

Bencoding is done as follows:
Strings are length-prefixed base ten followed by a colon and the string. For example /'4:spam/' corresponds to /'spam/'.
Integers are represented by an /'i/' followed by the number in base 10 followed by an /'e/'. For example /'i3e/' corresponds to 3 and /'i-3e/' corresponds to -3. Integers have no size limitation. /'i-0e/' is invalid. All encodings with a leading zero, such as /'i03e/', are invalid, other than /'i0e/', which of course corresponds to 0.
Lists are encoded as an /'l/' followed by their elements (also bencoded) followed by an /'e/'. For example /'l4:spam4:eggse/' corresponds to [/'spam/', /'eggs/'].
Dictionaries are encoded as a /'d/' followed by a list of alternating keys and their corresponding values followed by an /'e/'. For example, /'d3:cow3:moo4:spam4:eggse/' corresponds to {/'cow/': /'moo/', /'spam/': /'eggs/'} and /'d4:spaml1:a1:bee/' corresponds to {/'spam/': [/'a/', /'b/']} . Keys must be strings and appear in sorted order (sorted as raw strings, not alphanumerics).

下面是实现的bencoding解码器的VC++源代码:

  1. // BEncode.h: interface for the CBEncode class. 
  2. // 
  3. ////////////////////////////////////////////////////////////////////// 
  4.  
  5. #if !defined(AFX_BENCODE_H__4D0BB462_2AE0_45B3_8BE8_19D51B2DBB2E__INCLUDED_) 
  6. #define AFX_BENCODE_H__4D0BB462_2AE0_45B3_8BE8_19D51B2DBB2E__INCLUDED_ 
  7.  
  8. #if _MSC_VER > 1000 
  9. #pragma once 
  10. #endif // _MSC_VER > 1000 
  11. #pragma warning( disable : 4786 ) 
  12. #pragma warning( disable : 4355 ) 
  13. #include <list> 
  14. #include <map> 
  15. #include <string> 
  16. #include <vector> 
  17. using namespace std; 
  18. enum BEncodeParserErrorCode 
  19.     enm_BEncodeErr_noerr = 0,//没有错误  
  20.     enm_BEncodeErr_errString,//错误的字符串 
  21.     enm_BEncodeErr_errInt,//错误的整型数据 
  22.     enm_BEncodeErr_errList,//错误的列表 
  23.     enm_BEncodeErr_errDict,//错误的词典结构 
  24.     enm_BEncodeErr_End,//文本结束 
  25.     enm_BEncodeErr_unknown//未知错误 
  26. }; 
  27. enum BEncodeObjectType 
  28.     enum_BEncodeType_Objectbase = 0,     
  29.     enum_BEncodeType_String, 
  30.     enum_BEncodeType_Int, 
  31.     enum_BEncodeType_List, 
  32.     enum_BEncodeType_Dict, 
  33. }; 
  34. class CBEncodeObjectBase 
  35. public
  36.     CBEncodeObjectBase(BEncodeObjectType type
  37.  = enum_BEncodeType_Objectbase){m_type = type;clear();} 
  38.     virtual ~CBEncodeObjectBase(){}; 
  39.     void clear(){szPos = NULL;m_error = enm_BEncodeErr_noerr;} 
  40. public
  41.     BEncodeObjectType m_type;   //对象类型 
  42.     char * szPos;   //对象在字符串中的位置 
  43.     int ilen;//对象的数据长度 
  44.     BEncodeParserErrorCode m_error;//错误值     
  45. }; 
  46. class CBEncodeInt : public CBEncodeObjectBase 
  47. public
  48.     CBEncodeInt() : CBEncodeObjectBase(enum_BEncodeType_Int) {} 
  49.     virtual ~CBEncodeInt(){}         
  50. public:  
  51.     int m_iValue;//整型对象的值 
  52. }; 
  53. class CBEncodeString : public CBEncodeObjectBase 
  54. public
  55.     CBEncodeString() : CBEncodeObjectBase(enum_BEncodeType_String) {m_szData = NULL;} 
  56.     virtual ~CBEncodeString(){}      
  57. public:  
  58.     bool getstring(string & strValue) 
  59.     { 
  60.         if(m_error == enm_BEncodeErr_noerr && m_szData) 
  61.         { 
  62.             strValue.assign(m_szData,m_ilen); 
  63.             return true
  64.         } 
  65.         return false
  66.     } 
  67.     char * m_szData; 
  68.     int m_ilen; 
  69. }; 
  70. class CBEncodeList : public CBEncodeObjectBase 
  71. public
  72.     CBEncodeList() : CBEncodeObjectBase(enum_BEncodeType_List) {} 
  73.     virtual ~CBEncodeList(){clear();} 
  74.     void clear() 
  75.     {            
  76.         list<CBEncodeObjectBase *>::iterator it; 
  77.         for(it = m_listObj.begin();it!=m_listObj.end();++it) 
  78.             delete (*it); 
  79.         m_listObj.clear(); 
  80.     } 
  81. public:  
  82.     list<CBEncodeObjectBase*> m_listObj; 
  83. }; 
  84. class CBEncodeDict : public CBEncodeObjectBase 
  85. public
  86.     CBEncodeDict() : CBEncodeObjectBase(enum_BEncodeType_Dict) {} 
  87.     virtual ~CBEncodeDict(){clear();} 
  88.     CBEncodeObjectBase* getvalue(const char * szName) 
  89.     { 
  90.         map<string,CBEncodeObjectBase*>::iterator it = m_mapObj.find(szName); 
  91.         if(it != m_mapObj.end()) 
  92.             return it->second; 
  93.         return NULL; 
  94.     } 
  95.     void clear() 
  96.     {            
  97.         list<CBEncodeObjectBase *>::iterator it; 
  98.         for(it = m_listObj.begin();it!=m_listObj.end();++it) 
  99.             delete (*it); 
  100.         m_listObj.clear(); 
  101.         m_mapObj.clear(); 
  102.     } 
  103. public:  
  104.     map<string,CBEncodeObjectBase*> m_mapObj;// 
  105.     list<CBEncodeObjectBase*> m_listObj;
  106. //真正的对象保存在list中,list是一个name对象一个value对象.map只是一个映射表,引用了指针而已 
  107. }; 
  108. class CBEncode 
  109. public
  110.     bool readint(char *szCurPos,int & iendpos,list<CBEncodeObjectBase*> & listObj); 
  111.     bool readstring(char *szCurPos,int & iendpos,list<CBEncodeObjectBase*> & listObj);   
  112.     bool readlist(char *szCurPos,int & iendpos,list<CBEncodeObjectBase*> & listObj);     
  113.     bool readdict(char *szCurPos,int & iendpos,list<CBEncodeObjectBase*> & listObj);     
  114.     bool parse(const char * szData); 
  115.     CBEncode(); 
  116.     virtual ~CBEncode(); 
  117.     void clear() 
  118.     {    
  119.         list<CBEncodeObjectBase *>::iterator it; 
  120.         for(it = m_listObj.begin();it!=m_listObj.end();++it) 
  121.             delete (*it); 
  122.         m_listObj.clear();   
  123.     } 
  124. public
  125.     list<CBEncodeObjectBase*> m_listObj; 
  126.     CBEncodeObjectBase* m_plastObj;//解析出来的最后一个对象 
  127.     char * m_szTxt; 
  128. }; 
  129.  
  130. #endif // !defined(AFX_BENCODE_H__4D0BB462_2AE0_45B3_8BE8_19D51B2DBB2E__INCLUDED_) 

BEncode.cpp

  1. // BEncode.cpp: implementation of the CBEncode class. 
  2. // 
  3. ////////////////////////////////////////////////////////////////////// 
  4.  
  5. #include "stdafx.h" 
  6. #include "BEncode.h" 
  7.  
  8. ////////////////////////////////////////////////////////////////////// 
  9. // Construction/Destruction 
  10. ////////////////////////////////////////////////////////////////////// 
  11.  
  12. CBEncode::CBEncode() 
  13.     m_plastObj = NULL; 
  14.     m_szTxt = NULL; 
  15.  
  16. CBEncode::~CBEncode() 
  17.     clear(); 
  18.  
  19. bool CBEncode::parse(const char *szData) 
  20.     if(szData == NULL||*szData==NULL) 
  21.         return false
  22.     clear(); 
  23.     m_szTxt = (char*)szData; 
  24.     char * szCurPos = (char*)szData; 
  25.     int iendpos; 
  26.     while(*szCurPos) 
  27.     {    
  28.         if(*szCurPos== 'i'
  29.         { 
  30.             if(!readint(szCurPos,iendpos,m_listObj)) 
  31.                 break;//遇到任何错误都终止整个解析 
  32.             szCurPos+=iendpos; 
  33.         } 
  34.         else if(*szCurPos== 'l'
  35.         { 
  36.             if(!readlist(szCurPos,iendpos,m_listObj)) 
  37.                 break
  38.             szCurPos+=iendpos; 
  39.         } 
  40.         else if(*szCurPos== 'd'
  41.         { 
  42.             if(!readdict(szCurPos,iendpos,m_listObj)) 
  43.                 break
  44.             szCurPos+=iendpos; 
  45.         } 
  46.         else             
  47.         { 
  48.             if(!readstring(szCurPos,iendpos,m_listObj)) 
  49.                 break
  50.             szCurPos+=iendpos; 
  51.         } 
  52.     } 
  53.     if(*szCurPos==0&&m_plastObj->m_error == enm_BEncodeErr_noerr) 
  54.         return true
  55.     return false
  56. //从当前位置读取一个字符串 
  57. bool CBEncode::readstring(char *szCurPos,int & iendpos
  58. ,list<CBEncodeObjectBase*> & listObj) 
  59. {    
  60.     char * szTmp = szCurPos; 
  61.     CBEncodeString * pNewString = new CBEncodeString;    
  62.     pNewString->szPos = szCurPos; 
  63.  
  64.     char szLen[20]; 
  65.     int i = 0; 
  66.     while(*szTmp>='0'&&*szTmp<='9'
  67.         szLen[i++]=*(szTmp++); 
  68.     szLen[i]=0; 
  69.     if(*szTmp==':'
  70.     { 
  71.         int ilen = atoi(szLen); 
  72.         if(ilen>0) 
  73.         {    
  74.             pNewString->m_szData = ++szTmp; 
  75.             pNewString->m_ilen = ilen; 
  76.             szTmp+=ilen; 
  77.         } 
  78.         else 
  79.             pNewString->m_error = enm_BEncodeErr_errString; 
  80.     } 
  81.     else 
  82.         pNewString->m_error = enm_BEncodeErr_errString; 
  83.     listObj.push_back(pNewString); 
  84.     iendpos = szTmp-szCurPos;            
  85.     m_plastObj = pNewString; 
  86.     m_plastObj->ilen = iendpos; 
  87.     return pNewString->m_error == enm_BEncodeErr_noerr?true:false
  88. //读取一个整型数据 
  89. bool CBEncode::readint(char *szCurPos,int & iendpos
  90. ,list<CBEncodeObjectBase*> & listObj) 
  91.     char * szTmp = szCurPos; 
  92.     CBEncodeInt * pNewInt= new CBEncodeInt;  
  93.     pNewInt->szPos = szCurPos; 
  94.  
  95.     if(*szTmp == 'i'
  96.     {    
  97.         szTmp++; 
  98.         char szLen[20]; 
  99.         int i = 0; 
  100.         while(*szTmp>='0'&&*szTmp<='9'
  101.             szLen[i++]=*(szTmp++); 
  102.         szLen[i]=0; 
  103.         if(*szTmp=='e'
  104.         { 
  105.             pNewInt->m_iValue = atoi(szLen);             
  106.             ++szTmp; 
  107.         } 
  108.         else 
  109.             pNewInt->m_error = enm_BEncodeErr_errInt; 
  110.     } 
  111.     else 
  112.         pNewInt->m_error = enm_BEncodeErr_errInt; 
  113.     listObj.push_back(pNewInt); 
  114.     iendpos = szTmp-szCurPos;    
  115.     m_plastObj = pNewInt; 
  116.     m_plastObj->ilen = iendpos; 
  117.     return pNewInt->m_error == enm_BEncodeErr_noerr?true:false
  118. //读取一个列表 
  119. bool CBEncode::readlist(char *szCurPos,int & iendpos
  120. ,list<CBEncodeObjectBase*> & listObj) 
  121.     char * szTmp = szCurPos; 
  122.     CBEncodeList * pNewList= new CBEncodeList; 
  123.     pNewList->szPos = szCurPos; 
  124.     if(*szTmp == 'l'
  125.     { 
  126.         szTmp++; 
  127.         int ilistendpos; 
  128.         while(*szTmp!='e'
  129.         { 
  130.             if(*szTmp== 'i'
  131.             { 
  132.                 if(!readint(szTmp,ilistendpos,pNewList->m_listObj)) 
  133.                     break;//遇到任何错误都终止整个解析 
  134.                 szTmp+=ilistendpos; 
  135.             } 
  136.             else if(*szTmp== 'l'
  137.             { 
  138.                 if(!readlist(szTmp,ilistendpos,pNewList->m_listObj)) 
  139.                     break
  140.                 szTmp+=ilistendpos; 
  141.             } 
  142.             else if(*szTmp== 'd'
  143.             { 
  144.                 if(!readdict(szTmp,ilistendpos,pNewList->m_listObj)) 
  145.                     break
  146.                 szTmp+=ilistendpos; 
  147.             } 
  148.             else             
  149.             { 
  150.                 if(!readstring(szTmp,ilistendpos,pNewList->m_listObj)) 
  151.                     break
  152.                 szTmp+=ilistendpos; 
  153.             } 
  154.         }    
  155.         if(*szTmp!='e'||m_plastObj->m_error != enm_BEncodeErr_noerr) 
  156.             pNewList->m_error = enm_BEncodeErr_errList; 
  157.         else 
  158.             szTmp++; 
  159.     } 
  160.     else 
  161.         pNewList->m_error = enm_BEncodeErr_errList; 
  162.     listObj.push_back(pNewList); 
  163.     iendpos = szTmp-szCurPos; 
  164.     m_plastObj = pNewList; 
  165.     m_plastObj->ilen = iendpos; 
  166.     return pNewList->m_error == enm_BEncodeErr_noerr?true:false
  167. //读取一个字典 
  168. bool CBEncode::readdict(char *szCurPos,int & iendpos
  169. ,list<CBEncodeObjectBase*> & listObj) 
  170.     char * szTmp = szCurPos; 
  171.     CBEncodeDict * pNewDict= new CBEncodeDict; 
  172.     pNewDict->szPos = szCurPos;  
  173.     if(*szTmp == 'd'
  174.     {        
  175.         szTmp++; 
  176.         int ilistendpos; 
  177.         string strname; 
  178.         while(*szTmp!='e'
  179.         { 
  180.             if(!readstring(szTmp,ilistendpos,pNewDict->m_listObj)) 
  181.                 break
  182.             if(m_plastObj->m_type !=enum_BEncodeType_String) 
  183.                 break;           
  184.             strname.assign(((CBEncodeString *)m_plastObj)->m_szData
  185. ,((CBEncodeString *)m_plastObj)->m_ilen); 
  186.             szTmp+=ilistendpos; 
  187.             if(*szTmp== 'i'
  188.             { 
  189.                 if(!readint(szTmp,ilistendpos,pNewDict->m_listObj)) 
  190.                     break;//遇到任何错误都终止整个解析 
  191.                 szTmp+=ilistendpos; 
  192.             } 
  193.             else if(*szTmp== 'l'
  194.             { 
  195.                 if(!readlist(szTmp,ilistendpos,pNewDict->m_listObj)) 
  196.                     break
  197.                 szTmp+=ilistendpos; 
  198.             } 
  199.             else if(*szTmp== 'd'
  200.             { 
  201.                 if(!readdict(szTmp,ilistendpos,pNewDict->m_listObj)) 
  202.                     break
  203.                 szTmp+=ilistendpos; 
  204.             } 
  205.             else             
  206.             { 
  207.                 if(!readstring(szTmp,ilistendpos,pNewDict->m_listObj)) 
  208.                     break
  209.                 szTmp+=ilistendpos; 
  210.             } 
  211.             pNewDict->m_mapObj.insert(pair<string
  212. ,CBEncodeObjectBase*>(strname,m_plastObj));             
  213.         }    
  214.         if(*szTmp!='e'||m_plastObj->m_error != enm_BEncodeErr_noerr) 
  215.             pNewDict->m_error = enm_BEncodeErr_errDict; 
  216.         else 
  217.             szTmp++; 
  218.     } 
  219.     else 
  220.         pNewDict->m_error = enm_BEncodeErr_errDict; 
  221.     listObj.push_back(pNewDict); 
  222.     iendpos = szTmp-szCurPos; 
  223.     m_plastObj = pNewDict;   
  224.     m_plastObj->ilen = iendpos; 
  225.     return pNewDict->m_error == enm_BEncodeErr_noerr?true:false

 


(lightest)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201205/16046.html]
本文出处:CSDN博客 作者:lightest 原文
顶一下
(2)
100%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容