~ubuntu-branches/ubuntu/wily/libtorrent/wily-proposed

« back to all changes in this revision

Viewing changes to src/torrent/object.h

  • Committer: Bazaar Package Importer
  • Author(s): Rogério Brito
  • Date: 2011-03-20 01:06:18 UTC
  • mfrom: (1.1.13 upstream) (4.1.9 sid)
  • Revision ID: james.westby@ubuntu.com-20110320010618-g3wyylccqzqko73c
Tags: 0.12.7-5
* Use Steinar's "real" patch for IPv6. Addresses #490277, #618275,
  and Closes: #617791.
* Adapt libtorrent-0.12.6-ipv6-07.patch. It FTBFS otherwise.
* Add proper attibution to the IPv6 patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// libTorrent - BitTorrent library
 
2
// Copyright (C) 2005-2007, 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
 
 
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;
 
62
 
 
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;
 
67
 
 
68
  typedef std::pair<map_iterator, bool>     map_insert_type;
 
69
 
 
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;
 
76
 
 
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.
 
80
 
 
81
  enum type_type {
 
82
    TYPE_NONE,
 
83
    TYPE_RAW_BENCODE,
 
84
    TYPE_RAW_STRING,
 
85
    TYPE_RAW_LIST,
 
86
    TYPE_RAW_MAP,
 
87
    TYPE_VALUE,
 
88
    TYPE_STRING,
 
89
    TYPE_LIST,
 
90
    TYPE_MAP
 
91
  };
 
92
 
 
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);
 
102
 
 
103
  ~Object() { clear(); }
 
104
 
 
105
  // TODO: Move this out of the class namespace, call them
 
106
  // make_object_. 
 
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; }
 
112
 
 
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;
 
115
  }
 
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;
 
118
  }
 
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;
 
121
  }
 
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;
 
124
  }
 
125
 
 
126
  template <typename ForwardIterator>
 
127
  static Object       create_list_range(ForwardIterator first, ForwardIterator last);
 
128
 
 
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.
 
132
  void                clear();
 
133
 
 
134
  type_type           type() const                            { return (type_type)(m_flags & mask_type); }
 
135
  uint32_t            flags() const                           { return m_flags & mask_flags; }
 
136
 
 
137
  void                set_flags(uint32_t f)                   { m_flags |= f & mask_public; }
 
138
  void                unset_flags(uint32_t f)                 { m_flags &= ~(f & mask_public); }
 
139
 
 
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)); }
 
142
 
 
143
  // Add functions for setting/clearing the public flags.
 
144
 
 
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; }
 
155
 
 
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(); }
 
172
 
 
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); }
 
182
 
 
183
  // Should have an interface for that returns pointer or something,
 
184
  // so we don't need to search twice.
 
185
 
 
186
  // Make these inline...
 
187
 
 
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;
 
192
 
 
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(); }
 
201
 
 
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); }
 
204
 
 
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.
 
208
  //
 
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); }
 
214
 
 
215
  void                erase_key(const key_type& k)                   { check_throw(TYPE_MAP); _map().erase(k); }
 
216
 
 
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); }
 
219
 
 
220
  // Copy and merge operations:
 
221
  Object&             move(Object& b);
 
222
  Object&             swap(Object& b);
 
223
  Object&             swap_same_type(Object& b);
 
224
 
 
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());
 
230
 
 
231
  Object&             operator = (const Object& b);
 
232
 
 
233
  // Internal:
 
234
  void                swap_same_type(Object& left, Object& right);
 
235
 
 
236
 private:
 
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."); }
 
239
 
 
240
  uint32_t            m_flags;
 
241
 
 
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); }
 
262
 
 
263
  union pod_types {
 
264
    value_type t_value;
 
265
    map_type*  t_map;
 
266
    char       t_raw_obect[sizeof(raw_object)];
 
267
  };
 
268
 
 
269
  union {
 
270
    pod_types t_pod;
 
271
    char    t_string[sizeof(string_type)];
 
272
    char    t_list[sizeof(list_type)];
 
273
  };
 
274
};
 
275
 
 
276
inline
 
277
Object::Object(const Object& b) {
 
278
  m_flags = b.m_flags & (mask_type | mask_public);
 
279
 
 
280
  switch (type()) {
 
281
  case TYPE_NONE:
 
282
  case TYPE_RAW_BENCODE:
 
283
  case TYPE_RAW_STRING: 
 
284
  case TYPE_RAW_LIST: 
 
285
  case TYPE_RAW_MAP:
 
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;
 
290
  }
 
291
}
 
292
 
 
293
inline Object
 
294
Object::create_empty(type_type t) {
 
295
  switch (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();
 
304
  case TYPE_NONE:
 
305
  default: return torrent::Object();
 
306
  }
 
307
}
 
308
 
 
309
inline Object
 
310
object_create_raw_bencode_c_str(const char str[]) {
 
311
  return Object::create_raw_bencode(raw_bencode(str, strlen(str)));
 
312
}
 
313
 
 
314
// TODO: These do not preserve the flag...
 
315
 
 
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()); }
 
320
 
 
321
inline Object
 
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());
 
328
  default: return obj;
 
329
  }
 
330
}
 
331
 
 
332
inline std::string
 
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();
 
338
  }
 
339
}
 
340
 
 
341
template <typename ForwardIterator>
 
342
inline Object
 
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;
 
345
}
 
346
 
 
347
inline void
 
348
Object::clear() {
 
349
  switch (type()) {
 
350
  case TYPE_STRING: _string().~string_type(); break;
 
351
  case TYPE_LIST:   _list().~list_type(); break;
 
352
  case TYPE_MAP:    delete _map_ptr(); break;
 
353
  default: break;
 
354
  }
 
355
 
 
356
  // Only clear type?
 
357
  m_flags = TYPE_NONE;
 
358
}
 
359
 
 
360
inline void
 
361
Object::swap_same_type(Object& left, Object& right) {
 
362
  std::swap(left.m_flags, right.m_flags);
 
363
 
 
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;
 
368
  }
 
369
}
 
370
 
 
371
inline void swap(Object& left, Object& right) { left.swap(right); }
 
372
 
 
373
inline bool
 
374
object_equal(const Object& left, const Object& right) {
 
375
  if (left.type() != right.type())
 
376
    return false;
 
377
 
 
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;
 
383
  }
 
384
}
 
385
 
 
386
}
 
387
 
 
388
#endif