BCode解码练习

在学习BT协议中的一个小练习

参考了 https://github.com/airtrack/bitwave

具体B编码解释 可以自行搜索或者参考 这篇文章 

bittorrent 学习(一) 种子文件分析与bitmap位图

代码

 1 #pragma once
 2 #include "pre.h"
 3 #include <string>
 4 #include <vector>
 5 #include <iostream>
 6 #include <list>
 7 #include <map>
 8 
 9 NAMESPACE(DEF)
10 
11 class BCode
12 {
13 public:
14     enum BCODE_TYPE {
15         BCODE_BASE_TYPE = 1,
16         BCODE_STRING_TYPE = 3,
17         BCODE_INTENGER_TYPE = 5,
18         BCODE_LIST_TYPE = 7,
19         BCODE_DICT_TYPE = 9
20     };
21     
22     BCode(BCODE_TYPE type);
23     BCODE_TYPE GetBCodeType()const  { return type_; }
24     virtual ~BCode();
25 
26 protected:
27     BCODE_TYPE type_;
28     long long begin_;
29     long long end_;
30 };
31 
32 
33 class BCodeString :public BCode {
34 public:
35     explicit BCodeString(long long& begin, long long& end,
36         const std::vector<char>& data);
37         
38     bool ReadString(long long& begin,long long& end,int stringLen );
39     int ReadStringLen(long long& begin, long long& end);
40     std::string std_string() { return bcodeStr_; }
41 private:
42     const std::vector<char>& data_;
43     std::string bcodeStr_;
44 };
45 
46 class BCodeIntenger :public BCode {
47 public:
48     explicit BCodeIntenger(long long& begin, long long& end,
49         const std::vector<char>& data);
50 
51 private:
52     const std::vector<char>& data_;
53     long long bcodeInt_;
54 };
55 
56 class BCodeList :public BCode {
57 public:
58     typedef std::list<std::shared_ptr<BCode>> BCodeLists;
59     explicit BCodeList(long long& begin, long long& end,
60         const std::vector<char>& data);
61 
62 private:
63     BCodeList(const BCodeList&) = delete;
64     BCodeList& operator=(const BCodeList&) = delete;
65     BCodeLists bcodeList_;
66     const std::vector<char>& data_;
67 };
68 
69 class BCodeDictionary :public BCode {
70 public:
71     typedef std::map<std::string, std::shared_ptr<BCode> > BCodemap;
72     typedef BCodemap::value_type pair_type;
73 
74     explicit BCodeDictionary(long long& begin, long long& end,
75         const std::vector<char>& data);
76 private:
77     BCodeDictionary(const BCodeDictionary&) = delete;
78     BCodeDictionary& operator=(const BCodeDictionary&) = delete;
79     const std::vector<char>& data_;
80     BCodemap bcodeMap_;
81 };
82 
83 
84 
85 std::shared_ptr<BCode> GetBCodeObject(long long& begin,
86     long long& end,const std::vector<char>& data);
87 
88 
89 
90 NAMESPACEEND(DEF)
BCode.h
  1 #include "BCode.h"
  2 
  3 NAMESPACE(DEF)
  4 
  5 BCode::BCode(BCODE_TYPE type)
  6     :type_(type),begin_(0),end_(0){}
  7 
  8 
  9 BCode::~BCode(){}
 10 
 11 
 12 bool BCodeString::ReadString(
 13     long long& begin, 
 14     long long& end, 
 15     int stringLen) 
 16 {
 17     bool b = false;
 18     long long stringEnd = begin + stringLen;
 19     if (stringEnd > end) {
 20         std::cerr << __FUNCTION__ << ". string range error!" << std::endl;
 21         return b;
 22     }
 23     bcodeStr_.assign(&data_[begin], stringLen);
 24     begin = stringEnd;
 25 #ifdef _DEBUG_PRINT
 26     std::cout << __FUNCTION__ << ". BCodeString = " 
 27         << bcodeStr_ << std::endl;
 28 
 29 #endif // DEBUG
 30 
 31     b = true;
 32     return b;
 33 }
 34 
 35 BCodeString::BCodeString(long long& begin, long long& end,
 36     const std::vector<char>& data)
 37     :bcodeStr_(), BCode(BCODE_STRING_TYPE), data_(data)
 38 {
 39     begin_ = begin;
 40     int stringLen = ReadStringLen(begin, end);
 41     if (stringLen <= 0 || begin >= end || data_[begin] != ':') {
 42         std::cerr << __FUNCTION__ << ". string length error!" << std::endl;
 43         return;
 44     }
 45     begin++;
 46     ReadString(begin, end, stringLen);
 47     end_ = begin;
 48 }
 49 
 50 
 51 int BCodeString::ReadStringLen(
 52     long long& begin, 
 53     long long& end) 
 54 {
 55     std::vector<char> tmp;
 56     if (isdigit(data_[begin]) == 0) {
 57         std::cerr << __FUNCTION__ << ". read num error!" << std::endl;
 58         return 0;
 59     }
 60     while (begin != end && isdigit(data_[begin])) {
 61         tmp.push_back(data_[begin++]);
 62     }
 63     return atoi(&tmp[0]);
 64 }
 65 
 66 BCodeIntenger::BCodeIntenger(long long& begin, long long& end,
 67     const std::vector<char>& data)
 68     :bcodeInt_(), BCode(BCODE_INTENGER_TYPE), data_(data)
 69 {
 70     begin_ = begin;
 71     if (begin >= end || data_[begin] != 'i') {
 72         std::cerr << __FUNCTION__ << ". intenger flag error!" << std::endl;
 73         return;
 74     }
 75     ++begin; //skip 'i'
 76 
 77     std::string intstr;
 78     std::vector<char> tmp;
 79     while (begin != end && data_[begin] != 'e'  ) {
 80         if (!isdigit(data_[begin])) {
 81             std::cerr << __FUNCTION__ << ". get intenger error!" << std::endl;
 82             return;
 83         }
 84         tmp.push_back(data_[begin++]);
 85     }
 86     end_ = begin;
 87     ++begin; //skip 'e'
 88     if (begin > end) {
 89         std::cerr << __FUNCTION__ << ". range error!" << std::endl;
 90         return;
 91     }
 92     
 93     bcodeInt_ = _atoi64(&tmp[0]);
 94 
 95 #ifdef _DEBUG_PRINT
 96     std::cout << __FUNCTION__ << ". BCodeIntenger = "
 97         << bcodeInt_ << std::endl;
 98 #endif // DEBUG
 99 }
100 
101 BCodeList::BCodeList(long long& begin, long long& end,
102     const std::vector<char>& data)
103     :bcodeList_(), BCode(BCODE_LIST_TYPE),data_(data)
104 {
105     begin_ = begin;
106     if (begin >= end || data_[begin] != 'l') {
107         std::cerr << __FUNCTION__ << ". BCodeList error!" << std::endl;
108         return;
109     }
110     ++begin;
111 #ifdef _DEBUG_PRINT
112     std::cout << "start List" << std::endl;
113 #endif // _DEBUG
114 
115     while (begin != end && data_[begin] != 'e') {
116         bcodeList_.push_back(GetBCodeObject(begin,end,data_));
117     }
118     end_ = begin;
119     if (begin >= end || data[end_] != 'e' ) {
120         std::cerr << __FUNCTION__ << ". BCodeList end error!" << std::endl;
121         return;
122     }
123 
124     ++begin;
125 #ifdef _DEBUG_PRINT
126     std::cout << "end List" << std::endl;
127 #endif // _DEBUG
128 }
129 
130 BCodeDictionary::BCodeDictionary(long long& begin, long long& end,
131     const std::vector<char>& data)
132     :bcodeMap_(), BCode(BCODE_DICT_TYPE), data_(data)
133 {
134     begin_ = begin;
135     if (begin >= end || data_[begin] != 'd') {
136         std::cerr << __FUNCTION__ << ". range error!" << std::endl;
137         return;
138     }
139     ++begin; //skip 'd'
140 #ifdef _DEBUG_PRINT
141     std::cout << "dict start " << std::endl;
142 #endif
143     while (begin != end && data[begin] != 'e') {
144 #ifdef _DEBUG_PRINT
145         std::cout << "key is ";
146 #endif
147         BCodeString key(begin, end,data);
148         std::shared_ptr<BCode> value = GetBCodeObject(begin,end,data);
149         if (value) {
150             bcodeMap_.insert(BCodemap::value_type(key.std_string(), value));
151         }
152     }
153 #ifdef _DEBUG_PRINT
154     std::cout << "dict end " << std::endl;
155 #endif
156     end_ = begin;
157     if (begin >= end || data[end_] != 'e') {
158         std::cerr << __FUNCTION__ << ". BCodeDictionary end error!" << std::endl;
159         return;
160     }
161     ++begin;    //skip 'e'
162     
163 
164     return;
165 }
166 
167 std::shared_ptr<BCode> GetBCodeObject(long long& begin,
168     long long& end, const std::vector<char>& data) {
169     if (begin >= end || end > data.size()) {
170         std::cerr << __FUNCTION__ << ". Range error!" << std::endl;
171         return NULL;
172     }
173 
174     switch (data[begin]) {
175     case 'i':
176         return std::shared_ptr<BCode>(new BCodeIntenger(begin, end, data));
177     case 'l':
178         return std::make_shared<BCode>(BCodeList(begin, end, data));
179     case 'd':
180         return std::make_shared<BCode>(BCodeDictionary(begin,end,data));
181     default:
182         return std::make_shared<BCode>(BCodeString(begin, end, data));
183     }
184     
185 
186 
187 }
188 
189 NAMESPACEEND(DEF)
BCode.cpp

测试代码

#include <iostream>
#include "MetaFIleManager.h"

#include "BCode.h"

using namespace DEF;


void BCodetest() {
std::string s = "li1234e8:12345678l3:def3:abce4:1234i56789ee";
//std::string s = "8:123456783:def2:121:a";
std::vector<char> test(s.begin(), s.end());
long long size = test.size();
long long idx0 = 0;
//while (idx0 < size) {
std::shared_ptr<BCode> p = GetBCodeObject(idx0, size, test);
//}

std::cout << std::endl << std::endl;;

std::string s1 = "d4:key1d9:innerKey14:teste9:innerkey2li23456ei1234ei45678eee";
std::vector<char> test1(s1.begin(), s1.end());
long long size1 = test1.size();
long long idx1 = 0;

std::shared_ptr<BCode> p1 = GetBCodeObject(idx1, size1, test1);
}

int main()
{

BCodetest();

}

运行效果如图:

作 者: itdef
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
阿里打赏 微信打赏
原文地址:https://www.cnblogs.com/itdef/p/9943709.html