zoukankan      html  css  js  c++  java
  • 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驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    相对路径和绝对路径的问题"/"带不带斜杠
    El表达式获取项目名称
    struts 中的创建Action的三种方法
    maven中的profile文件的解析
    Maven中模块的聚合以及对jar包的继承
    Maven中解决依赖冲突的问题
    maven中的传递依赖和传递依赖的解除
    String类为什么是final的
    jdbc 报错解决办法
    org.hibernate.PropertyValueException: not-null property references a null or transient value:
  • 原文地址:https://www.cnblogs.com/itdef/p/9943709.html
Copyright © 2011-2022 走看看