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
41
#include <rak/functional.h>
44
#include "object_stream.h"
49
Object::get_key(const std::string& k) {
50
check_throw(TYPE_MAP);
51
map_type::iterator itr = _map().find(k);
53
if (itr == _map().end())
54
throw bencode_error("Object operator [" + k + "] could not find element");
61
Object::get_key(const std::string& k) const {
62
check_throw(TYPE_MAP);
63
map_type::const_iterator itr = _map().find(k);
65
if (itr == _map().end())
66
throw bencode_error("Object operator [" + k + "] could not find element");
72
Object::get_key(const char* k) {
73
check_throw(TYPE_MAP);
74
map_type::iterator itr = _map().find(std::string(k));
76
if (itr == _map().end())
77
throw bencode_error("Object operator [" + std::string(k) + "] could not find element");
83
Object::get_key(const char* k) const {
84
check_throw(TYPE_MAP);
85
map_type::const_iterator itr = _map().find(std::string(k));
87
if (itr == _map().end())
88
throw bencode_error("Object operator [" + std::string(k) + "] could not find element");
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));
98
if (!result.second && result.first->second.type() != b.type()) {
99
result.first->second.move(b);
100
result.second = true;
107
Object::move(Object& src) {
111
*this = create_empty(src.type());
112
swap_same_type(*this, src);
118
Object::swap(Object& src) {
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);
131
swap_same_type(*this, src);
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);
142
if (object.is_map()) {
144
*this = create_map();
146
map_type& dest = as_map();
147
map_type::iterator destItr = dest.begin();
149
map_type::const_iterator srcItr = object.as_map().begin();
150
map_type::const_iterator srcLast = object.as_map().end();
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)));
155
if (srcItr->first < destItr->first)
156
// destItr remains valid and pointing to the next possible
158
dest.insert(destItr, *srcItr);
160
destItr->second.merge_copy(srcItr->second, maxDepth - 1);
165
// } else if (object.is_list()) {
167
// *this = create_list();
169
// list_type& dest = as_list();
170
// list_type::iterator destItr = dest.begin();
172
// list_type::const_iterator srcItr = object.as_list().begin();
173
// list_type::const_iterator srcLast = object.as_list().end();
175
// while (srcItr != srcLast) {
176
// if (destItr == dest.end())
177
// destItr = dest.insert(destItr, *srcItr);
179
// destItr->merge_copy(*srcItr, maxDepth - 1);
192
Object::operator = (const Object& src) {
198
// Need some more magic here?
199
m_flags = src.m_flags & (mask_type | mask_public);
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;
211
Object object_create_normal(const raw_bencode& obj) {
212
torrent::Object result;
214
if (object_read_bencode_c(obj.begin(), obj.end(), &result, 128) != obj.end())
215
throw bencode_error("Invalid bencode data.");
220
Object object_create_normal(const raw_list& obj) {
221
torrent::Object result = Object::create_list();
223
raw_list::iterator first = obj.begin();
224
raw_list::iterator last = obj.end();
226
while (first != last) {
227
Object::list_iterator new_entry = result.as_list().insert(result.as_list().end(), Object());
229
first = object_read_bencode_c(first, last, &*new_entry, 128);
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);
241
Object object_create_normal(const raw_map& obj) {
242
torrent::Object result = Object::create_map();
244
raw_list::iterator first = obj.begin();
245
raw_list::iterator last = obj.end();
247
Object::string_type prev;
249
while (first != last) {
250
raw_string raw_str = object_read_bencode_c_string(first, last);
251
first = raw_str.end();
253
Object::string_type key_str = raw_str.as_string();
255
// We do not set flag_unordered if the first key was zero
256
// length, while multiple zero length keys will trigger the
258
if (key_str <= prev && !result.as_map().empty())
259
result.set_internal_flags(Object::flag_unordered);
261
Object* value = &result.as_map()[key_str];
262
first = object_read_bencode_c(first, last, value, 128);
264
if (value->flags() & Object::flag_unordered)
265
result.set_internal_flags(Object::flag_unordered);