file_progress fix
[libtorrent.git] / src / entry.cpp
blob59e5b061d7bd95d339f787a95a09bc082fc99f10
1 /*
3 Copyright (c) 2003, Arvid Norberg
4 All rights reserved.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the distribution.
15 * Neither the name of the author nor the names of its
16 contributors may be used to endorse or promote products derived
17 from this software without specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 POSSIBILITY OF SUCH DAMAGE.
33 #include "libtorrent/pch.hpp"
35 #include <algorithm>
36 #include <iostream>
37 #include <iomanip>
38 #include <boost/bind.hpp>
39 #include "libtorrent/entry.hpp"
40 #include "libtorrent/config.hpp"
41 #include "libtorrent/escape_string.hpp"
43 #if defined(_MSC_VER)
44 namespace std
46 using ::isprint;
48 #define for if (false) {} else for
49 #endif
51 namespace
53 template <class T>
54 void call_destructor(T* o)
56 TORRENT_ASSERT(o);
57 o->~T();
61 namespace libtorrent
63 namespace detail
65 TORRENT_EXPORT char const* integer_to_str(char* buf, int size, entry::integer_type val)
67 int sign = 0;
68 if (val < 0)
70 sign = 1;
71 val = -val;
73 buf[--size] = '\0';
74 if (val == 0) buf[--size] = '0';
75 for (; size > sign && val != 0;)
77 buf[--size] = '0' + char(val % 10);
78 val /= 10;
80 if (sign) buf[--size] = '-';
81 return buf + size;
85 entry& entry::operator[](char const* key)
87 dictionary_type::iterator i = dict().find(key);
88 if (i != dict().end()) return i->second;
89 dictionary_type::iterator ret = dict().insert(
90 dict().begin()
91 , std::make_pair(key, entry()));
92 return ret->second;
95 entry& entry::operator[](std::string const& key)
97 dictionary_type::iterator i = dict().find(key);
98 if (i != dict().end()) return i->second;
99 dictionary_type::iterator ret = dict().insert(
100 dict().begin()
101 , std::make_pair(std::string(key), entry()));
102 return ret->second;
105 entry* entry::find_key(char const* key)
107 dictionary_type::iterator i = dict().find(key);
108 if (i == dict().end()) return 0;
109 return &i->second;
112 entry const* entry::find_key(char const* key) const
114 dictionary_type::const_iterator i = dict().find(key);
115 if (i == dict().end()) return 0;
116 return &i->second;
119 entry* entry::find_key(std::string const& key)
121 dictionary_type::iterator i = dict().find(key);
122 if (i == dict().end()) return 0;
123 return &i->second;
126 entry const* entry::find_key(std::string const& key) const
128 dictionary_type::const_iterator i = dict().find(key);
129 if (i == dict().end()) return 0;
130 return &i->second;
133 #ifndef BOOST_NO_EXCEPTIONS
134 const entry& entry::operator[](char const* key) const
136 dictionary_type::const_iterator i = dict().find(key);
137 if (i == dict().end()) throw type_error(
138 (std::string("key not found: ") + key).c_str());
139 return i->second;
142 const entry& entry::operator[](std::string const& key) const
144 return (*this)[key.c_str()];
146 #endif
148 entry::entry()
149 : m_type(undefined_t)
151 #ifndef NDEBUG
152 m_type_queried = true;
153 #endif
156 entry::entry(data_type t)
157 : m_type(undefined_t)
159 construct(t);
160 #ifndef NDEBUG
161 m_type_queried = true;
162 #endif
165 entry::entry(const entry& e)
166 : m_type(undefined_t)
168 copy(e);
169 #ifndef NDEBUG
170 m_type_queried = e.m_type_queried;
171 #endif
174 entry::entry(dictionary_type const& v)
175 : m_type(undefined_t)
177 #ifndef NDEBUG
178 m_type_queried = true;
179 #endif
180 new(data) dictionary_type(v);
181 m_type = dictionary_t;
184 entry::entry(string_type const& v)
185 : m_type(undefined_t)
187 #ifndef NDEBUG
188 m_type_queried = true;
189 #endif
190 new(data) string_type(v);
191 m_type = string_t;
194 entry::entry(list_type const& v)
195 : m_type(undefined_t)
197 #ifndef NDEBUG
198 m_type_queried = true;
199 #endif
200 new(data) list_type(v);
201 m_type = list_t;
204 entry::entry(integer_type const& v)
205 : m_type(undefined_t)
207 #ifndef NDEBUG
208 m_type_queried = true;
209 #endif
210 new(data) integer_type(v);
211 m_type = int_t;
214 void entry::operator=(dictionary_type const& v)
216 destruct();
217 new(data) dictionary_type(v);
218 m_type = dictionary_t;
219 #ifndef NDEBUG
220 m_type_queried = true;
221 #endif
224 void entry::operator=(string_type const& v)
226 destruct();
227 new(data) string_type(v);
228 m_type = string_t;
229 #ifndef NDEBUG
230 m_type_queried = true;
231 #endif
234 void entry::operator=(list_type const& v)
236 destruct();
237 new(data) list_type(v);
238 m_type = list_t;
239 #ifndef NDEBUG
240 m_type_queried = true;
241 #endif
244 void entry::operator=(integer_type const& v)
246 destruct();
247 new(data) integer_type(v);
248 m_type = int_t;
249 #ifndef NDEBUG
250 m_type_queried = true;
251 #endif
254 bool entry::operator==(entry const& e) const
256 if (m_type != e.m_type) return false;
258 switch(m_type)
260 case int_t:
261 return integer() == e.integer();
262 case string_t:
263 return string() == e.string();
264 case list_t:
265 return list() == e.list();
266 case dictionary_t:
267 return dict() == e.dict();
268 default:
269 TORRENT_ASSERT(m_type == undefined_t);
270 return true;
274 void entry::construct(data_type t)
276 switch(t)
278 case int_t:
279 new(data) integer_type;
280 break;
281 case string_t:
282 new(data) string_type;
283 break;
284 case list_t:
285 new(data) list_type;
286 break;
287 case dictionary_t:
288 new (data) dictionary_type;
289 break;
290 default:
291 TORRENT_ASSERT(t == undefined_t);
293 m_type = t;
294 #ifndef NDEBUG
295 m_type_queried = true;
296 #endif
299 void entry::copy(entry const& e)
301 switch (e.type())
303 case int_t:
304 new(data) integer_type(e.integer());
305 break;
306 case string_t:
307 new(data) string_type(e.string());
308 break;
309 case list_t:
310 new(data) list_type(e.list());
311 break;
312 case dictionary_t:
313 new (data) dictionary_type(e.dict());
314 break;
315 default:
316 TORRENT_ASSERT(e.type() == undefined_t);
318 m_type = e.type();
319 #ifndef NDEBUG
320 m_type_queried = true;
321 #endif
324 void entry::destruct()
326 switch(m_type)
328 case int_t:
329 call_destructor(reinterpret_cast<integer_type*>(data));
330 break;
331 case string_t:
332 call_destructor(reinterpret_cast<string_type*>(data));
333 break;
334 case list_t:
335 call_destructor(reinterpret_cast<list_type*>(data));
336 break;
337 case dictionary_t:
338 call_destructor(reinterpret_cast<dictionary_type*>(data));
339 break;
340 default:
341 TORRENT_ASSERT(m_type == undefined_t);
342 break;
344 m_type = undefined_t;
345 #ifndef NDEBUG
346 m_type_queried = false;
347 #endif
350 void entry::swap(entry& e)
352 // not implemented
353 TORRENT_ASSERT(false);
356 void entry::print(std::ostream& os, int indent) const
358 TORRENT_ASSERT(indent >= 0);
359 for (int i = 0; i < indent; ++i) os << " ";
360 switch (m_type)
362 case int_t:
363 os << integer() << "\n";
364 break;
365 case string_t:
367 bool binary_string = false;
368 for (std::string::const_iterator i = string().begin(); i != string().end(); ++i)
370 if (!std::isprint(static_cast<unsigned char>(*i)))
372 binary_string = true;
373 break;
376 if (binary_string) os << to_hex(string()) << "\n";
377 else os << string() << "\n";
378 } break;
379 case list_t:
381 os << "list\n";
382 for (list_type::const_iterator i = list().begin(); i != list().end(); ++i)
384 i->print(os, indent+1);
386 } break;
387 case dictionary_t:
389 os << "dictionary\n";
390 for (dictionary_type::const_iterator i = dict().begin(); i != dict().end(); ++i)
392 bool binary_string = false;
393 for (std::string::const_iterator k = i->first.begin(); k != i->first.end(); ++k)
395 if (!std::isprint(static_cast<unsigned char>(*k)))
397 binary_string = true;
398 break;
401 for (int j = 0; j < indent+1; ++j) os << " ";
402 os << "[";
403 if (binary_string) os << to_hex(i->first);
404 else os << i->first;
405 os << "]";
407 if (i->second.type() != entry::string_t
408 && i->second.type() != entry::int_t)
409 os << "\n";
410 else os << " ";
411 i->second.print(os, indent+2);
413 } break;
414 default:
415 os << "<uninitialized>\n";