Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert dedicated dict_key type to a 1-element map #276

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/torrent/object.cc
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,6 @@ Object::operator = (const Object& src) {
case TYPE_STRING: new (&_string()) string_type(src._string()); break;
case TYPE_LIST: new (&_list()) list_type(src._list()); break;
case TYPE_MAP: _map_ptr() = new map_type(src._map()); break;
case TYPE_DICT_KEY: new (&_dict_key()) dict_key_type(src._dict_key()); _dict_key().second = new Object(*src._dict_key().second); break;
default: t_pod = src.t_pod; break;
}

Expand Down
76 changes: 6 additions & 70 deletions src/torrent/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ class LIBTORRENT_EXPORT Object {
typedef std::map<std::string, Object> map_type;
typedef map_type* map_ptr_type;
typedef map_type::key_type key_type;
typedef std::pair<std::string, Object*> dict_key_type;

typedef list_type::iterator list_iterator;
typedef list_type::const_iterator list_const_iterator;
Expand Down Expand Up @@ -94,8 +93,7 @@ class LIBTORRENT_EXPORT Object {
TYPE_VALUE,
TYPE_STRING,
TYPE_LIST,
TYPE_MAP,
TYPE_DICT_KEY
TYPE_MAP
};

Object() : m_flags(TYPE_NONE) {}
Expand All @@ -117,7 +115,6 @@ class LIBTORRENT_EXPORT Object {
static Object create_string() { return Object(string_type()); }
static Object create_list() { Object tmp; tmp.m_flags = TYPE_LIST; new (&tmp._list()) list_type(); return tmp; }
static Object create_map() { Object tmp; tmp.m_flags = TYPE_MAP; tmp._map_ptr() = new map_type(); return tmp; }
static Object create_dict_key();

static Object create_raw_bencode(raw_bencode obj = raw_bencode());
static Object create_raw_string(raw_string obj = raw_string());
Expand Down Expand Up @@ -152,11 +149,12 @@ class LIBTORRENT_EXPORT Object {
bool is_string_empty() const { return type() != TYPE_STRING || _string().empty(); }
bool is_list() const { return type() == TYPE_LIST; }
bool is_map() const { return type() == TYPE_MAP; }
bool is_dict_key() const { return type() == TYPE_DICT_KEY; }
bool is_raw_bencode() const { return type() == TYPE_RAW_BENCODE; }
bool is_raw_string() const { return type() == TYPE_RAW_STRING; }
bool is_raw_list() const { return type() == TYPE_RAW_LIST; }
bool is_raw_map() const { return type() == TYPE_RAW_MAP; }
// TYPE_DICT_KEY used to be a dedicated type, now it's an alias for a function map
bool is_dict_key() const { return type() == TYPE_MAP && (flags() & mask_function); }

value_type& as_value() { check_throw(TYPE_VALUE); return _value(); }
const value_type& as_value() const { check_throw(TYPE_VALUE); return _value(); }
Expand All @@ -168,10 +166,9 @@ class LIBTORRENT_EXPORT Object {
const list_type& as_list() const { check_throw(TYPE_LIST); return _list(); }
map_type& as_map() { check_throw(TYPE_MAP); return _map(); }
const map_type& as_map() const { check_throw(TYPE_MAP); return _map(); }
string_type& as_dict_key() { check_throw(TYPE_DICT_KEY); return _dict_key().first; }
const string_type& as_dict_key() const { check_throw(TYPE_DICT_KEY); return _dict_key().first; }
Object& as_dict_obj() { check_throw(TYPE_DICT_KEY); return *_dict_key().second; }
const Object& as_dict_obj() const { check_throw(TYPE_DICT_KEY); return *_dict_key().second; }
const string_type& as_dict_key() const { check_throw(TYPE_MAP); return _map().begin()->first; }
Object& as_dict_obj() { check_throw(TYPE_MAP); return _map().begin()->second; }
const Object& as_dict_obj() const { check_throw(TYPE_MAP); return _map().begin()->second; }
raw_bencode& as_raw_bencode() { check_throw(TYPE_RAW_BENCODE); return _raw_bencode(); }
const raw_bencode& as_raw_bencode() const { check_throw(TYPE_RAW_BENCODE); return _raw_bencode(); }
raw_string& as_raw_string() { check_throw(TYPE_RAW_STRING); return _raw_string(); }
Expand Down Expand Up @@ -254,7 +251,6 @@ class LIBTORRENT_EXPORT Object {

uint32_t m_flags;

#ifndef HAVE_STDCXX_0X
value_type& _value() { return t_value; }
const value_type& _value() const { return t_value; }
string_type& _string() { return t_string; }
Expand All @@ -265,8 +261,6 @@ class LIBTORRENT_EXPORT Object {
const map_type& _map() const { return *t_map; }
map_ptr_type& _map_ptr() { return t_map; }
const map_ptr_type& _map_ptr() const { return t_map; }
dict_key_type& _dict_key() { return t_dict_key; }
const dict_key_type& _dict_key() const { return t_dict_key; }
raw_object& _raw_object() { return t_raw_object; }
const raw_object& _raw_object() const { return t_raw_object; }
raw_bencode& _raw_bencode() { return t_raw_bencode; }
Expand Down Expand Up @@ -294,53 +288,12 @@ class LIBTORRENT_EXPORT Object {
string_type t_string;
list_type t_list;
map_type* t_map;
dict_key_type t_dict_key;
raw_object t_raw_object;
raw_bencode t_raw_bencode;
raw_string t_raw_string;
raw_list t_raw_list;
raw_map t_raw_map;
};

#else
// #error "WTF we're testing C++11 now."

value_type& _value() { return reinterpret_cast<value_type&>(t_pod); }
const value_type& _value() const { return reinterpret_cast<const value_type&>(t_pod); }
string_type& _string() { return reinterpret_cast<string_type&>(t_string); }
const string_type& _string() const { return reinterpret_cast<const string_type&>(t_string); }
list_type& _list() { return reinterpret_cast<list_type&>(t_list); }
const list_type& _list() const { return reinterpret_cast<const list_type&>(t_list); }
map_type& _map() { return *reinterpret_cast<map_ptr_type&>(t_pod); }
const map_type& _map() const { return *reinterpret_cast<const map_ptr_type&>(t_pod); }
map_ptr_type& _map_ptr() { return reinterpret_cast<map_ptr_type&>(t_pod); }
const map_ptr_type& _map_ptr() const { return reinterpret_cast<const map_ptr_type&>(t_pod); }
dict_key_type& _dict_key() { return reinterpret_cast<dict_key_type&>(t_pod); }
const dict_key_type& _dict_key() const { return reinterpret_cast<const dict_key_type&>(t_pod); }
raw_object& _raw_object() { return reinterpret_cast<raw_object&>(t_pod); }
const raw_object& _raw_object() const { return reinterpret_cast<const raw_object&>(t_pod); }
raw_bencode& _raw_bencode() { return reinterpret_cast<raw_bencode&>(t_pod); }
const raw_bencode& _raw_bencode() const { return reinterpret_cast<const raw_bencode&>(t_pod); }
raw_string& _raw_string() { return reinterpret_cast<raw_string&>(t_pod); }
const raw_string& _raw_string() const { return reinterpret_cast<const raw_string&>(t_pod); }
raw_list& _raw_list() { return reinterpret_cast<raw_list&>(t_pod); }
const raw_list& _raw_list() const { return reinterpret_cast<const raw_list&>(t_pod); }
raw_map& _raw_map() { return reinterpret_cast<raw_map&>(t_pod); }
const raw_map& _raw_map() const { return reinterpret_cast<const raw_map&>(t_pod); }

union pod_types {
value_type t_value;
map_type* t_map;
char t_raw_object[sizeof(raw_object)];
};

union {
pod_types t_pod;
char t_string[sizeof(string_type)];
char t_list[sizeof(list_type)];
char t_dict_key[sizeof(dict_key_type)];
};
#endif
};

inline
Expand All @@ -357,9 +310,6 @@ Object::Object(const Object& b) {
case TYPE_STRING: new (&_string()) string_type(b._string()); break;
case TYPE_LIST: new (&_list()) list_type(b._list()); break;
case TYPE_MAP: _map_ptr() = new map_type(b._map()); break;
case TYPE_DICT_KEY:
new (&_dict_key().first) string_type(b._dict_key().first);
_dict_key().second = new Object(*b._dict_key().second); break;
}
}

Expand All @@ -374,7 +324,6 @@ Object::create_empty(type_type t) {
case TYPE_STRING: return create_string();
case TYPE_LIST: return create_list();
case TYPE_MAP: return create_map();
case TYPE_DICT_KEY: return create_dict_key();
case TYPE_NONE:
default: return torrent::Object();
}
Expand All @@ -392,15 +341,6 @@ Object object_create_normal(const raw_list& obj) LIBTORRENT_EXPORT;
Object object_create_normal(const raw_map& obj) LIBTORRENT_EXPORT;
inline Object object_create_normal(const raw_string& obj) { return torrent::Object(obj.as_string()); }

inline Object
Object::create_dict_key() {
Object tmp;
tmp.m_flags = TYPE_DICT_KEY;
new (&tmp._dict_key()) dict_key_type();
tmp._dict_key().second = new Object();
return tmp;
}

inline Object
Object::create_raw_bencode(raw_bencode obj) {
Object tmp; tmp.m_flags = TYPE_RAW_BENCODE; new (&tmp._raw_bencode()) raw_bencode(obj); return tmp;
Expand Down Expand Up @@ -453,7 +393,6 @@ Object::clear() {
case TYPE_STRING: _string().~string_type(); break;
case TYPE_LIST: _list().~list_type(); break;
case TYPE_MAP: delete _map_ptr(); break;
case TYPE_DICT_KEY: delete _dict_key().second; _dict_key().~dict_key_type(); break;
default: break;
}

Expand All @@ -468,9 +407,6 @@ Object::swap_same_type(Object& left, Object& right) {
switch (left.type()) {
case Object::TYPE_STRING: left._string().swap(right._string()); break;
case Object::TYPE_LIST: left._list().swap(right._list()); break;
case Object::TYPE_DICT_KEY:
std::swap(left._dict_key().first, right._dict_key().first);
std::swap(left._dict_key().second, right._dict_key().second); break;
default: std::swap(left.t_pod, right.t_pod); break;
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/torrent/object_stream.cc
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,9 @@ object_write_bencode_c_object(object_write_data_t* output, const Object* object,
break;

case Object::TYPE_MAP:
if (object->is_dict_key())
throw torrent::bencode_error("Cannot bencode internal dict_key type.");

object_write_bencode_c_char(output, 'd');

for (Object::map_const_iterator itr = object->as_map().begin(), last = object->as_map().end(); itr != last; ++itr) {
Expand All @@ -567,9 +570,6 @@ object_write_bencode_c_object(object_write_data_t* output, const Object* object,

object_write_bencode_c_char(output, 'e');
break;
case Object::TYPE_DICT_KEY:
throw torrent::bencode_error("Cannot bencode internal dict_key type.");
break;
}
}

Expand Down
25 changes: 0 additions & 25 deletions test/torrent/object_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -78,29 +78,6 @@ swap_compare(const char* left, const char* right) {
return true;
}

static bool
swap_compare_dict_key(const char* left_key, const char* left_obj, const char* right_key, const char* right_obj) {
torrent::Object obj_left = torrent::Object::create_dict_key();
torrent::Object obj_right = torrent::Object::create_dict_key();

obj_left.as_dict_key() = left_key;
obj_left.as_dict_obj() = create_bencode(left_obj);
obj_right.as_dict_key() = right_key;
obj_right.as_dict_obj() = create_bencode(right_obj);

obj_left.swap(obj_right);
if (obj_left.as_dict_key() != right_key || !compare_bencode(obj_left.as_dict_obj(), right_obj) ||
obj_right.as_dict_key() != left_key || !compare_bencode(obj_right.as_dict_obj(), left_obj))
return false;

obj_left.swap(obj_right);
if (obj_left.as_dict_key() != left_key || !compare_bencode(obj_left.as_dict_obj(), left_obj) ||
obj_right.as_dict_key() != right_key || !compare_bencode(obj_right.as_dict_obj(), right_obj))
return false;

return true;
}

void
ObjectTest::test_swap_and_move() {
CPPUNIT_ASSERT(swap_compare(TEST_VALUE_A, TEST_VALUE_B));
Expand All @@ -117,8 +94,6 @@ ObjectTest::test_swap_and_move() {
CPPUNIT_ASSERT(swap_compare("i1e", TEST_MAP_A));
CPPUNIT_ASSERT(swap_compare("i1e", TEST_LIST_A));

CPPUNIT_ASSERT(swap_compare_dict_key("a", TEST_VALUE_A, "b", TEST_STRING_B));
CPPUNIT_ASSERT(swap_compare_dict_key("a", TEST_STRING_A, "b", TEST_STRING_B));
}

void
Expand Down