Repository URL to install this package:
|
Version:
0.16.6-0.1 ▾
|
#ifndef LIBTORRENT_OBJECT_RAW_BENCODE_H
#define LIBTORRENT_OBJECT_RAW_BENCODE_H
#include <algorithm>
#include <string>
#include <cstring>
#include <torrent/common.h>
#include <torrent/exceptions.h>
namespace torrent {
class raw_bencode;
class raw_string;
class raw_list;
class raw_map;
// The base class for static constant version of Objects. This class
// should never be used directly.
class raw_object {
public:
using value_type = const char;
using iterator = const char*;
using const_iterator = const char*;
using size_type = uint32_t;
raw_object() = default;
raw_object(value_type* src_data, size_type src_size) : m_data(src_data), m_size(src_size) {}
bool empty() const { return m_size == 0; }
size_type size() const { return m_size; }
iterator begin() const { return m_data; }
iterator end() const { return m_data + m_size; }
value_type* data() const { return m_data; }
bool operator == (const raw_object& rhs) const { return m_size == rhs.m_size && std::memcmp(m_data, rhs.m_data, m_size) == 0; }
bool operator != (const raw_object& rhs) const { return m_size != rhs.m_size || std::memcmp(m_data, rhs.m_data, m_size) != 0; }
protected:
iterator m_data{};
size_type m_size{};
};
#define RAW_BENCODE_SET_USING \
using raw_object::value_type; \
using raw_object::iterator; \
using raw_object::const_iterator; \
using raw_object::size_type; \
using raw_object::empty; \
using raw_object::size; \
using raw_object::begin; \
using raw_object::end; \
using raw_object::data; \
\
bool operator == (const this_type& rhs) const { return raw_object::operator==(rhs); } \
bool operator != (const this_type& rhs) const { return raw_object::operator!=(rhs); } \
// A raw_bencode object shall always contain valid bencode data or be
// empty.
class raw_bencode : protected raw_object {
public:
using this_type = raw_bencode;
RAW_BENCODE_SET_USING
raw_bencode() = default;
raw_bencode(value_type* src_data, size_type src_size) : raw_object(src_data, src_size) {}
bool is_empty() const { return m_size == 0; }
bool is_value() const { return m_size >= 3 && m_data[0] >= 'i'; }
bool is_raw_string() const { return m_size >= 2 && m_data[0] >= '0' && m_data[0] <= '9'; }
bool is_raw_list() const { return m_size >= 2 && m_data[0] >= 'l'; }
bool is_raw_map() const { return m_size >= 2 && m_data[0] >= 'd'; }
std::string as_value_string() const;
raw_string as_raw_string() const;
raw_list as_raw_list() const;
raw_map as_raw_map() const;
static raw_bencode from_c_str(const char* str) { return raw_bencode(str, std::strlen(str)); }
};
class raw_string : protected raw_object {
public:
using this_type = raw_string;
RAW_BENCODE_SET_USING
raw_string() = default;
raw_string(value_type* src_data, size_type src_size) : raw_object(src_data, src_size) {}
std::string as_string() const { return std::string(m_data, m_size); }
static raw_string from_c_str(const char* str) { return raw_string(str, std::strlen(str)); }
static raw_string from_string(const std::string& str) { return raw_string(str.data(), str.size()); }
};
class raw_list : protected raw_object {
public:
using this_type = raw_list;
RAW_BENCODE_SET_USING
raw_list() = default;
raw_list(value_type* src_data, size_type src_size) : raw_object(src_data, src_size) {}
static raw_list from_c_str(const char* str) { return raw_list(str, std::strlen(str)); }
};
class raw_map : protected raw_object {
public:
using this_type = raw_map;
RAW_BENCODE_SET_USING
raw_map() = default;
raw_map(value_type* src_data, size_type src_size) : raw_object(src_data, src_size) {}
};
//
//
//
inline std::string
raw_bencode::as_value_string() const {
if (!is_value())
throw bencode_error("Wrong object type.");
return std::string(data() + 1, size() - 2);
}
inline raw_string
raw_bencode::as_raw_string() const {
if (!is_raw_string())
throw bencode_error("Wrong object type.");
const_iterator itr = std::find(begin(), end(), ':');
if (itr == end())
throw internal_error("Invalid bencode in raw_bencode.");
return raw_string(itr + 1, std::distance(itr + 1, end()));
}
inline raw_list
raw_bencode::as_raw_list() const {
if (!is_raw_list())
throw bencode_error("Wrong object type.");
return raw_list(m_data + 1, m_size - 2);
}
inline raw_map
raw_bencode::as_raw_map() const {
if (!is_raw_map())
throw bencode_error("Wrong object type.");
return raw_map(m_data + 1, m_size - 2);
}
//
// Redo...
//
inline bool
raw_bencode_equal(const raw_bencode& left, const raw_bencode& right) {
return left.size() == right.size() && std::memcmp(left.begin(), right.begin(), left.size()) == 0;
}
template <typename tmpl_raw_object>
inline bool
raw_bencode_equal(const tmpl_raw_object& left, const char* right, size_t right_size) {
return left.size() == right_size && std::memcmp(left.begin(), right, right_size) == 0;
}
template <typename tmpl_raw_object>
inline bool
raw_bencode_equal_c_str(const tmpl_raw_object& left, const char* right) {
return raw_bencode_equal(left, right, strlen(right));
}
} // namespace torrent
#endif