Bdecode.cpp
上传用户:lds876
上传日期:2013-05-25
资源大小:567k
文件大小:5k
源码类别:

P2P编程

开发平台:

Visual C++

  1. // Bdecode.cpp: implementation of the CBdecode class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "testBT.h"
  6. #include "Bdecode.h"
  7. #ifdef _DEBUG
  8. #undef THIS_FILE
  9. static char THIS_FILE[]=__FILE__;
  10. #define new DEBUG_NEW
  11. #endif
  12. //////////////////////////////////////////////////////////////////////
  13. // Construction/Destruction
  14. //////////////////////////////////////////////////////////////////////
  15. CBdecode::CBdecode()
  16. {
  17. m_lsize = 0;
  18. m_pBuf = 0;
  19. }
  20. CBdecode::~CBdecode()
  21. {
  22. }
  23. CVal* CBdecode::decode_int(long &lPos)
  24. {
  25. //*
  26. long lOldPos = lPos;
  27. for (; lPos<m_lsize; lPos++)
  28. {
  29. if (m_pBuf[lPos] == 'e')
  30. {
  31. lPos ++;
  32. break;
  33. }
  34. }
  35. if (lPos > m_lsize)
  36. return 0;
  37. char* pstrStop = 0;
  38. long l = strtol(m_pBuf+lOldPos, &pstrStop, 10);
  39. if (pstrStop[0] != 'e')
  40. return 0;
  41. return new CVal(l);
  42. }
  43. CVal* CBdecode::decode_string(long &lPos)
  44. {
  45. long lOldPos = lPos;
  46. for (; lPos<m_lsize; lPos++)
  47. {
  48. if (m_pBuf[lPos] == ':')
  49. {
  50. lPos ++;
  51. break;
  52. }
  53. }
  54. if (lPos > m_lsize)
  55. return 0;
  56. char* pstrStop = 0;
  57. long len = strtol(m_pBuf+lOldPos, &pstrStop, 10);
  58. if (pstrStop[0] != ':')
  59. return 0;
  60. if ((lPos+len) > m_lsize)
  61. return 0;
  62. CVal* pVal = new CVal(m_pBuf+lPos, len);
  63. lPos += len;
  64.  
  65. return pVal;
  66. }
  67. void ClearList(VALLIST* pls)
  68. {
  69. VALLIST::iterator iter = pls->begin();
  70. while(iter != pls->end())
  71. {
  72. delete *iter;
  73. iter++;
  74. }
  75. }
  76. CVal* CBdecode::decode_list(long &lPos)
  77. {
  78. VALLIST* ls = new VALLIST();
  79. for (; lPos<m_lsize; )
  80. {
  81. if (m_pBuf[lPos] == 'e')
  82. {
  83. lPos++;
  84. break;
  85. }
  86. CVal* pRet = bdecode_rec(lPos);
  87. if (!pRet)
  88. {
  89. ClearList(ls);
  90. delete ls;
  91. return 0;
  92. }
  93. ls->push_back(pRet);
  94. }
  95. if (lPos > m_lsize)
  96. {
  97. ClearList(ls);
  98. delete ls;
  99. return 0;
  100. }
  101. return new CVal(ls);
  102. }
  103. void ClearMap(VALMAP* pmap)
  104. {
  105. VALMAP::iterator iter = pmap->begin();
  106. while(iter != pmap->end())
  107. {
  108. delete (*iter).second;
  109. iter++;
  110. }
  111. }
  112. CVal*  CBdecode::decode_dict(long& lPos)
  113. {
  114. VALMAP* pmap = new VALMAP();
  115. string strLast;
  116. for (; lPos<m_lsize;)
  117. {
  118. if (m_pBuf[lPos] == 'e')
  119. {
  120. lPos++;
  121. break;
  122. }
  123. CVal* pRet = decode_string(lPos);
  124. if (!pRet)
  125. {
  126. ClearMap(pmap);
  127. delete pmap;
  128. return 0;
  129. }
  130. string strCur = pRet->pstrVal;
  131. delete pRet;
  132. if (strLast.size() > 0)
  133. {
  134. if (strCur <= strLast)
  135. {
  136. ClearMap(pmap);
  137. delete pmap;
  138. return 0;
  139. }
  140. }
  141. strLast = strCur;
  142. CVal* pRetVal = bdecode_rec(lPos);
  143. if (!pRetVal)
  144. {
  145. ClearMap(pmap);
  146. delete pmap;
  147. return 0;
  148. }
  149. (*pmap)[strLast] = pRetVal;
  150. }
  151. if (lPos > m_lsize)
  152. {
  153. ClearMap(pmap);
  154. delete pmap;
  155. return 0;
  156. }
  157. return new CVal(pmap);
  158. }
  159. CVal* CBdecode::bdecode_rec(long& lPos)
  160. {
  161. CVal* pRet = 0;
  162. char t = m_pBuf[lPos];
  163. switch (t)
  164. {
  165. case 'i':
  166. return decode_int(++lPos);
  167. case 'l':
  168. return decode_list(++lPos); 
  169. case 'd':
  170. return decode_dict(++lPos);
  171. default:
  172. return decode_string(lPos);
  173. }
  174. }
  175. CVal* CBdecode::bdecode(char *pbuf, long lsize)
  176. {
  177. if (lsize <= 0)
  178. {
  179. // assert(false);
  180. return 0;
  181. }
  182. m_lsize = lsize;
  183. m_pBuf = pbuf;
  184. long lPos = 0;
  185. CVal* v = bdecode_rec(lPos);
  186. if (lPos > m_lsize)
  187. {
  188. if (v)
  189. delete v;
  190. return 0;
  191. }
  192. return v;
  193. }
  194. void CBdecode::bencode(CVal *pVal, memstream& memRet)
  195. {
  196. bencode_rec(pVal, memRet);
  197. }
  198. void CBdecode::bencode_rec(CVal *pVal, memstream &strRet)
  199. {
  200. char temp[100] = {0};
  201. switch (pVal->vt)
  202. {
  203. case VT_LONG:
  204. sprintf(temp, "%d", pVal->lVal);
  205. strRet += string("i") + temp + "e";
  206. break;
  207. case VT_PSTR:
  208. sprintf(temp, "%d", pVal->lstrLen);
  209. strRet += string(temp) + ":";
  210. // strRet += string(temp) + ":" + pVal->pstrVal;
  211. strRet.write(pVal->pstrVal, pVal->lstrLen);
  212. break;
  213. case VT_PLIST:
  214. {
  215. strRet += "l";
  216. for (int i=0; i<pVal->plistVal->size(); i++)
  217. bencode_rec((*pVal->plistVal)[i], strRet);
  218. strRet += "e";
  219. }
  220. break;
  221. case VT_PMAP:
  222. {
  223. strRet += "d";
  224. for (VALMAP::iterator iter=pVal->pmapVal->begin(); iter != pVal->pmapVal->end(); iter++)
  225. {
  226. string strKey = (*iter).first;
  227. /*
  228. char* pstrBuf = new char[strKey.size()+1];
  229. memset(pstrBuf, 0, strKey.size()+1);
  230. memcpy(pstrBuf, strKey.data(), strKey.size());
  231. CVal v(pstrBuf, strKey.size());
  232. //*/
  233. CVal v(strKey);
  234. bencode_rec(&v, strRet);
  235. bencode_rec((*iter).second, strRet);
  236. }
  237. strRet += "e";
  238. }
  239. break;
  240. default:
  241. assert(false);
  242. break;
  243. }
  244. }