1 // libTorrent - BitTorrent library
2 // Copyright (C) 2005-2011, Jari Sundell
3 //
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.
8 //
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.
13 //
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
17 //
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
22 // including the two.
23 //
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.
31 //
32 // Contact: Jari Sundell <jaris@ifi.uio.no>
33 //
34 // Skomakerveien 33
35 // 3185 Skoppum, NORWAY
36
37 #ifndef LIBTORRENT_OBJECT_H
38 #define LIBTORRENT_OBJECT_H
39
40 #include <string>
41 #include <map>
42 #include <vector>
43 #include <torrent/common.h>
44 #include <torrent/exceptions.h>
45 #include <torrent/object_raw_bencode.h>
46
47 namespace torrent {
48
49 class LIBTORRENT_EXPORT Object {
50 public:
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;
57 typedef std::pair<std::string, Object*> dict_key_type;
58
59 typedef list_type::iterator list_iterator;
60 typedef list_type::const_iterator list_const_iterator;
61 typedef list_type::reverse_iterator list_reverse_iterator;
62 typedef list_type::const_reverse_iterator list_const_reverse_iterator;
63
64 typedef map_type::iterator map_iterator;
65 typedef map_type::const_iterator map_const_iterator;
66 typedef map_type::reverse_iterator map_reverse_iterator;
67 typedef map_type::const_reverse_iterator map_const_reverse_iterator;
68
69 typedef std::pair<map_iterator, bool> map_insert_type;
70
71 // Flags in the range of 0xffff0000 may be set by the user, however
72 // 0x00ff0000 are reserved for keywords defined by libtorrent.
73 static const uint32_t mask_type = 0xff;
74 static const uint32_t mask_flags = ~mask_type;
75 static const uint32_t mask_internal = 0xffff;
76 static const uint32_t mask_public = ~mask_internal;
77
78 static const uint32_t flag_unordered = 0x100; // bencode dictionary was not sorted
79 static const uint32_t flag_static_data = 0x010000; // Object does not change across sessions.
80 static const uint32_t flag_session_data = 0x020000; // Object changes between sessions.
81 static const uint32_t flag_function = 0x040000; // A function object.
82 static const uint32_t flag_function_q1 = 0x080000; // A quoted function object.
83 static const uint32_t flag_function_q2 = 0x100000; // A double-quoted function object.
84
85 static const uint32_t mask_function = 0x1C0000; // Mask for function objects.
86
87 enum type_type {
88 TYPE_NONE,
89 TYPE_RAW_BENCODE,
90 TYPE_RAW_STRING,
91 TYPE_RAW_LIST,
92 TYPE_RAW_MAP,
93 TYPE_VALUE,
94 TYPE_STRING,
95 TYPE_LIST,
96 TYPE_MAP,
97 TYPE_DICT_KEY
98 };
99
Object()100 Object() : m_flags(TYPE_NONE) {}
Object(const value_type v)101 Object(const value_type v) : m_flags(TYPE_VALUE) { new (&_value()) value_type(v); }
Object(const char * s)102 Object(const char* s) : m_flags(TYPE_STRING) { new (&_string()) string_type(s); }
Object(const string_type & s)103 Object(const string_type& s) : m_flags(TYPE_STRING) { new (&_string()) string_type(s); }
Object(const raw_bencode & r)104 Object(const raw_bencode& r) : m_flags(TYPE_RAW_BENCODE) { new (&_raw_bencode()) raw_bencode(r); }
Object(const raw_string & r)105 Object(const raw_string& r) : m_flags(TYPE_RAW_STRING) { new (&_raw_string()) raw_string(r); }
Object(const raw_list & r)106 Object(const raw_list& r) : m_flags(TYPE_RAW_LIST) { new (&_raw_list()) raw_list(r); }
Object(const raw_map & r)107 Object(const raw_map& r) : m_flags(TYPE_RAW_MAP) { new (&_raw_map()) raw_map(r); }
108 Object(const Object& b);
109
~Object()110 ~Object() { clear(); }
111
112 // TODO: Move this out of the class namespace, call them
113 // make_object_.
114 static Object create_empty(type_type t);
create_value()115 static Object create_value() { return Object(value_type()); }
create_string()116 static Object create_string() { return Object(string_type()); }
create_list()117 static Object create_list() { Object tmp; tmp.m_flags = TYPE_LIST; new (&tmp._list()) list_type(); return tmp; }
create_map()118 static Object create_map() { Object tmp; tmp.m_flags = TYPE_MAP; tmp._map_ptr() = new map_type(); return tmp; }
119 static Object create_dict_key();
120
121 static Object create_raw_bencode(raw_bencode obj = raw_bencode());
122 static Object create_raw_string(raw_string obj = raw_string());
123 static Object create_raw_list(raw_list obj = raw_list());
124 static Object create_raw_map(raw_map obj = raw_map());
125
126 template <typename ForwardIterator>
127 static Object create_list_range(ForwardIterator first, ForwardIterator last);
128
from_list(const list_type & src)129 static Object from_list(const list_type& src) { Object tmp; tmp.m_flags = TYPE_LIST; new (&tmp._list()) list_type(src); return tmp; }
130
131 // Clear should probably not be inlined due to size and not being
132 // optimized away in pretty much any case. Might not work well in
133 // cases where we pass constant rvalues.
134 void clear();
135
type()136 type_type type() const { return (type_type)(m_flags & mask_type); }
flags()137 uint32_t flags() const { return m_flags & mask_flags; }
138
set_flags(uint32_t f)139 void set_flags(uint32_t f) { m_flags |= f & mask_public; }
unset_flags(uint32_t f)140 void unset_flags(uint32_t f) { m_flags &= ~(f & mask_public); }
141
set_internal_flags(uint32_t f)142 void set_internal_flags(uint32_t f) { m_flags |= f & (mask_internal & ~mask_type); }
unset_internal_flags(uint32_t f)143 void unset_internal_flags(uint32_t f) { m_flags &= ~(f & (mask_internal & ~mask_type)); }
144
145 // Add functions for setting/clearing the public flags.
146
is_empty()147 bool is_empty() const { return type() == TYPE_NONE; }
is_not_empty()148 bool is_not_empty() const { return type() != TYPE_NONE; }
is_value()149 bool is_value() const { return type() == TYPE_VALUE; }
is_string()150 bool is_string() const { return type() == TYPE_STRING; }
is_string_empty()151 bool is_string_empty() const { return type() != TYPE_STRING || _string().empty(); }
is_list()152 bool is_list() const { return type() == TYPE_LIST; }
is_map()153 bool is_map() const { return type() == TYPE_MAP; }
is_dict_key()154 bool is_dict_key() const { return type() == TYPE_DICT_KEY; }
is_raw_bencode()155 bool is_raw_bencode() const { return type() == TYPE_RAW_BENCODE; }
is_raw_string()156 bool is_raw_string() const { return type() == TYPE_RAW_STRING; }
is_raw_list()157 bool is_raw_list() const { return type() == TYPE_RAW_LIST; }
is_raw_map()158 bool is_raw_map() const { return type() == TYPE_RAW_MAP; }
159
as_value()160 value_type& as_value() { check_throw(TYPE_VALUE); return _value(); }
as_value()161 const value_type& as_value() const { check_throw(TYPE_VALUE); return _value(); }
as_string()162 string_type& as_string() { check_throw(TYPE_STRING); return _string(); }
as_string()163 const string_type& as_string() const { check_throw(TYPE_STRING); return _string(); }
as_string_c()164 const string_type& as_string_c() const { check_throw(TYPE_STRING); return _string(); }
as_list()165 list_type& as_list() { check_throw(TYPE_LIST); return _list(); }
as_list()166 const list_type& as_list() const { check_throw(TYPE_LIST); return _list(); }
as_map()167 map_type& as_map() { check_throw(TYPE_MAP); return _map(); }
as_map()168 const map_type& as_map() const { check_throw(TYPE_MAP); return _map(); }
as_dict_key()169 string_type& as_dict_key() { check_throw(TYPE_DICT_KEY); return _dict_key().first; }
as_dict_key()170 const string_type& as_dict_key() const { check_throw(TYPE_DICT_KEY); return _dict_key().first; }
as_dict_obj()171 Object& as_dict_obj() { check_throw(TYPE_DICT_KEY); return *_dict_key().second; }
as_dict_obj()172 const Object& as_dict_obj() const { check_throw(TYPE_DICT_KEY); return *_dict_key().second; }
as_raw_bencode()173 raw_bencode& as_raw_bencode() { check_throw(TYPE_RAW_BENCODE); return _raw_bencode(); }
as_raw_bencode()174 const raw_bencode& as_raw_bencode() const { check_throw(TYPE_RAW_BENCODE); return _raw_bencode(); }
as_raw_string()175 raw_string& as_raw_string() { check_throw(TYPE_RAW_STRING); return _raw_string(); }
as_raw_string()176 const raw_string& as_raw_string() const { check_throw(TYPE_RAW_STRING); return _raw_string(); }
as_raw_list()177 raw_list& as_raw_list() { check_throw(TYPE_RAW_LIST); return _raw_list(); }
as_raw_list()178 const raw_list& as_raw_list() const { check_throw(TYPE_RAW_LIST); return _raw_list(); }
as_raw_map()179 raw_map& as_raw_map() { check_throw(TYPE_RAW_MAP); return _raw_map(); }
as_raw_map()180 const raw_map& as_raw_map() const { check_throw(TYPE_RAW_MAP); return _raw_map(); }
181
has_key(const key_type & k)182 bool has_key(const key_type& k) const { check_throw(TYPE_MAP); return _map().find(k) != _map().end(); }
has_key_value(const key_type & k)183 bool has_key_value(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_VALUE); }
has_key_string(const key_type & k)184 bool has_key_string(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_STRING); }
has_key_list(const key_type & k)185 bool has_key_list(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_LIST); }
has_key_map(const key_type & k)186 bool has_key_map(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_MAP); }
has_key_raw_bencode(const key_type & k)187 bool has_key_raw_bencode(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_RAW_BENCODE); }
has_key_raw_string(const key_type & k)188 bool has_key_raw_string(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_RAW_STRING); }
has_key_raw_list(const key_type & k)189 bool has_key_raw_list(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_RAW_LIST); }
has_key_raw_map(const key_type & k)190 bool has_key_raw_map(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_RAW_MAP); }
191
192 // Should have an interface for that returns pointer or something,
193 // so we don't need to search twice.
194
195 // Make these inline...
196
197 Object& get_key(const key_type& k);
198 const Object& get_key(const key_type& k) const;
199 Object& get_key(const char* k);
200 const Object& get_key(const char* k) const;
201
get_key_value(const T & k)202 template <typename T> value_type& get_key_value(const T& k) { return get_key(k).as_value(); }
get_key_value(const T & k)203 template <typename T> const value_type& get_key_value(const T& k) const { return get_key(k).as_value(); }
get_key_string(const T & k)204 template <typename T> string_type& get_key_string(const T& k) { return get_key(k).as_string(); }
get_key_string(const T & k)205 template <typename T> const string_type& get_key_string(const T& k) const { return get_key(k).as_string(); }
get_key_list(const T & k)206 template <typename T> list_type& get_key_list(const T& k) { return get_key(k).as_list(); }
get_key_list(const T & k)207 template <typename T> const list_type& get_key_list(const T& k) const { return get_key(k).as_list(); }
get_key_map(const T & k)208 template <typename T> map_type& get_key_map(const T& k) { return get_key(k).as_map(); }
get_key_map(const T & k)209 template <typename T> const map_type& get_key_map(const T& k) const { return get_key(k).as_map(); }
210
insert_key(const key_type & k,const Object & b)211 Object& insert_key(const key_type& k, const Object& b) { check_throw(TYPE_MAP); return _map()[k] = b; }
insert_key_move(const key_type & k,Object & b)212 Object& insert_key_move(const key_type& k, Object& b) { check_throw(TYPE_MAP); return _map()[k].move(b); }
213
214 // 'insert_preserve_*' inserts the object 'b' if the key 'k' does
215 // not exist, else it returns the old entry. The type specific
216 // versions also require the old entry to be of the same type.
217 //
218 // Consider making insert_preserve_* return std::pair<Foo*,bool> or
219 // something similar.
insert_preserve_any(const key_type & k,const Object & b)220 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)); }
221 map_insert_type insert_preserve_type(const key_type& k, Object& b);
insert_preserve_copy(const key_type & k,Object b)222 map_insert_type insert_preserve_copy(const key_type& k, Object b) { return insert_preserve_type(k, b); }
223
erase_key(const key_type & k)224 void erase_key(const key_type& k) { check_throw(TYPE_MAP); _map().erase(k); }
225
insert_front(const Object & b)226 Object& insert_front(const Object& b) { check_throw(TYPE_LIST); return *_list().insert(_list().begin(), b); }
insert_back(const Object & b)227 Object& insert_back(const Object& b) { check_throw(TYPE_LIST); return *_list().insert(_list().end(), b); }
228
229 // Copy and merge operations:
230 Object& move(Object& b);
231 Object& swap(Object& b);
232 Object& swap_same_type(Object& b);
233
234 // Only map entries are merged.
235 Object& merge_move(Object& object, uint32_t maxDepth = ~uint32_t());
236 Object& merge_copy(const Object& object,
237 uint32_t skip_mask = flag_static_data,
238 uint32_t maxDepth = ~uint32_t());
239
240 Object& operator = (const Object& b);
241
242 // Internal:
243 void swap_same_type(Object& left, Object& right);
244
245 private:
check(map_type::const_iterator itr,type_type t)246 inline bool check(map_type::const_iterator itr, type_type t) const { return itr != _map().end() && itr->second.type() == t; }
check_throw(type_type t)247 inline void check_throw(type_type t) const { if (t != type()) throw bencode_error("Wrong object type."); }
248
249 uint32_t m_flags;
250
251 #ifndef HAVE_STDCXX_0X
_value()252 value_type& _value() { return t_value; }
_value()253 const value_type& _value() const { return t_value; }
_string()254 string_type& _string() { return t_string; }
_string()255 const string_type& _string() const { return t_string; }
_list()256 list_type& _list() { return t_list; }
_list()257 const list_type& _list() const { return t_list; }
_map()258 map_type& _map() { return *t_map; }
_map()259 const map_type& _map() const { return *t_map; }
_map_ptr()260 map_ptr_type& _map_ptr() { return t_map; }
_map_ptr()261 const map_ptr_type& _map_ptr() const { return t_map; }
_dict_key()262 dict_key_type& _dict_key() { return t_dict_key; }
_dict_key()263 const dict_key_type& _dict_key() const { return t_dict_key; }
_raw_object()264 raw_object& _raw_object() { return t_raw_object; }
_raw_object()265 const raw_object& _raw_object() const { return t_raw_object; }
_raw_bencode()266 raw_bencode& _raw_bencode() { return t_raw_bencode; }
_raw_bencode()267 const raw_bencode& _raw_bencode() const { return t_raw_bencode; }
_raw_string()268 raw_string& _raw_string() { return t_raw_string; }
_raw_string()269 const raw_string& _raw_string() const { return t_raw_string; }
_raw_list()270 raw_list& _raw_list() { return t_raw_list; }
_raw_list()271 const raw_list& _raw_list() const { return t_raw_list; }
_raw_map()272 raw_map& _raw_map() { return t_raw_map; }
_raw_map()273 const raw_map& _raw_map() const { return t_raw_map; }
274
275 union pod_types {
276 value_type t_value;
277 raw_object t_raw_object;
278 raw_bencode t_raw_bencode;
279 raw_string t_raw_string;
280 raw_list t_raw_list;
281 raw_map t_raw_map;
282 };
283
284 union {
285 pod_types t_pod;
286
287 value_type t_value;
288 string_type t_string;
289 list_type t_list;
290 map_type* t_map;
291 dict_key_type t_dict_key;
292 raw_object t_raw_object;
293 raw_bencode t_raw_bencode;
294 raw_string t_raw_string;
295 raw_list t_raw_list;
296 raw_map t_raw_map;
297 };
298
299 #else
300 // #error "WTF we're testing C++11 now."
301
_value()302 value_type& _value() { return reinterpret_cast<value_type&>(t_pod); }
_value()303 const value_type& _value() const { return reinterpret_cast<const value_type&>(t_pod); }
_string()304 string_type& _string() { return reinterpret_cast<string_type&>(t_string); }
_string()305 const string_type& _string() const { return reinterpret_cast<const string_type&>(t_string); }
_list()306 list_type& _list() { return reinterpret_cast<list_type&>(t_list); }
_list()307 const list_type& _list() const { return reinterpret_cast<const list_type&>(t_list); }
_map()308 map_type& _map() { return *reinterpret_cast<map_ptr_type&>(t_pod); }
_map()309 const map_type& _map() const { return *reinterpret_cast<const map_ptr_type&>(t_pod); }
_map_ptr()310 map_ptr_type& _map_ptr() { return reinterpret_cast<map_ptr_type&>(t_pod); }
_map_ptr()311 const map_ptr_type& _map_ptr() const { return reinterpret_cast<const map_ptr_type&>(t_pod); }
_dict_key()312 dict_key_type& _dict_key() { return reinterpret_cast<dict_key_type&>(t_pod); }
_dict_key()313 const dict_key_type& _dict_key() const { return reinterpret_cast<const dict_key_type&>(t_pod); }
_raw_object()314 raw_object& _raw_object() { return reinterpret_cast<raw_object&>(t_pod); }
_raw_object()315 const raw_object& _raw_object() const { return reinterpret_cast<const raw_object&>(t_pod); }
_raw_bencode()316 raw_bencode& _raw_bencode() { return reinterpret_cast<raw_bencode&>(t_pod); }
_raw_bencode()317 const raw_bencode& _raw_bencode() const { return reinterpret_cast<const raw_bencode&>(t_pod); }
_raw_string()318 raw_string& _raw_string() { return reinterpret_cast<raw_string&>(t_pod); }
_raw_string()319 const raw_string& _raw_string() const { return reinterpret_cast<const raw_string&>(t_pod); }
_raw_list()320 raw_list& _raw_list() { return reinterpret_cast<raw_list&>(t_pod); }
_raw_list()321 const raw_list& _raw_list() const { return reinterpret_cast<const raw_list&>(t_pod); }
_raw_map()322 raw_map& _raw_map() { return reinterpret_cast<raw_map&>(t_pod); }
_raw_map()323 const raw_map& _raw_map() const { return reinterpret_cast<const raw_map&>(t_pod); }
324
325 union pod_types {
326 value_type t_value;
327 map_type* t_map;
328 char t_raw_object[sizeof(raw_object)];
329 };
330
331 union {
332 pod_types t_pod;
333 char t_string[sizeof(string_type)];
334 char t_list[sizeof(list_type)];
335 char t_dict_key[sizeof(dict_key_type)];
336 };
337 #endif
338 };
339
340 inline
Object(const Object & b)341 Object::Object(const Object& b) {
342 m_flags = b.m_flags & (mask_type | mask_public);
343
344 switch (type()) {
345 case TYPE_NONE:
346 case TYPE_RAW_BENCODE:
347 case TYPE_RAW_STRING:
348 case TYPE_RAW_LIST:
349 case TYPE_RAW_MAP:
350 case TYPE_VALUE: t_pod = b.t_pod; break;
351 case TYPE_STRING: new (&_string()) string_type(b._string()); break;
352 case TYPE_LIST: new (&_list()) list_type(b._list()); break;
353 case TYPE_MAP: _map_ptr() = new map_type(b._map()); break;
354 case TYPE_DICT_KEY:
355 new (&_dict_key().first) string_type(b._dict_key().first);
356 _dict_key().second = new Object(*b._dict_key().second); break;
357 }
358 }
359
360 inline Object
create_empty(type_type t)361 Object::create_empty(type_type t) {
362 switch (t) {
363 case TYPE_RAW_BENCODE: return create_raw_bencode();
364 case TYPE_RAW_STRING: return create_raw_string();
365 case TYPE_RAW_LIST: return create_raw_list();
366 case TYPE_RAW_MAP: return create_raw_map();
367 case TYPE_VALUE: return create_value();
368 case TYPE_STRING: return create_string();
369 case TYPE_LIST: return create_list();
370 case TYPE_MAP: return create_map();
371 case TYPE_DICT_KEY: return create_dict_key();
372 case TYPE_NONE:
373 default: return torrent::Object();
374 }
375 }
376
377 inline Object
object_create_raw_bencode_c_str(const char str[])378 object_create_raw_bencode_c_str(const char str[]) {
379 return Object::create_raw_bencode(raw_bencode(str, strlen(str)));
380 }
381
382 // TODO: These do not preserve the flag...
383
384 Object object_create_normal(const raw_bencode& obj) LIBTORRENT_EXPORT;
385 Object object_create_normal(const raw_list& obj) LIBTORRENT_EXPORT;
386 Object object_create_normal(const raw_map& obj) LIBTORRENT_EXPORT;
object_create_normal(const raw_string & obj)387 inline Object object_create_normal(const raw_string& obj) { return torrent::Object(obj.as_string()); }
388
389 inline Object
create_dict_key()390 Object::create_dict_key() {
391 Object tmp;
392 tmp.m_flags = TYPE_DICT_KEY;
393 new (&tmp._dict_key()) dict_key_type();
394 tmp._dict_key().second = new Object();
395 return tmp;
396 }
397
398 inline Object
create_raw_bencode(raw_bencode obj)399 Object::create_raw_bencode(raw_bencode obj) {
400 Object tmp; tmp.m_flags = TYPE_RAW_BENCODE; new (&tmp._raw_bencode()) raw_bencode(obj); return tmp;
401 }
402
403 inline Object
create_raw_string(raw_string obj)404 Object::create_raw_string(raw_string obj) {
405 Object tmp; tmp.m_flags = TYPE_RAW_STRING; new (&tmp._raw_string()) raw_string(obj); return tmp;
406 }
407
408 inline Object
create_raw_list(raw_list obj)409 Object::create_raw_list(raw_list obj) {
410 Object tmp; tmp.m_flags = TYPE_RAW_LIST; new (&tmp._raw_list()) raw_list(obj); return tmp;
411 }
412
413 inline Object
create_raw_map(raw_map obj)414 Object::create_raw_map(raw_map obj) {
415 Object tmp; tmp.m_flags = TYPE_RAW_MAP; new (&tmp._raw_map()) raw_map(obj); return tmp;
416 }
417
418 inline Object
object_create_normal(const Object & obj)419 object_create_normal(const Object& obj) {
420 switch (obj.type()) {
421 case Object::TYPE_RAW_BENCODE: return object_create_normal(obj.as_raw_bencode());
422 case Object::TYPE_RAW_STRING: return object_create_normal(obj.as_raw_string());
423 case Object::TYPE_RAW_LIST: return object_create_normal(obj.as_raw_list());
424 case Object::TYPE_RAW_MAP: return object_create_normal(obj.as_raw_map());
425 default: return obj;
426 }
427 }
428
429 inline std::string
object_create_string(const torrent::Object & obj)430 object_create_string(const torrent::Object& obj) {
431 switch (obj.type()) {
432 case Object::TYPE_RAW_BENCODE: return obj.as_raw_bencode().as_raw_string().as_string();
433 case Object::TYPE_RAW_STRING: return obj.as_raw_string().as_string();
434 default: return obj.as_string();
435 }
436 }
437
438 template <typename ForwardIterator>
439 inline Object
create_list_range(ForwardIterator first,ForwardIterator last)440 Object::create_list_range(ForwardIterator first, ForwardIterator last) {
441 Object tmp; tmp.m_flags = TYPE_LIST; new (&tmp._list()) list_type(first, last); return tmp;
442 }
443
444 inline void
clear()445 Object::clear() {
446 switch (type()) {
447 case TYPE_STRING: _string().~string_type(); break;
448 case TYPE_LIST: _list().~list_type(); break;
449 case TYPE_MAP: delete _map_ptr(); break;
450 case TYPE_DICT_KEY: delete _dict_key().second; _dict_key().~dict_key_type(); break;
451 default: break;
452 }
453
454 // Only clear type?
455 m_flags = TYPE_NONE;
456 }
457
458 inline void
swap_same_type(Object & left,Object & right)459 Object::swap_same_type(Object& left, Object& right) {
460 std::swap(left.m_flags, right.m_flags);
461
462 switch (left.type()) {
463 case Object::TYPE_STRING: left._string().swap(right._string()); break;
464 case Object::TYPE_LIST: left._list().swap(right._list()); break;
465 case Object::TYPE_DICT_KEY:
466 std::swap(left._dict_key().first, right._dict_key().first);
467 std::swap(left._dict_key().second, right._dict_key().second); break;
468 default: std::swap(left.t_pod, right.t_pod); break;
469 }
470 }
471
swap(Object & left,Object & right)472 inline void swap(Object& left, Object& right) { left.swap(right); }
473
474 inline bool
object_equal(const Object & left,const Object & right)475 object_equal(const Object& left, const Object& right) {
476 if (left.type() != right.type())
477 return false;
478
479 switch (left.type()) {
480 case Object::TYPE_NONE: return true;
481 case Object::TYPE_VALUE: return left.as_value() == right.as_value();
482 case Object::TYPE_STRING: return left.as_string() == right.as_string();
483 default: return false;
484 }
485 }
486
487 }
488
489 #endif
490