1
// libTorrent - BitTorrent library
2
// Copyright (C) 2005-2007, Jari Sundell
4
// This program is free software; you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation; either version 2 of the License, or
7
// (at your option) any later version.
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
// GNU General Public License for more details.
14
// You should have received a copy of the GNU General Public License
15
// along with this program; if not, write to the Free Software
16
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
// In addition, as a special exception, the copyright holders give
19
// permission to link the code of portions of this program with the
20
// OpenSSL library under certain conditions as described in each
21
// individual source file, and distribute linked combinations
24
// You must obey the GNU General Public License in all respects for
25
// all of the code used other than OpenSSL. If you modify file(s)
26
// with this exception, you may extend this exception to your version
27
// of the file(s), but you are not obligated to do so. If you do not
28
// wish to do so, delete this exception statement from your version.
29
// If you delete this exception statement from all source files in the
30
// program, then also delete it here.
32
// Contact: Jari Sundell <jaris@ifi.uio.no>
35
// 3185 Skoppum, NORWAY
37
#ifndef LIBTORRENT_OBJECT_H
38
#define LIBTORRENT_OBJECT_H
43
#include <torrent/common.h>
44
#include <torrent/exceptions.h>
45
#include <torrent/object_raw_bencode.h>
49
class LIBTORRENT_EXPORT Object {
51
typedef int64_t value_type;
52
typedef std::string string_type;
53
typedef std::vector<Object> list_type;
54
typedef std::map<std::string, Object> map_type;
55
typedef map_type* map_ptr_type;
56
typedef map_type::key_type key_type;
58
typedef list_type::iterator list_iterator;
59
typedef list_type::const_iterator list_const_iterator;
60
typedef list_type::reverse_iterator list_reverse_iterator;
61
typedef list_type::const_reverse_iterator list_const_reverse_iterator;
63
typedef map_type::iterator map_iterator;
64
typedef map_type::const_iterator map_const_iterator;
65
typedef map_type::reverse_iterator map_reverse_iterator;
66
typedef map_type::const_reverse_iterator map_const_reverse_iterator;
68
typedef std::pair<map_iterator, bool> map_insert_type;
70
// Flags in the range of 0xffff0000 may be set by the user, however
71
// 0x00ff0000 are reserved for keywords defined by libtorrent.
72
static const uint32_t mask_type = 0xff;
73
static const uint32_t mask_flags = ~mask_type;
74
static const uint32_t mask_internal = 0xffff;
75
static const uint32_t mask_public = ~mask_internal;
77
static const uint32_t flag_unordered = 0x100; // bencode dictionary was not sorted
78
static const uint32_t flag_static_data = 0x10000; // Object does not change across sessions.
79
static const uint32_t flag_session_data = 0x20000; // Object changes between sessions.
93
Object() : m_flags(TYPE_NONE) {}
94
Object(const value_type v) : m_flags(TYPE_VALUE) { new (&_value()) value_type(v); }
95
Object(const char* s) : m_flags(TYPE_STRING) { new (&_string()) string_type(s); }
96
Object(const string_type& s) : m_flags(TYPE_STRING) { new (&_string()) string_type(s); }
97
Object(const raw_bencode& r) : m_flags(TYPE_RAW_BENCODE) { new (&_raw_bencode()) raw_bencode(r); }
98
Object(const raw_string& r) : m_flags(TYPE_RAW_STRING) { new (&_raw_string()) raw_string(r); }
99
Object(const raw_list& r) : m_flags(TYPE_RAW_LIST) { new (&_raw_list()) raw_list(r); }
100
Object(const raw_map& r) : m_flags(TYPE_RAW_MAP) { new (&_raw_map()) raw_map(r); }
101
Object(const Object& b);
103
~Object() { clear(); }
105
// TODO: Move this out of the class namespace, call them
107
static Object create_empty(type_type t);
108
static Object create_value() { return Object(value_type()); }
109
static Object create_string() { return Object(string_type()); }
110
static Object create_list() { Object tmp; tmp.m_flags = TYPE_LIST; new (&tmp._list()) list_type(); return tmp; }
111
static Object create_map() { Object tmp; tmp.m_flags = TYPE_MAP; tmp._map_ptr() = new map_type(); return tmp; }
113
static Object create_raw_bencode(raw_bencode obj = raw_bencode()) {
114
Object tmp; tmp.m_flags = TYPE_RAW_BENCODE; new (&tmp._raw_bencode()) raw_bencode(obj); return tmp;
116
static Object create_raw_string(raw_string obj = raw_string()) {
117
Object tmp; tmp.m_flags = TYPE_RAW_STRING; new (&tmp._raw_string()) raw_string(obj); return tmp;
119
static Object create_raw_list(raw_list obj = raw_list()) {
120
Object tmp; tmp.m_flags = TYPE_RAW_LIST; new (&tmp._raw_list()) raw_list(obj); return tmp;
122
static Object create_raw_map(raw_map obj = raw_map()) {
123
Object tmp; tmp.m_flags = TYPE_RAW_MAP; new (&tmp._raw_map()) raw_map(obj); return tmp;
126
template <typename ForwardIterator>
127
static Object create_list_range(ForwardIterator first, ForwardIterator last);
129
// Clear should probably not be inlined due to size and not being
130
// optimized away in pretty much any case. Might not work well in
131
// cases where we pass constant rvalues.
134
type_type type() const { return (type_type)(m_flags & mask_type); }
135
uint32_t flags() const { return m_flags & mask_flags; }
137
void set_flags(uint32_t f) { m_flags |= f & mask_public; }
138
void unset_flags(uint32_t f) { m_flags &= ~(f & mask_public); }
140
void set_internal_flags(uint32_t f) { m_flags |= f & (mask_internal & ~mask_type); }
141
void unset_internal_flags(uint32_t f) { m_flags &= ~(f & (mask_internal & ~mask_type)); }
143
// Add functions for setting/clearing the public flags.
145
bool is_empty() const { return type() == TYPE_NONE; }
146
bool is_not_empty() const { return type() != TYPE_NONE; }
147
bool is_value() const { return type() == TYPE_VALUE; }
148
bool is_string() const { return type() == TYPE_STRING; }
149
bool is_list() const { return type() == TYPE_LIST; }
150
bool is_map() const { return type() == TYPE_MAP; }
151
bool is_raw_bencode() const { return type() == TYPE_RAW_BENCODE; }
152
bool is_raw_string() const { return type() == TYPE_RAW_STRING; }
153
bool is_raw_list() const { return type() == TYPE_RAW_LIST; }
154
bool is_raw_map() const { return type() == TYPE_RAW_MAP; }
156
value_type& as_value() { check_throw(TYPE_VALUE); return _value(); }
157
const value_type& as_value() const { check_throw(TYPE_VALUE); return _value(); }
158
string_type& as_string() { check_throw(TYPE_STRING); return _string(); }
159
const string_type& as_string() const { check_throw(TYPE_STRING); return _string(); }
160
list_type& as_list() { check_throw(TYPE_LIST); return _list(); }
161
const list_type& as_list() const { check_throw(TYPE_LIST); return _list(); }
162
map_type& as_map() { check_throw(TYPE_MAP); return _map(); }
163
const map_type& as_map() const { check_throw(TYPE_MAP); return _map(); }
164
raw_bencode& as_raw_bencode() { check_throw(TYPE_RAW_BENCODE); return _raw_bencode(); }
165
const raw_bencode& as_raw_bencode() const { check_throw(TYPE_RAW_BENCODE); return _raw_bencode(); }
166
raw_string& as_raw_string() { check_throw(TYPE_RAW_STRING); return _raw_string(); }
167
const raw_string& as_raw_string() const { check_throw(TYPE_RAW_STRING); return _raw_string(); }
168
raw_list& as_raw_list() { check_throw(TYPE_RAW_LIST); return _raw_list(); }
169
const raw_list& as_raw_list() const { check_throw(TYPE_RAW_LIST); return _raw_list(); }
170
raw_map& as_raw_map() { check_throw(TYPE_RAW_MAP); return _raw_map(); }
171
const raw_map& as_raw_map() const { check_throw(TYPE_RAW_MAP); return _raw_map(); }
173
bool has_key(const key_type& k) const { check_throw(TYPE_MAP); return _map().find(k) != _map().end(); }
174
bool has_key_value(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_VALUE); }
175
bool has_key_string(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_STRING); }
176
bool has_key_list(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_LIST); }
177
bool has_key_map(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_MAP); }
178
bool has_key_raw_bencode(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_RAW_BENCODE); }
179
bool has_key_raw_string(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_RAW_STRING); }
180
bool has_key_raw_list(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_RAW_LIST); }
181
bool has_key_raw_map(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_RAW_MAP); }
183
// Should have an interface for that returns pointer or something,
184
// so we don't need to search twice.
186
// Make these inline...
188
Object& get_key(const key_type& k);
189
const Object& get_key(const key_type& k) const;
190
Object& get_key(const char* k);
191
const Object& get_key(const char* k) const;
193
template <typename T> value_type& get_key_value(const T& k) { return get_key(k).as_value(); }
194
template <typename T> const value_type& get_key_value(const T& k) const { return get_key(k).as_value(); }
195
template <typename T> string_type& get_key_string(const T& k) { return get_key(k).as_string(); }
196
template <typename T> const string_type& get_key_string(const T& k) const { return get_key(k).as_string(); }
197
template <typename T> list_type& get_key_list(const T& k) { return get_key(k).as_list(); }
198
template <typename T> const list_type& get_key_list(const T& k) const { return get_key(k).as_list(); }
199
template <typename T> map_type& get_key_map(const T& k) { return get_key(k).as_map(); }
200
template <typename T> const map_type& get_key_map(const T& k) const { return get_key(k).as_map(); }
202
Object& insert_key(const key_type& k, const Object& b) { check_throw(TYPE_MAP); return _map()[k] = b; }
203
Object& insert_key_move(const key_type& k, Object& b) { check_throw(TYPE_MAP); return _map()[k].move(b); }
205
// 'insert_preserve_*' inserts the object 'b' if the key 'k' does
206
// not exist, else it returns the old entry. The type specific
207
// versions also require the old entry to be of the same type.
209
// Consider making insert_preserve_* return std::pair<Foo*,bool> or
210
// something similar.
211
map_insert_type insert_preserve_any(const key_type& k, const Object& b) { check_throw(TYPE_MAP); return _map().insert(map_type::value_type(k, b)); }
212
map_insert_type insert_preserve_type(const key_type& k, Object& b);
213
map_insert_type insert_preserve_copy(const key_type& k, Object b) { return insert_preserve_type(k, b); }
215
void erase_key(const key_type& k) { check_throw(TYPE_MAP); _map().erase(k); }
217
Object& insert_front(const Object& b) { check_throw(TYPE_LIST); return *_list().insert(_list().begin(), b); }
218
Object& insert_back(const Object& b) { check_throw(TYPE_LIST); return *_list().insert(_list().end(), b); }
220
// Copy and merge operations:
221
Object& move(Object& b);
222
Object& swap(Object& b);
223
Object& swap_same_type(Object& b);
225
// Only map entries are merged.
226
Object& merge_move(Object& object, uint32_t maxDepth = ~uint32_t());
227
Object& merge_copy(const Object& object,
228
uint32_t skip_mask = flag_static_data,
229
uint32_t maxDepth = ~uint32_t());
231
Object& operator = (const Object& b);
234
void swap_same_type(Object& left, Object& right);
237
inline bool check(map_type::const_iterator itr, type_type t) const { return itr != _map().end() && itr->second.type() == t; }
238
inline void check_throw(type_type t) const { if (t != type()) throw bencode_error("Wrong object type."); }
242
value_type& _value() { return reinterpret_cast<value_type&>(t_pod); }
243
const value_type& _value() const { return reinterpret_cast<const value_type&>(t_pod); }
244
string_type& _string() { return reinterpret_cast<string_type&>(t_string); }
245
const string_type& _string() const { return reinterpret_cast<const string_type&>(t_string); }
246
list_type& _list() { return reinterpret_cast<list_type&>(t_list); }
247
const list_type& _list() const { return reinterpret_cast<const list_type&>(t_list); }
248
map_type& _map() { return *reinterpret_cast<map_ptr_type&>(t_pod); }
249
const map_type& _map() const { return *reinterpret_cast<const map_ptr_type&>(t_pod); }
250
map_ptr_type& _map_ptr() { return reinterpret_cast<map_ptr_type&>(t_pod); }
251
const map_ptr_type& _map_ptr() const { return reinterpret_cast<const map_ptr_type&>(t_pod); }
252
raw_object& _raw_object() { return reinterpret_cast<raw_object&>(t_pod); }
253
const raw_object& _raw_object() const { return reinterpret_cast<const raw_object&>(t_pod); }
254
raw_bencode& _raw_bencode() { return reinterpret_cast<raw_bencode&>(t_pod); }
255
const raw_bencode& _raw_bencode() const { return reinterpret_cast<const raw_bencode&>(t_pod); }
256
raw_string& _raw_string() { return reinterpret_cast<raw_string&>(t_pod); }
257
const raw_string& _raw_string() const { return reinterpret_cast<const raw_string&>(t_pod); }
258
raw_list& _raw_list() { return reinterpret_cast<raw_list&>(t_pod); }
259
const raw_list& _raw_list() const { return reinterpret_cast<const raw_list&>(t_pod); }
260
raw_map& _raw_map() { return reinterpret_cast<raw_map&>(t_pod); }
261
const raw_map& _raw_map() const { return reinterpret_cast<const raw_map&>(t_pod); }
266
char t_raw_obect[sizeof(raw_object)];
271
char t_string[sizeof(string_type)];
272
char t_list[sizeof(list_type)];
277
Object::Object(const Object& b) {
278
m_flags = b.m_flags & (mask_type | mask_public);
282
case TYPE_RAW_BENCODE:
283
case TYPE_RAW_STRING:
286
case TYPE_VALUE: t_pod = b.t_pod; break;
287
case TYPE_STRING: new (&_string()) string_type(b._string()); break;
288
case TYPE_LIST: new (&_list()) list_type(b._list()); break;
289
case TYPE_MAP: _map_ptr() = new map_type(b._map()); break;
294
Object::create_empty(type_type t) {
296
case TYPE_RAW_BENCODE: return create_raw_bencode();
297
case TYPE_RAW_STRING: return create_raw_string();
298
case TYPE_RAW_LIST: return create_raw_list();
299
case TYPE_RAW_MAP: return create_raw_map();
300
case TYPE_VALUE: return create_value();
301
case TYPE_STRING: return create_string();
302
case TYPE_LIST: return create_list();
303
case TYPE_MAP: return create_map();
305
default: return torrent::Object();
310
object_create_raw_bencode_c_str(const char str[]) {
311
return Object::create_raw_bencode(raw_bencode(str, strlen(str)));
314
// TODO: These do not preserve the flag...
316
Object object_create_normal(const raw_bencode& obj) LIBTORRENT_EXPORT;
317
Object object_create_normal(const raw_list& obj) LIBTORRENT_EXPORT;
318
Object object_create_normal(const raw_map& obj) LIBTORRENT_EXPORT;
319
inline Object object_create_normal(const raw_string& obj) { return torrent::Object(obj.as_string()); }
322
object_create_normal(const Object& obj) {
323
switch (obj.type()) {
324
case Object::TYPE_RAW_BENCODE: return object_create_normal(obj.as_raw_bencode());
325
case Object::TYPE_RAW_STRING: return object_create_normal(obj.as_raw_string());
326
case Object::TYPE_RAW_LIST: return object_create_normal(obj.as_raw_list());
327
case Object::TYPE_RAW_MAP: return object_create_normal(obj.as_raw_map());
333
object_create_string(const torrent::Object& obj) {
334
switch (obj.type()) {
335
case Object::TYPE_RAW_BENCODE: return obj.as_raw_bencode().as_raw_string().as_string();
336
case Object::TYPE_RAW_STRING: return obj.as_raw_string().as_string();
337
default: return obj.as_string();
341
template <typename ForwardIterator>
343
Object::create_list_range(ForwardIterator first, ForwardIterator last) {
344
Object tmp; tmp.m_flags = TYPE_LIST; new (&tmp._list()) list_type(first, last); return tmp;
350
case TYPE_STRING: _string().~string_type(); break;
351
case TYPE_LIST: _list().~list_type(); break;
352
case TYPE_MAP: delete _map_ptr(); break;
361
Object::swap_same_type(Object& left, Object& right) {
362
std::swap(left.m_flags, right.m_flags);
364
switch (left.type()) {
365
case Object::TYPE_STRING: left._string().swap(right._string()); break;
366
case Object::TYPE_LIST: left._list().swap(right._list()); break;
367
default: std::swap(left.t_pod, right.t_pod); break;
371
inline void swap(Object& left, Object& right) { left.swap(right); }
374
object_equal(const Object& left, const Object& right) {
375
if (left.type() != right.type())
378
switch (left.type()) {
379
case Object::TYPE_NONE: return true;
380
case Object::TYPE_VALUE: return left.as_value() == right.as_value();
381
case Object::TYPE_STRING: return left.as_string() == right.as_string();
382
default: return false;