3 Copyright (c) 2003, Arvid Norberg
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
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"
38 #include <boost/bind.hpp>
39 #include "libtorrent/entry.hpp"
40 #include "libtorrent/config.hpp"
41 #include "libtorrent/escape_string.hpp"
48 #define for if (false) {} else for
54 void call_destructor(T
* o
)
65 TORRENT_EXPORT
char const* integer_to_str(char* buf
, int size
, entry::integer_type val
)
74 if (val
== 0) buf
[--size
] = '0';
75 for (; size
> sign
&& val
!= 0;)
77 buf
[--size
] = '0' + char(val
% 10);
80 if (sign
) 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(
91 , std::make_pair(key
, entry()));
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(
101 , std::make_pair(std::string(key
), entry()));
105 entry
* entry::find_key(char const* key
)
107 dictionary_type::iterator i
= dict().find(key
);
108 if (i
== dict().end()) return 0;
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;
119 entry
* entry::find_key(std::string
const& key
)
121 dictionary_type::iterator i
= dict().find(key
);
122 if (i
== dict().end()) return 0;
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;
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());
142 const entry
& entry::operator[](std::string
const& key
) const
144 return (*this)[key
.c_str()];
149 : m_type(undefined_t
)
152 m_type_queried
= true;
156 entry::entry(data_type t
)
157 : m_type(undefined_t
)
161 m_type_queried
= true;
165 entry::entry(const entry
& e
)
166 : m_type(undefined_t
)
170 m_type_queried
= e
.m_type_queried
;
174 entry::entry(dictionary_type
const& v
)
175 : m_type(undefined_t
)
178 m_type_queried
= true;
180 new(data
) dictionary_type(v
);
181 m_type
= dictionary_t
;
184 entry::entry(string_type
const& v
)
185 : m_type(undefined_t
)
188 m_type_queried
= true;
190 new(data
) string_type(v
);
194 entry::entry(list_type
const& v
)
195 : m_type(undefined_t
)
198 m_type_queried
= true;
200 new(data
) list_type(v
);
204 entry::entry(integer_type
const& v
)
205 : m_type(undefined_t
)
208 m_type_queried
= true;
210 new(data
) integer_type(v
);
214 void entry::operator=(dictionary_type
const& v
)
217 new(data
) dictionary_type(v
);
218 m_type
= dictionary_t
;
220 m_type_queried
= true;
224 void entry::operator=(string_type
const& v
)
227 new(data
) string_type(v
);
230 m_type_queried
= true;
234 void entry::operator=(list_type
const& v
)
237 new(data
) list_type(v
);
240 m_type_queried
= true;
244 void entry::operator=(integer_type
const& v
)
247 new(data
) integer_type(v
);
250 m_type_queried
= true;
254 bool entry::operator==(entry
const& e
) const
256 if (m_type
!= e
.m_type
) return false;
261 return integer() == e
.integer();
263 return string() == e
.string();
265 return list() == e
.list();
267 return dict() == e
.dict();
269 TORRENT_ASSERT(m_type
== undefined_t
);
274 void entry::construct(data_type t
)
279 new(data
) integer_type
;
282 new(data
) string_type
;
288 new (data
) dictionary_type
;
291 TORRENT_ASSERT(t
== undefined_t
);
295 m_type_queried
= true;
299 void entry::copy(entry
const& e
)
304 new(data
) integer_type(e
.integer());
307 new(data
) string_type(e
.string());
310 new(data
) list_type(e
.list());
313 new (data
) dictionary_type(e
.dict());
316 TORRENT_ASSERT(e
.type() == undefined_t
);
320 m_type_queried
= true;
324 void entry::destruct()
329 call_destructor(reinterpret_cast<integer_type
*>(data
));
332 call_destructor(reinterpret_cast<string_type
*>(data
));
335 call_destructor(reinterpret_cast<list_type
*>(data
));
338 call_destructor(reinterpret_cast<dictionary_type
*>(data
));
341 TORRENT_ASSERT(m_type
== undefined_t
);
344 m_type
= undefined_t
;
346 m_type_queried
= false;
350 void entry::swap(entry
& e
)
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
<< " ";
363 os
<< integer() << "\n";
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;
376 if (binary_string
) os
<< to_hex(string()) << "\n";
377 else os
<< string() << "\n";
382 for (list_type::const_iterator i
= list().begin(); i
!= list().end(); ++i
)
384 i
->print(os
, indent
+1);
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;
401 for (int j
= 0; j
< indent
+1; ++j
) os
<< " ";
403 if (binary_string
) os
<< to_hex(i
->first
);
407 if (i
->second
.type() != entry::string_t
408 && i
->second
.type() != entry::int_t
)
411 i
->second
.print(os
, indent
+2);
415 os
<< "<uninitialized>\n";