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

« back to all changes in this revision

Viewing changes to src/torrent/object.cc

  • 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
#include "config.h"
 
38
 
 
39
#include <algorithm>
 
40
#include <cstring>
 
41
#include <rak/functional.h>
 
42
 
 
43
#include "object.h"
 
44
#include "object_stream.h"
 
45
 
 
46
namespace torrent {
 
47
 
 
48
Object&
 
49
Object::get_key(const std::string& k) {
 
50
  check_throw(TYPE_MAP);
 
51
  map_type::iterator itr = _map().find(k);
 
52
 
 
53
  if (itr == _map().end())
 
54
    throw bencode_error("Object operator [" + k + "] could not find element");
 
55
 
 
56
  return itr->second;
 
57
}
 
58
 
 
59
 
 
60
const Object&
 
61
Object::get_key(const std::string& k) const {
 
62
  check_throw(TYPE_MAP);
 
63
  map_type::const_iterator itr = _map().find(k);
 
64
 
 
65
  if (itr == _map().end())
 
66
    throw bencode_error("Object operator [" + k + "] could not find element");
 
67
 
 
68
  return itr->second;
 
69
}
 
70
 
 
71
Object&
 
72
Object::get_key(const char* k) {
 
73
  check_throw(TYPE_MAP);
 
74
  map_type::iterator itr = _map().find(std::string(k));
 
75
 
 
76
  if (itr == _map().end())
 
77
    throw bencode_error("Object operator [" + std::string(k) + "] could not find element");
 
78
 
 
79
  return itr->second;
 
80
}
 
81
 
 
82
const Object&
 
83
Object::get_key(const char* k) const {
 
84
  check_throw(TYPE_MAP);
 
85
  map_type::const_iterator itr = _map().find(std::string(k));
 
86
 
 
87
  if (itr == _map().end())
 
88
    throw bencode_error("Object operator [" + std::string(k) + "] could not find element");
 
89
 
 
90
  return itr->second;
 
91
}
 
92
 
 
93
Object::map_insert_type
 
94
Object::insert_preserve_type(const key_type& k, Object& b) {
 
95
  check_throw(TYPE_MAP);
 
96
  map_insert_type result = _map().insert(map_type::value_type(k, b));
 
97
 
 
98
  if (!result.second && result.first->second.type() != b.type()) {
 
99
    result.first->second.move(b);
 
100
    result.second = true;
 
101
  }
 
102
 
 
103
  return result;
 
104
}
 
105
 
 
106
Object&
 
107
Object::move(Object& src) {
 
108
  if (this == &src)
 
109
    return *this;
 
110
 
 
111
  *this = create_empty(src.type());
 
112
  swap_same_type(*this, src);
 
113
 
 
114
  return *this;
 
115
}
 
116
 
 
117
Object&
 
118
Object::swap(Object& src) {
 
119
  if (this == &src)
 
120
    return *this;
 
121
 
 
122
  if (type() != src.type()) {
 
123
    torrent::Object tmp = create_empty(src.type());
 
124
    swap_same_type(tmp, src);
 
125
    src = create_empty(this->type());
 
126
    swap_same_type(src, *this);
 
127
    *this = create_empty(tmp.type());
 
128
    swap_same_type(*this, tmp);
 
129
 
 
130
  } else {
 
131
    swap_same_type(*this, src);
 
132
  }
 
133
 
 
134
  return *this;
 
135
}
 
136
 
 
137
Object&
 
138
Object::merge_copy(const Object& object, uint32_t skip_mask, uint32_t maxDepth) {
 
139
  if (maxDepth == 0 || m_flags & skip_mask)
 
140
    return (*this = object);
 
141
 
 
142
  if (object.is_map()) {
 
143
    if (!is_map())
 
144
      *this = create_map();
 
145
 
 
146
    map_type& dest = as_map();
 
147
    map_type::iterator destItr = dest.begin();
 
148
 
 
149
    map_type::const_iterator srcItr = object.as_map().begin();
 
150
    map_type::const_iterator srcLast = object.as_map().end();
 
151
 
 
152
    while (srcItr != srcLast) {
 
153
      destItr = std::find_if(destItr, dest.end(), rak::less_equal(srcItr->first, rak::mem_ref(&map_type::value_type::first)));
 
154
 
 
155
      if (srcItr->first < destItr->first)
 
156
        // destItr remains valid and pointing to the next possible
 
157
        // position.
 
158
        dest.insert(destItr, *srcItr);
 
159
      else
 
160
        destItr->second.merge_copy(srcItr->second, maxDepth - 1);
 
161
 
 
162
      srcItr++;
 
163
    }
 
164
 
 
165
//   } else if (object.is_list()) {
 
166
//     if (!is_list())
 
167
//       *this = create_list();
 
168
 
 
169
//     list_type& dest = as_list();
 
170
//     list_type::iterator destItr = dest.begin();
 
171
 
 
172
//     list_type::const_iterator srcItr = object.as_list().begin();
 
173
//     list_type::const_iterator srcLast = object.as_list().end();
 
174
    
 
175
//     while (srcItr != srcLast) {
 
176
//       if (destItr == dest.end())
 
177
//         destItr = dest.insert(destItr, *srcItr);
 
178
//       else
 
179
//         destItr->merge_copy(*srcItr, maxDepth - 1);
 
180
 
 
181
//       destItr++;
 
182
//     }
 
183
 
 
184
  } else {
 
185
    *this = object;
 
186
  }
 
187
 
 
188
  return *this;
 
189
}
 
190
 
 
191
Object&
 
192
Object::operator = (const Object& src) {
 
193
  if (&src == this)
 
194
    return *this;
 
195
 
 
196
  clear();
 
197
 
 
198
  // Need some more magic here?
 
199
  m_flags = src.m_flags & (mask_type | mask_public);
 
200
 
 
201
  switch (type()) {
 
202
  case TYPE_STRING: new (&_string()) string_type(src._string()); break;
 
203
  case TYPE_LIST:   new (&_list()) list_type(src._list()); break;
 
204
  case TYPE_MAP:    _map_ptr() = new map_type(src._map()); break;
 
205
  default: t_pod = src.t_pod; break;
 
206
  }
 
207
 
 
208
  return *this;
 
209
}
 
210
 
 
211
Object object_create_normal(const raw_bencode& obj) {
 
212
  torrent::Object result;
 
213
 
 
214
  if (object_read_bencode_c(obj.begin(), obj.end(), &result, 128) != obj.end())
 
215
    throw bencode_error("Invalid bencode data.");
 
216
 
 
217
  return result;
 
218
}
 
219
 
 
220
Object object_create_normal(const raw_list& obj) {
 
221
  torrent::Object result = Object::create_list();
 
222
 
 
223
  raw_list::iterator first = obj.begin();
 
224
  raw_list::iterator last = obj.end();
 
225
 
 
226
  while (first != last) {
 
227
    Object::list_iterator new_entry = result.as_list().insert(result.as_list().end(), Object());
 
228
 
 
229
    first = object_read_bencode_c(first, last, &*new_entry, 128);
 
230
 
 
231
    // The unordered flag is inherited also from list elements who
 
232
    // have been marked as unordered, though e.g. unordered strings
 
233
    // in the list itself does not cause this flag to be set.
 
234
    if (new_entry->flags() & Object::flag_unordered)
 
235
      result.set_internal_flags(Object::flag_unordered);
 
236
  }
 
237
 
 
238
  return result;
 
239
}
 
240
 
 
241
Object object_create_normal(const raw_map& obj) {
 
242
  torrent::Object result = Object::create_map();
 
243
 
 
244
  raw_list::iterator first = obj.begin();
 
245
  raw_list::iterator last = obj.end();
 
246
 
 
247
  Object::string_type prev;
 
248
 
 
249
  while (first != last) {
 
250
    raw_string raw_str = object_read_bencode_c_string(first, last);
 
251
    first = raw_str.end();
 
252
 
 
253
    Object::string_type key_str = raw_str.as_string();
 
254
 
 
255
    // We do not set flag_unordered if the first key was zero
 
256
    // length, while multiple zero length keys will trigger the
 
257
    // unordered_flag.
 
258
    if (key_str <= prev && !result.as_map().empty())
 
259
      result.set_internal_flags(Object::flag_unordered);
 
260
 
 
261
    Object* value = &result.as_map()[key_str];
 
262
    first = object_read_bencode_c(first, last, value, 128);
 
263
 
 
264
    if (value->flags() & Object::flag_unordered)
 
265
      result.set_internal_flags(Object::flag_unordered);
 
266
 
 
267
    key_str.swap(prev);
 
268
  }
 
269
 
 
270
  return result;
 
271
}
 
272
 
 
273
 
 
274
}