keker123

Untitled

Apr 6th, 2023
140
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.65 KB | None | 0 0
  1. #include <string>
  2. #include <memory>
  3. #include <unordered_map>
  4. #include "map"
  5. #include <utility>
  6. #include <vector>
  7.  
  8. struct BencodeCommon;
  9. struct BencodeInteger;
  10. struct BencodeString;
  11. struct BencodeList;
  12. struct BencodeDictionary;
  13. std::shared_ptr<BencodeCommon> parse_bencode(const char *buffer, size_t length, size_t &pos);
  14.  
  15.  
  16.  
  17.  
  18.  
  19. struct BencodeCommon{
  20.     virtual ~BencodeCommon() = default;
  21.     virtual std::string encode() const = 0;
  22. };
  23.  
  24. struct BencodeInteger : public BencodeCommon{
  25.     long long int_val;
  26.     BencodeInteger(long long int_val) : int_val(int_val) {}
  27.     std::string encode() const override {
  28.         return "i" + std::to_string(int_val) + "e";
  29.     }
  30.     long long get_int() const {
  31.         return int_val;
  32.     }
  33. };
  34.  
  35. struct BencodeString : public BencodeCommon{
  36.     std::string str_val;
  37.     BencodeString(std::string str_val) : str_val(std::move(str_val)) {}
  38.     std::string encode() const override {
  39.         return std::to_string(str_val.length()) + ":" + str_val;
  40.     }
  41.     std::string get_str() const {
  42.         return str_val;
  43.     }
  44. };
  45.  
  46. struct BencodeList : public BencodeCommon{
  47.     std::vector<std::shared_ptr<BencodeCommon>> list_val; // TODO: make iterator
  48.     std::string encode() const override {
  49.         std::string result = "l";
  50.         for (auto &item : list_val) {
  51.             result += item->encode();
  52.         }
  53.         result += "e";
  54.         return result;
  55.     }
  56.     size_t get_size() const{
  57.         return list_val.size();
  58.     }
  59.     std::shared_ptr<BencodeCommon> get(size_t index) const {
  60.         if (index >= list_val.size()) {
  61.             throw std::runtime_error("Invalid bencode: index out of range");
  62.         }
  63.         return list_val[index];
  64.     }
  65. };
  66.  
  67. struct BencodeDictionary : public BencodeCommon{
  68.     std::map<std::string, std::shared_ptr<BencodeCommon>> dict_val;
  69.     std::string encode() const override {
  70.         std::string result = "d";
  71.         for (auto &item : dict_val) {
  72.             result += BencodeString(item.first).encode() + item.second->encode();
  73.         }
  74.         result += "e";
  75.         return result;
  76.     }
  77.     std::shared_ptr<BencodeCommon> get(const std::string &key) const {
  78.         auto it = dict_val.find(key);
  79.         if (it == dict_val.end()) {
  80.             throw std::runtime_error("Invalid bencode: no key " + key);
  81.         }
  82.         return it->second;
  83.     }
  84. };
  85.  
  86. std::shared_ptr<BencodeCommon> parse_bencode(const char *buffer, size_t length, size_t &pos) {
  87.     std::shared_ptr<BencodeCommon> result;
  88.     char c = buffer[pos++];
  89.     switch (c) {
  90.         case 'i': {
  91.             // Integer
  92.             size_t end_pos = pos;
  93.             while (end_pos < length && buffer[end_pos] != 'e') {
  94.                 end_pos++;
  95.             }
  96.             if (end_pos >= length) {
  97.                 throw std::runtime_error("Invalid bencode: unterminated integer");
  98.             }
  99.             std::string int_str(buffer + pos, end_pos - pos);
  100.             result = std::make_shared<BencodeInteger>(stoll(int_str));
  101.             pos = end_pos + 1;
  102.             break;
  103.         }
  104.         case 'l': {
  105.             // List
  106.             result = std::make_shared<BencodeList>();
  107.             while (buffer[pos] != 'e') {
  108.                 std::dynamic_pointer_cast<BencodeList>(result)->list_val.push_back(parse_bencode(buffer, length, pos));
  109.             }
  110.             pos++;
  111.             break;
  112.         }
  113.         case 'd': {
  114.             // Dictionary
  115.             result = std::make_shared<BencodeDictionary>();
  116.             while (buffer[pos] != 'e') {
  117.                 std::string key = std::dynamic_pointer_cast<BencodeString>(parse_bencode(buffer, length, pos))->str_val;
  118.                 std::dynamic_pointer_cast<BencodeDictionary>(result)->dict_val[key] = parse_bencode(buffer, length, pos);
  119.             }
  120.             pos++;
  121.             break;
  122.         }
  123.         default: {
  124.             // String
  125.             size_t end_pos = pos - 1;
  126.             while (end_pos < length && buffer[end_pos] != ':') {
  127.                 if (buffer[end_pos] == 'e') {
  128.                     throw std::runtime_error("Invalid bencode: unexpected end of list or dictionary");
  129.                 }
  130.                 end_pos++;
  131.             }
  132.             if (end_pos >= length) {
  133.                 throw std::runtime_error("Invalid bencode: unterminated string length");
  134.             }
  135.             std::string length_str(buffer + pos - 1, end_pos - pos + 1);
  136.             size_t str_length = stoll(length_str);
  137.             pos = end_pos + 1;
  138.             result = std::make_shared<BencodeString>(std::string(buffer + pos, str_length));
  139.             pos += str_length;
  140.             break;
  141.         }
  142.     }
  143.     return result;
  144. }
Advertisement
Add Comment
Please, Sign In to add comment