2003-10-23 01:00:57 +02:00
|
|
|
/*
|
|
|
|
|
2018-04-09 09:04:33 +02:00
|
|
|
Copyright (c) 2003-2018, Arvid Norberg
|
2003-10-23 01:00:57 +02:00
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions
|
|
|
|
are met:
|
|
|
|
|
|
|
|
* Redistributions of source code must retain the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer in
|
|
|
|
the documentation and/or other materials provided with the distribution.
|
|
|
|
* Neither the name of the author nor the names of its
|
|
|
|
contributors may be used to endorse or promote products derived
|
|
|
|
from this software without specific prior written permission.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
|
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2015-04-20 02:01:27 +02:00
|
|
|
#include "libtorrent/config.hpp"
|
2018-04-26 09:01:14 +02:00
|
|
|
#if TORRENT_ABI_VERSION == 1
|
2010-03-04 17:42:39 +01:00
|
|
|
#include "libtorrent/lazy_entry.hpp"
|
2015-03-12 06:20:12 +01:00
|
|
|
#endif
|
|
|
|
#include "libtorrent/bdecode.hpp"
|
2017-07-20 09:27:47 +02:00
|
|
|
#include "libtorrent/bencode.hpp"
|
2015-04-20 02:01:27 +02:00
|
|
|
#include "libtorrent/entry.hpp"
|
2015-03-15 00:10:20 +01:00
|
|
|
#include "libtorrent/hex.hpp"
|
2016-08-18 23:08:40 +02:00
|
|
|
#include "libtorrent/string_util.hpp"
|
2017-01-29 21:37:42 +01:00
|
|
|
#include "libtorrent/aux_/throw.hpp"
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2017-04-12 19:00:57 +02:00
|
|
|
namespace libtorrent {
|
|
|
|
|
|
|
|
namespace detail {
|
2017-07-20 09:27:47 +02:00
|
|
|
|
2018-11-16 02:39:31 +01:00
|
|
|
string_view integer_to_str(span<char> buf
|
2017-07-20 09:27:47 +02:00
|
|
|
, entry::integer_type val)
|
|
|
|
{
|
|
|
|
int sign = 0;
|
|
|
|
if (val < 0)
|
2005-08-12 14:40:58 +02:00
|
|
|
{
|
2017-07-20 09:27:47 +02:00
|
|
|
sign = 1;
|
|
|
|
val = -val;
|
2005-08-12 14:40:58 +02:00
|
|
|
}
|
2018-11-16 02:39:31 +01:00
|
|
|
char* ptr = &buf.back();
|
|
|
|
*ptr-- = '\0';
|
|
|
|
if (val == 0) *ptr-- = '0';
|
|
|
|
while (ptr > buf.data() + sign && val != 0)
|
2017-07-20 09:27:47 +02:00
|
|
|
{
|
2018-11-16 02:39:31 +01:00
|
|
|
*ptr-- = '0' + char(val % 10);
|
2017-07-20 09:27:47 +02:00
|
|
|
val /= 10;
|
|
|
|
}
|
2018-11-16 02:39:31 +01:00
|
|
|
if (sign) *ptr-- = '-';
|
|
|
|
++ptr;
|
|
|
|
return {ptr, static_cast<std::size_t>(&buf.back() - ptr)};
|
2017-07-20 09:27:47 +02:00
|
|
|
}
|
|
|
|
} // detail
|
|
|
|
|
2017-04-12 19:00:57 +02:00
|
|
|
namespace {
|
|
|
|
|
2017-07-20 09:27:47 +02:00
|
|
|
inline void TORRENT_NO_RETURN throw_error()
|
|
|
|
{ aux::throw_ex<system_error>(errors::invalid_entry_type); }
|
2016-05-15 06:33:06 +02:00
|
|
|
|
2017-07-20 09:27:47 +02:00
|
|
|
template <class T>
|
|
|
|
void call_destructor(T* o)
|
|
|
|
{
|
|
|
|
TORRENT_ASSERT(o);
|
|
|
|
o->~T();
|
2016-05-15 06:33:06 +02:00
|
|
|
}
|
2017-07-20 09:27:47 +02:00
|
|
|
} // anonymous
|
2016-05-15 06:33:06 +02:00
|
|
|
|
2016-09-24 15:10:54 +02:00
|
|
|
entry& entry::operator[](string_view key)
|
2004-03-17 13:14:44 +01:00
|
|
|
{
|
2017-11-29 01:22:50 +01:00
|
|
|
auto const i = dict().find(key);
|
2008-05-19 09:15:44 +02:00
|
|
|
if (i != dict().end()) return i->second;
|
2017-11-29 01:22:50 +01:00
|
|
|
auto const ret = dict().emplace(
|
2017-01-20 00:08:39 +01:00
|
|
|
std::piecewise_construct,
|
|
|
|
std::forward_as_tuple(key),
|
|
|
|
std::forward_as_tuple()).first;
|
2008-05-19 09:15:44 +02:00
|
|
|
return ret->second;
|
2004-03-17 13:14:44 +01:00
|
|
|
}
|
|
|
|
|
2016-09-24 15:10:54 +02:00
|
|
|
const entry& entry::operator[](string_view key) const
|
2004-03-17 13:14:44 +01:00
|
|
|
{
|
2017-11-29 01:22:50 +01:00
|
|
|
auto const i = dict().find(key);
|
2016-09-24 15:10:54 +02:00
|
|
|
if (i == dict().end()) throw_error();
|
|
|
|
return i->second;
|
2004-03-17 13:14:44 +01:00
|
|
|
}
|
2015-06-03 07:12:54 +02:00
|
|
|
|
2016-09-24 15:10:54 +02:00
|
|
|
entry* entry::find_key(string_view key)
|
2008-05-19 09:15:44 +02:00
|
|
|
{
|
2017-11-29 01:22:50 +01:00
|
|
|
auto const i = dict().find(key);
|
2016-07-09 22:26:26 +02:00
|
|
|
if (i == dict().end()) return nullptr;
|
2008-05-19 09:15:44 +02:00
|
|
|
return &i->second;
|
|
|
|
}
|
|
|
|
|
2016-09-24 15:10:54 +02:00
|
|
|
entry const* entry::find_key(string_view key) const
|
2008-05-19 09:15:44 +02:00
|
|
|
{
|
2017-11-29 01:22:50 +01:00
|
|
|
auto const i = dict().find(key);
|
2016-07-09 22:26:26 +02:00
|
|
|
if (i == dict().end()) return nullptr;
|
2008-05-19 09:15:44 +02:00
|
|
|
return &i->second;
|
|
|
|
}
|
2015-06-03 07:12:54 +02:00
|
|
|
|
2010-06-06 02:47:39 +02:00
|
|
|
entry::data_type entry::type() const
|
|
|
|
{
|
2016-06-20 17:32:06 +02:00
|
|
|
#if TORRENT_USE_ASSERTS
|
2010-06-06 02:47:39 +02:00
|
|
|
m_type_queried = true;
|
|
|
|
#endif
|
2015-08-02 05:57:11 +02:00
|
|
|
return entry::data_type(m_type);
|
2010-06-06 02:47:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
entry::~entry() { destruct(); }
|
|
|
|
|
2018-06-30 18:31:45 +02:00
|
|
|
entry& entry::operator=(const entry& e) &
|
2010-06-06 02:47:39 +02:00
|
|
|
{
|
2016-05-06 07:08:05 +02:00
|
|
|
if (&e == this) return *this;
|
2010-06-06 02:47:39 +02:00
|
|
|
destruct();
|
|
|
|
copy(e);
|
2016-02-21 05:40:45 +01:00
|
|
|
return *this;
|
2010-06-06 02:47:39 +02:00
|
|
|
}
|
|
|
|
|
2018-06-30 18:31:45 +02:00
|
|
|
entry& entry::operator=(entry&& e) & noexcept
|
2016-05-01 05:44:48 +02:00
|
|
|
{
|
2017-09-12 23:10:11 +02:00
|
|
|
if (&e == this) return *this;
|
2018-01-04 21:02:34 +01:00
|
|
|
destruct();
|
|
|
|
const auto t = e.type();
|
|
|
|
switch (t)
|
|
|
|
{
|
|
|
|
case int_t:
|
|
|
|
new (&data) integer_type(std::move(e.integer()));
|
|
|
|
break;
|
|
|
|
case string_t:
|
|
|
|
new (&data) string_type(std::move(e.string()));
|
|
|
|
break;
|
|
|
|
case list_t:
|
|
|
|
new (&data) list_type(std::move(e.list()));
|
|
|
|
break;
|
|
|
|
case dictionary_t:
|
|
|
|
new (&data) dictionary_type(std::move(e.dict()));
|
|
|
|
break;
|
|
|
|
case undefined_t:
|
|
|
|
break;
|
|
|
|
case preformatted_t:
|
|
|
|
new (&data) preformatted_type(std::move(e.preformatted()));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
m_type = t;
|
|
|
|
#if TORRENT_USE_ASSERTS
|
|
|
|
m_type_queried = true;
|
|
|
|
#endif
|
2016-05-01 05:44:48 +02:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2010-06-06 02:47:39 +02:00
|
|
|
entry::integer_type& entry::integer()
|
|
|
|
{
|
|
|
|
if (m_type == undefined_t) construct(int_t);
|
2016-06-20 17:32:06 +02:00
|
|
|
#ifdef BOOST_NO_EXCEPTIONS
|
2010-06-06 02:47:39 +02:00
|
|
|
TORRENT_ASSERT(m_type_queried);
|
|
|
|
#endif
|
2016-06-20 17:32:06 +02:00
|
|
|
if (m_type != int_t) throw_error();
|
2010-06-06 02:47:39 +02:00
|
|
|
TORRENT_ASSERT(m_type == int_t);
|
2016-05-22 03:04:47 +02:00
|
|
|
return *reinterpret_cast<integer_type*>(&data);
|
2010-06-06 02:47:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
entry::integer_type const& entry::integer() const
|
|
|
|
{
|
2016-05-15 06:33:06 +02:00
|
|
|
if (m_type != int_t) throw_error();
|
2016-06-20 17:32:06 +02:00
|
|
|
#ifdef BOOST_NO_EXCEPTIONS
|
2010-06-06 02:47:39 +02:00
|
|
|
TORRENT_ASSERT(m_type_queried);
|
|
|
|
#endif
|
|
|
|
TORRENT_ASSERT(m_type == int_t);
|
2016-05-22 03:04:47 +02:00
|
|
|
return *reinterpret_cast<const integer_type*>(&data);
|
2010-06-06 02:47:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
entry::string_type& entry::string()
|
|
|
|
{
|
|
|
|
if (m_type == undefined_t) construct(string_t);
|
2016-06-20 17:32:06 +02:00
|
|
|
#ifdef BOOST_NO_EXCEPTIONS
|
2010-06-06 02:47:39 +02:00
|
|
|
TORRENT_ASSERT(m_type_queried);
|
|
|
|
#endif
|
2016-06-20 17:32:06 +02:00
|
|
|
if (m_type != string_t) throw_error();
|
2010-06-06 02:47:39 +02:00
|
|
|
TORRENT_ASSERT(m_type == string_t);
|
2016-05-22 03:04:47 +02:00
|
|
|
return *reinterpret_cast<string_type*>(&data);
|
2010-06-06 02:47:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
entry::string_type const& entry::string() const
|
|
|
|
{
|
2016-05-15 06:33:06 +02:00
|
|
|
if (m_type != string_t) throw_error();
|
2016-06-20 17:32:06 +02:00
|
|
|
#ifdef BOOST_NO_EXCEPTIONS
|
2010-06-06 02:47:39 +02:00
|
|
|
TORRENT_ASSERT(m_type_queried);
|
|
|
|
#endif
|
|
|
|
TORRENT_ASSERT(m_type == string_t);
|
2016-05-22 03:04:47 +02:00
|
|
|
return *reinterpret_cast<const string_type*>(&data);
|
2010-06-06 02:47:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
entry::list_type& entry::list()
|
|
|
|
{
|
|
|
|
if (m_type == undefined_t) construct(list_t);
|
2016-06-20 17:32:06 +02:00
|
|
|
#ifdef BOOST_NO_EXCEPTIONS
|
2010-06-06 02:47:39 +02:00
|
|
|
TORRENT_ASSERT(m_type_queried);
|
|
|
|
#endif
|
2016-06-20 17:32:06 +02:00
|
|
|
if (m_type != list_t) throw_error();
|
2010-06-06 02:47:39 +02:00
|
|
|
TORRENT_ASSERT(m_type == list_t);
|
2016-05-22 03:04:47 +02:00
|
|
|
return *reinterpret_cast<list_type*>(&data);
|
2010-06-06 02:47:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
entry::list_type const& entry::list() const
|
|
|
|
{
|
2016-05-15 06:33:06 +02:00
|
|
|
if (m_type != list_t) throw_error();
|
2016-06-20 17:32:06 +02:00
|
|
|
#ifdef BOOST_NO_EXCEPTIONS
|
2010-06-06 02:47:39 +02:00
|
|
|
TORRENT_ASSERT(m_type_queried);
|
|
|
|
#endif
|
|
|
|
TORRENT_ASSERT(m_type == list_t);
|
2016-05-22 03:04:47 +02:00
|
|
|
return *reinterpret_cast<const list_type*>(&data);
|
2010-06-06 02:47:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
entry::dictionary_type& entry::dict()
|
|
|
|
{
|
|
|
|
if (m_type == undefined_t) construct(dictionary_t);
|
2016-06-20 17:32:06 +02:00
|
|
|
#ifdef BOOST_NO_EXCEPTIONS
|
2010-06-06 02:47:39 +02:00
|
|
|
TORRENT_ASSERT(m_type_queried);
|
|
|
|
#endif
|
2016-06-20 17:32:06 +02:00
|
|
|
if (m_type != dictionary_t) throw_error();
|
2010-06-06 02:47:39 +02:00
|
|
|
TORRENT_ASSERT(m_type == dictionary_t);
|
2016-05-22 03:04:47 +02:00
|
|
|
return *reinterpret_cast<dictionary_type*>(&data);
|
2010-06-06 02:47:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
entry::dictionary_type const& entry::dict() const
|
|
|
|
{
|
2016-05-15 06:33:06 +02:00
|
|
|
if (m_type != dictionary_t) throw_error();
|
2016-06-20 17:32:06 +02:00
|
|
|
#ifdef BOOST_NO_EXCEPTIONS
|
2010-06-06 02:47:39 +02:00
|
|
|
TORRENT_ASSERT(m_type_queried);
|
|
|
|
#endif
|
|
|
|
TORRENT_ASSERT(m_type == dictionary_t);
|
2016-05-22 03:04:47 +02:00
|
|
|
return *reinterpret_cast<const dictionary_type*>(&data);
|
2010-06-06 02:47:39 +02:00
|
|
|
}
|
|
|
|
|
2016-05-06 03:38:57 +02:00
|
|
|
entry::preformatted_type& entry::preformatted()
|
|
|
|
{
|
|
|
|
if (m_type == undefined_t) construct(preformatted_t);
|
2016-06-20 17:32:06 +02:00
|
|
|
#ifdef BOOST_NO_EXCEPTIONS
|
2016-05-06 03:38:57 +02:00
|
|
|
TORRENT_ASSERT(m_type_queried);
|
|
|
|
#endif
|
2016-06-20 17:32:06 +02:00
|
|
|
if (m_type != preformatted_t) throw_error();
|
2016-05-06 03:38:57 +02:00
|
|
|
TORRENT_ASSERT(m_type == preformatted_t);
|
2016-05-22 03:04:47 +02:00
|
|
|
return *reinterpret_cast<preformatted_type*>(&data);
|
2016-05-06 03:38:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
entry::preformatted_type const& entry::preformatted() const
|
|
|
|
{
|
2016-05-15 06:33:06 +02:00
|
|
|
if (m_type != preformatted_t) throw_error();
|
2016-06-20 17:32:06 +02:00
|
|
|
#ifdef BOOST_NO_EXCEPTIONS
|
2016-05-06 03:38:57 +02:00
|
|
|
TORRENT_ASSERT(m_type_queried);
|
|
|
|
#endif
|
|
|
|
TORRENT_ASSERT(m_type == preformatted_t);
|
2016-05-22 03:04:47 +02:00
|
|
|
return *reinterpret_cast<const preformatted_type*>(&data);
|
2016-05-06 03:38:57 +02:00
|
|
|
}
|
|
|
|
|
2008-02-22 05:54:43 +01:00
|
|
|
entry::entry()
|
|
|
|
: m_type(undefined_t)
|
2008-01-03 04:10:25 +01:00
|
|
|
{
|
2016-06-20 17:32:06 +02:00
|
|
|
#if TORRENT_USE_ASSERTS
|
2008-01-03 04:10:25 +01:00
|
|
|
m_type_queried = true;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2008-02-22 05:54:43 +01:00
|
|
|
entry::entry(data_type t)
|
|
|
|
: m_type(undefined_t)
|
2008-01-03 04:10:25 +01:00
|
|
|
{
|
|
|
|
construct(t);
|
2016-06-20 17:32:06 +02:00
|
|
|
#if TORRENT_USE_ASSERTS
|
2008-01-03 04:10:25 +01:00
|
|
|
m_type_queried = true;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
entry::entry(const entry& e)
|
2008-02-22 05:54:43 +01:00
|
|
|
: m_type(undefined_t)
|
2008-01-03 04:10:25 +01:00
|
|
|
{
|
|
|
|
copy(e);
|
2016-06-20 17:32:06 +02:00
|
|
|
#if TORRENT_USE_ASSERTS
|
2008-01-03 04:10:25 +01:00
|
|
|
m_type_queried = e.m_type_queried;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-05-28 13:14:58 +02:00
|
|
|
entry::entry(entry&& e) noexcept
|
2016-05-01 05:44:48 +02:00
|
|
|
: m_type(undefined_t)
|
|
|
|
{
|
2018-01-04 21:02:34 +01:00
|
|
|
this->operator=(std::move(e));
|
2016-05-01 05:44:48 +02:00
|
|
|
}
|
|
|
|
|
2018-11-18 12:59:52 +01:00
|
|
|
entry::entry(bdecode_node const& n)
|
|
|
|
: m_type(undefined_t)
|
|
|
|
{
|
|
|
|
this->operator=(n);
|
|
|
|
}
|
|
|
|
|
2016-07-22 16:29:39 +02:00
|
|
|
entry::entry(dictionary_type v)
|
2008-02-22 05:54:43 +01:00
|
|
|
: m_type(undefined_t)
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
2016-06-20 17:32:06 +02:00
|
|
|
#if TORRENT_USE_ASSERTS
|
2007-12-28 20:07:28 +01:00
|
|
|
m_type_queried = true;
|
|
|
|
#endif
|
2016-07-22 16:29:39 +02:00
|
|
|
new(&data) dictionary_type(std::move(v));
|
2004-01-07 01:48:02 +01:00
|
|
|
m_type = dictionary_t;
|
2003-10-23 01:00:57 +02:00
|
|
|
}
|
|
|
|
|
2016-07-22 18:31:42 +02:00
|
|
|
entry::entry(span<char const> v)
|
2008-02-22 05:54:43 +01:00
|
|
|
: m_type(undefined_t)
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
2016-06-20 17:32:06 +02:00
|
|
|
#if TORRENT_USE_ASSERTS
|
2007-12-28 20:07:28 +01:00
|
|
|
m_type_queried = true;
|
|
|
|
#endif
|
2018-11-01 23:05:30 +01:00
|
|
|
new(&data) string_type(v.data(), std::size_t(v.size()));
|
2004-01-07 01:48:02 +01:00
|
|
|
m_type = string_t;
|
2003-10-23 01:00:57 +02:00
|
|
|
}
|
|
|
|
|
2016-07-22 16:29:39 +02:00
|
|
|
entry::entry(list_type v)
|
2008-02-22 05:54:43 +01:00
|
|
|
: m_type(undefined_t)
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
2016-06-20 17:32:06 +02:00
|
|
|
#if TORRENT_USE_ASSERTS
|
2007-12-28 20:07:28 +01:00
|
|
|
m_type_queried = true;
|
|
|
|
#endif
|
2016-07-22 16:29:39 +02:00
|
|
|
new(&data) list_type(std::move(v));
|
2004-01-07 01:48:02 +01:00
|
|
|
m_type = list_t;
|
2003-10-23 01:00:57 +02:00
|
|
|
}
|
|
|
|
|
2016-07-22 16:29:39 +02:00
|
|
|
entry::entry(integer_type v)
|
2008-02-22 05:54:43 +01:00
|
|
|
: m_type(undefined_t)
|
2004-01-07 01:48:02 +01:00
|
|
|
{
|
2016-06-20 17:32:06 +02:00
|
|
|
#if TORRENT_USE_ASSERTS
|
2007-12-28 20:07:28 +01:00
|
|
|
m_type_queried = true;
|
|
|
|
#endif
|
2016-07-22 16:29:39 +02:00
|
|
|
new(&data) integer_type(std::move(v));
|
2004-01-07 01:48:02 +01:00
|
|
|
m_type = int_t;
|
|
|
|
}
|
|
|
|
|
2016-07-22 16:29:39 +02:00
|
|
|
entry::entry(preformatted_type v)
|
2016-05-06 03:38:57 +02:00
|
|
|
: m_type(undefined_t)
|
|
|
|
{
|
2016-06-20 17:32:06 +02:00
|
|
|
#if TORRENT_USE_ASSERTS
|
2016-05-06 03:38:57 +02:00
|
|
|
m_type_queried = true;
|
|
|
|
#endif
|
2016-07-22 16:29:39 +02:00
|
|
|
new(&data) preformatted_type(std::move(v));
|
2016-05-06 03:38:57 +02:00
|
|
|
m_type = preformatted_t;
|
|
|
|
}
|
|
|
|
|
2015-03-12 06:20:12 +01:00
|
|
|
// convert a bdecode_node into an old skool entry
|
2018-06-30 18:31:45 +02:00
|
|
|
entry& entry::operator=(bdecode_node const& e) &
|
2015-03-12 06:20:12 +01:00
|
|
|
{
|
|
|
|
switch (e.type())
|
|
|
|
{
|
|
|
|
case bdecode_node::string_t:
|
2016-08-13 13:04:53 +02:00
|
|
|
this->string() = e.string_value().to_string();
|
2015-03-12 06:20:12 +01:00
|
|
|
break;
|
|
|
|
case bdecode_node::int_t:
|
|
|
|
this->integer() = e.int_value();
|
|
|
|
break;
|
|
|
|
case bdecode_node::dict_t:
|
|
|
|
{
|
|
|
|
dictionary_type& d = this->dict();
|
|
|
|
for (int i = 0; i < e.dict_size(); ++i)
|
|
|
|
{
|
2016-08-13 13:04:53 +02:00
|
|
|
std::pair<string_view, bdecode_node> elem = e.dict_at(i);
|
|
|
|
d[elem.first.to_string()] = elem.second;
|
2015-03-12 06:20:12 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case bdecode_node::list_t:
|
|
|
|
{
|
|
|
|
list_type& l = this->list();
|
|
|
|
for (int i = 0; i < e.list_size(); ++i)
|
|
|
|
{
|
2017-11-29 01:22:50 +01:00
|
|
|
l.emplace_back();
|
2015-03-12 06:20:12 +01:00
|
|
|
l.back() = e.list_at(i);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case bdecode_node::none_t:
|
|
|
|
destruct();
|
|
|
|
break;
|
|
|
|
}
|
2016-02-21 05:40:45 +01:00
|
|
|
return *this;
|
2015-03-12 06:20:12 +01:00
|
|
|
}
|
|
|
|
|
2018-04-26 09:01:14 +02:00
|
|
|
#if TORRENT_ABI_VERSION == 1
|
2010-03-04 17:42:39 +01:00
|
|
|
// convert a lazy_entry into an old skool entry
|
2018-06-30 18:31:45 +02:00
|
|
|
entry& entry::operator=(lazy_entry const& e) &
|
2010-03-04 17:42:39 +01:00
|
|
|
{
|
|
|
|
switch (e.type())
|
|
|
|
{
|
|
|
|
case lazy_entry::string_t:
|
|
|
|
this->string() = e.string_value();
|
|
|
|
break;
|
|
|
|
case lazy_entry::int_t:
|
|
|
|
this->integer() = e.int_value();
|
|
|
|
break;
|
|
|
|
case lazy_entry::dict_t:
|
|
|
|
{
|
|
|
|
dictionary_type& d = this->dict();
|
|
|
|
for (int i = 0; i < e.dict_size(); ++i)
|
|
|
|
{
|
|
|
|
std::pair<std::string, lazy_entry const*> elem = e.dict_at(i);
|
|
|
|
d[elem.first] = *elem.second;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case lazy_entry::list_t:
|
|
|
|
{
|
|
|
|
list_type& l = this->list();
|
|
|
|
for (int i = 0; i < e.list_size(); ++i)
|
|
|
|
{
|
2017-11-29 01:22:50 +01:00
|
|
|
l.emplace_back();
|
2010-03-04 17:42:39 +01:00
|
|
|
l.back() = *e.list_at(i);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2011-02-14 02:59:01 +01:00
|
|
|
case lazy_entry::none_t:
|
|
|
|
destruct();
|
|
|
|
break;
|
2010-03-04 17:42:39 +01:00
|
|
|
}
|
2016-02-21 05:40:45 +01:00
|
|
|
return *this;
|
2010-03-04 17:42:39 +01:00
|
|
|
}
|
2015-03-12 06:20:12 +01:00
|
|
|
#endif
|
2010-03-04 17:42:39 +01:00
|
|
|
|
2018-06-30 18:31:45 +02:00
|
|
|
entry& entry::operator=(preformatted_type v) &
|
2016-05-06 03:38:57 +02:00
|
|
|
{
|
|
|
|
destruct();
|
2016-07-22 16:29:39 +02:00
|
|
|
new(&data) preformatted_type(std::move(v));
|
2016-05-06 03:38:57 +02:00
|
|
|
m_type = preformatted_t;
|
2016-06-20 17:32:06 +02:00
|
|
|
#if TORRENT_USE_ASSERTS
|
2016-05-06 03:38:57 +02:00
|
|
|
m_type_queried = true;
|
|
|
|
#endif
|
2016-05-06 07:08:05 +02:00
|
|
|
return *this;
|
2016-05-06 03:38:57 +02:00
|
|
|
}
|
|
|
|
|
2018-06-30 18:31:45 +02:00
|
|
|
entry& entry::operator=(dictionary_type v) &
|
2004-01-07 01:48:02 +01:00
|
|
|
{
|
|
|
|
destruct();
|
2016-07-22 16:29:39 +02:00
|
|
|
new(&data) dictionary_type(std::move(v));
|
2004-01-07 01:48:02 +01:00
|
|
|
m_type = dictionary_t;
|
2016-06-20 17:32:06 +02:00
|
|
|
#if TORRENT_USE_ASSERTS
|
2007-12-28 20:07:28 +01:00
|
|
|
m_type_queried = true;
|
|
|
|
#endif
|
2016-02-21 05:40:45 +01:00
|
|
|
return *this;
|
2004-01-07 01:48:02 +01:00
|
|
|
}
|
|
|
|
|
2018-06-30 18:31:45 +02:00
|
|
|
entry& entry::operator=(span<char const> v) &
|
2004-01-07 01:48:02 +01:00
|
|
|
{
|
|
|
|
destruct();
|
2018-11-01 23:05:30 +01:00
|
|
|
new(&data) string_type(v.data(), std::size_t(v.size()));
|
2004-01-07 01:48:02 +01:00
|
|
|
m_type = string_t;
|
2016-06-20 17:32:06 +02:00
|
|
|
#if TORRENT_USE_ASSERTS
|
2007-12-28 20:07:28 +01:00
|
|
|
m_type_queried = true;
|
|
|
|
#endif
|
2016-02-21 05:40:45 +01:00
|
|
|
return *this;
|
2004-01-07 01:48:02 +01:00
|
|
|
}
|
|
|
|
|
2018-06-30 18:31:45 +02:00
|
|
|
entry& entry::operator=(list_type v) &
|
2004-01-07 01:48:02 +01:00
|
|
|
{
|
|
|
|
destruct();
|
2016-07-22 16:29:39 +02:00
|
|
|
new(&data) list_type(std::move(v));
|
2004-01-07 01:48:02 +01:00
|
|
|
m_type = list_t;
|
2016-06-20 17:32:06 +02:00
|
|
|
#if TORRENT_USE_ASSERTS
|
2007-12-28 20:07:28 +01:00
|
|
|
m_type_queried = true;
|
|
|
|
#endif
|
2016-02-21 05:40:45 +01:00
|
|
|
return *this;
|
2004-01-07 01:48:02 +01:00
|
|
|
}
|
|
|
|
|
2018-06-30 18:31:45 +02:00
|
|
|
entry& entry::operator=(integer_type v) &
|
2004-01-07 01:48:02 +01:00
|
|
|
{
|
|
|
|
destruct();
|
2016-07-22 16:29:39 +02:00
|
|
|
new(&data) integer_type(std::move(v));
|
2004-01-07 01:48:02 +01:00
|
|
|
m_type = int_t;
|
2016-06-20 17:32:06 +02:00
|
|
|
#if TORRENT_USE_ASSERTS
|
2007-12-28 20:07:28 +01:00
|
|
|
m_type_queried = true;
|
|
|
|
#endif
|
2016-02-21 05:40:45 +01:00
|
|
|
return *this;
|
2004-01-07 01:48:02 +01:00
|
|
|
}
|
|
|
|
|
2018-11-18 12:59:52 +01:00
|
|
|
bool operator==(entry const& lhs, entry const& rhs)
|
2005-08-11 13:06:52 +02:00
|
|
|
{
|
2018-11-18 12:59:52 +01:00
|
|
|
if (lhs.type() != rhs.type()) return false;
|
2005-08-11 13:06:52 +02:00
|
|
|
|
2018-11-18 12:59:52 +01:00
|
|
|
switch (lhs.type())
|
2005-08-11 13:06:52 +02:00
|
|
|
{
|
2018-11-18 12:59:52 +01:00
|
|
|
case entry::int_t:
|
|
|
|
return lhs.integer() == rhs.integer();
|
|
|
|
case entry::string_t:
|
|
|
|
return lhs.string() == rhs.string();
|
|
|
|
case entry::list_t:
|
|
|
|
return lhs.list() == rhs.list();
|
|
|
|
case entry::dictionary_t:
|
|
|
|
return lhs.dict() == rhs.dict();
|
|
|
|
case entry::preformatted_t:
|
|
|
|
return lhs.preformatted() == rhs.preformatted();
|
|
|
|
case entry::undefined_t:
|
2005-08-11 13:06:52 +02:00
|
|
|
return true;
|
|
|
|
}
|
2018-11-18 12:59:52 +01:00
|
|
|
return false;
|
2005-08-11 13:06:52 +02:00
|
|
|
}
|
2004-01-07 01:48:02 +01:00
|
|
|
|
|
|
|
void entry::construct(data_type t)
|
|
|
|
{
|
2015-08-11 02:03:24 +02:00
|
|
|
switch (t)
|
2004-01-07 01:48:02 +01:00
|
|
|
{
|
|
|
|
case int_t:
|
2018-11-16 08:22:36 +01:00
|
|
|
new (&data) integer_type(0);
|
2004-01-07 01:48:02 +01:00
|
|
|
break;
|
|
|
|
case string_t:
|
2016-05-22 03:04:47 +02:00
|
|
|
new (&data) string_type;
|
2004-01-07 01:48:02 +01:00
|
|
|
break;
|
|
|
|
case list_t:
|
2016-05-22 03:04:47 +02:00
|
|
|
new (&data) list_type;
|
2004-01-07 01:48:02 +01:00
|
|
|
break;
|
|
|
|
case dictionary_t:
|
2016-05-22 03:04:47 +02:00
|
|
|
new (&data) dictionary_type;
|
2004-01-07 01:48:02 +01:00
|
|
|
break;
|
2015-08-11 02:03:24 +02:00
|
|
|
case undefined_t:
|
|
|
|
break;
|
2016-05-06 03:38:57 +02:00
|
|
|
case preformatted_t:
|
2016-05-22 03:04:47 +02:00
|
|
|
new (&data) preformatted_type;
|
2016-05-06 03:38:57 +02:00
|
|
|
break;
|
2004-01-07 01:48:02 +01:00
|
|
|
}
|
2008-02-22 05:54:43 +01:00
|
|
|
m_type = t;
|
2016-06-20 17:32:06 +02:00
|
|
|
#if TORRENT_USE_ASSERTS
|
2007-12-28 20:07:28 +01:00
|
|
|
m_type_queried = true;
|
|
|
|
#endif
|
2004-01-07 01:48:02 +01:00
|
|
|
}
|
|
|
|
|
2006-11-14 01:08:16 +01:00
|
|
|
void entry::copy(entry const& e)
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
2008-02-22 05:54:43 +01:00
|
|
|
switch (e.type())
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
2004-01-07 01:48:02 +01:00
|
|
|
case int_t:
|
2016-05-22 03:04:47 +02:00
|
|
|
new (&data) integer_type(e.integer());
|
2004-01-07 01:48:02 +01:00
|
|
|
break;
|
|
|
|
case string_t:
|
2016-05-22 03:04:47 +02:00
|
|
|
new (&data) string_type(e.string());
|
2004-01-07 01:48:02 +01:00
|
|
|
break;
|
|
|
|
case list_t:
|
2016-05-22 03:04:47 +02:00
|
|
|
new (&data) list_type(e.list());
|
2004-01-07 01:48:02 +01:00
|
|
|
break;
|
|
|
|
case dictionary_t:
|
2016-05-22 03:04:47 +02:00
|
|
|
new (&data) dictionary_type(e.dict());
|
2004-01-07 01:48:02 +01:00
|
|
|
break;
|
2015-08-11 02:03:24 +02:00
|
|
|
case undefined_t:
|
2008-02-22 05:54:43 +01:00
|
|
|
TORRENT_ASSERT(e.type() == undefined_t);
|
2016-05-06 03:38:57 +02:00
|
|
|
break;
|
|
|
|
case preformatted_t:
|
2016-05-22 03:04:47 +02:00
|
|
|
new (&data) preformatted_type(e.preformatted());
|
2016-05-06 03:38:57 +02:00
|
|
|
break;
|
2004-01-07 01:48:02 +01:00
|
|
|
}
|
2008-02-22 05:54:43 +01:00
|
|
|
m_type = e.type();
|
2016-06-20 17:32:06 +02:00
|
|
|
#if TORRENT_USE_ASSERTS
|
2007-12-28 20:07:28 +01:00
|
|
|
m_type_queried = true;
|
|
|
|
#endif
|
2004-01-07 01:48:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void entry::destruct()
|
|
|
|
{
|
|
|
|
switch(m_type)
|
|
|
|
{
|
|
|
|
case int_t:
|
2016-05-22 03:04:47 +02:00
|
|
|
call_destructor(reinterpret_cast<integer_type*>(&data));
|
2004-01-07 01:48:02 +01:00
|
|
|
break;
|
|
|
|
case string_t:
|
2016-05-22 03:04:47 +02:00
|
|
|
call_destructor(reinterpret_cast<string_type*>(&data));
|
2004-01-07 01:48:02 +01:00
|
|
|
break;
|
|
|
|
case list_t:
|
2016-05-22 03:04:47 +02:00
|
|
|
call_destructor(reinterpret_cast<list_type*>(&data));
|
2004-01-07 01:48:02 +01:00
|
|
|
break;
|
|
|
|
case dictionary_t:
|
2016-05-22 03:04:47 +02:00
|
|
|
call_destructor(reinterpret_cast<dictionary_type*>(&data));
|
2004-01-07 01:48:02 +01:00
|
|
|
break;
|
2016-05-06 03:38:57 +02:00
|
|
|
case preformatted_t:
|
2016-05-22 03:04:47 +02:00
|
|
|
call_destructor(reinterpret_cast<preformatted_type*>(&data));
|
2016-05-06 03:38:57 +02:00
|
|
|
break;
|
2004-01-07 01:48:02 +01:00
|
|
|
default:
|
2007-10-05 02:30:00 +02:00
|
|
|
TORRENT_ASSERT(m_type == undefined_t);
|
2004-01-07 01:48:02 +01:00
|
|
|
break;
|
|
|
|
}
|
2008-02-22 05:54:43 +01:00
|
|
|
m_type = undefined_t;
|
2016-06-20 17:32:06 +02:00
|
|
|
#if TORRENT_USE_ASSERTS
|
2007-12-28 20:07:28 +01:00
|
|
|
m_type_queried = false;
|
|
|
|
#endif
|
2004-01-07 01:48:02 +01:00
|
|
|
}
|
|
|
|
|
2018-01-04 21:02:34 +01:00
|
|
|
void entry::swap(entry& e)
|
2007-06-10 22:46:09 +02:00
|
|
|
{
|
2014-02-28 05:02:48 +01:00
|
|
|
bool clear_this = false;
|
|
|
|
bool clear_that = false;
|
|
|
|
|
|
|
|
if (m_type == undefined_t && e.m_type == undefined_t)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (m_type == undefined_t)
|
|
|
|
{
|
2015-08-02 05:57:11 +02:00
|
|
|
construct(data_type(e.m_type));
|
2014-02-28 05:02:48 +01:00
|
|
|
clear_that = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (e.m_type == undefined_t)
|
|
|
|
{
|
2015-08-02 05:57:11 +02:00
|
|
|
e.construct(data_type(m_type));
|
2014-02-28 05:02:48 +01:00
|
|
|
clear_this = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_type == e.m_type)
|
|
|
|
{
|
|
|
|
switch (m_type)
|
|
|
|
{
|
|
|
|
case int_t:
|
2016-05-22 03:04:47 +02:00
|
|
|
std::swap(*reinterpret_cast<integer_type*>(&data)
|
|
|
|
, *reinterpret_cast<integer_type*>(&e.data));
|
2014-02-28 05:02:48 +01:00
|
|
|
break;
|
|
|
|
case string_t:
|
2016-05-22 03:04:47 +02:00
|
|
|
std::swap(*reinterpret_cast<string_type*>(&data)
|
|
|
|
, *reinterpret_cast<string_type*>(&e.data));
|
2014-02-28 05:02:48 +01:00
|
|
|
break;
|
|
|
|
case list_t:
|
2016-05-22 03:04:47 +02:00
|
|
|
std::swap(*reinterpret_cast<list_type*>(&data)
|
|
|
|
, *reinterpret_cast<list_type*>(&e.data));
|
2014-02-28 05:02:48 +01:00
|
|
|
break;
|
|
|
|
case dictionary_t:
|
2016-05-22 03:04:47 +02:00
|
|
|
std::swap(*reinterpret_cast<dictionary_type*>(&data)
|
|
|
|
, *reinterpret_cast<dictionary_type*>(&e.data));
|
2014-02-28 05:02:48 +01:00
|
|
|
break;
|
2016-05-06 03:38:57 +02:00
|
|
|
case preformatted_t:
|
2016-05-22 03:04:47 +02:00
|
|
|
std::swap(*reinterpret_cast<preformatted_type*>(&data)
|
|
|
|
, *reinterpret_cast<preformatted_type*>(&e.data));
|
2016-05-06 03:38:57 +02:00
|
|
|
break;
|
2014-02-28 05:02:48 +01:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (clear_this)
|
|
|
|
destruct();
|
|
|
|
|
|
|
|
if (clear_that)
|
|
|
|
e.destruct();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// currently, only swapping entries of the same type or where one
|
|
|
|
// of the entries is uninitialized is supported.
|
2016-05-02 18:36:21 +02:00
|
|
|
TORRENT_ASSERT_FAIL();
|
2014-02-28 05:02:48 +01:00
|
|
|
}
|
2007-06-10 22:46:09 +02:00
|
|
|
}
|
|
|
|
|
2018-08-26 22:15:05 +02:00
|
|
|
namespace {
|
|
|
|
bool is_binary(std::string const& str)
|
|
|
|
{
|
2018-11-26 15:16:39 +01:00
|
|
|
return std::any_of(str.begin(), str.end()
|
|
|
|
, [](char const c) { return !is_print(c); });
|
2018-08-26 22:15:05 +02:00
|
|
|
}
|
|
|
|
|
2018-09-19 20:32:18 +02:00
|
|
|
std::string print_string(std::string const& str)
|
|
|
|
{
|
|
|
|
if (is_binary(str)) return aux::to_hex(str);
|
|
|
|
else return str;
|
|
|
|
}
|
|
|
|
|
2018-08-26 22:15:05 +02:00
|
|
|
void add_indent(std::string& out, int const indent)
|
|
|
|
{
|
2018-09-04 14:31:05 +02:00
|
|
|
out.resize(out.size() + size_t(indent), ' ');
|
2018-08-26 22:15:05 +02:00
|
|
|
}
|
|
|
|
|
2018-10-02 08:57:50 +02:00
|
|
|
void print_list(std::string&, entry const&, int, bool);
|
|
|
|
void print_dict(std::string&, entry const&, int, bool);
|
|
|
|
|
|
|
|
void to_string_impl(std::string& out, entry const& e, int const indent
|
|
|
|
, bool const single_line)
|
2004-01-07 01:48:02 +01:00
|
|
|
{
|
2007-10-05 02:30:00 +02:00
|
|
|
TORRENT_ASSERT(indent >= 0);
|
2018-10-02 08:57:50 +02:00
|
|
|
switch (e.type())
|
2004-01-07 01:48:02 +01:00
|
|
|
{
|
2018-10-02 08:57:50 +02:00
|
|
|
case entry::int_t:
|
|
|
|
out += libtorrent::to_string(e.integer()).data();
|
2004-01-07 01:48:02 +01:00
|
|
|
break;
|
2018-10-02 08:57:50 +02:00
|
|
|
case entry::string_t:
|
|
|
|
out += "'";
|
|
|
|
out += print_string(e.string());
|
|
|
|
out += "'";
|
|
|
|
break;
|
|
|
|
case entry::list_t:
|
|
|
|
print_list(out, e, indent + 1, single_line);
|
|
|
|
break;
|
|
|
|
case entry::dictionary_t:
|
|
|
|
print_dict(out, e, indent + 1, single_line);
|
|
|
|
break;
|
|
|
|
case entry::preformatted_t:
|
2018-08-26 22:15:05 +02:00
|
|
|
out += "<preformatted>";
|
2016-05-06 03:38:57 +02:00
|
|
|
break;
|
2018-10-02 08:57:50 +02:00
|
|
|
case entry::undefined_t:
|
2018-08-26 22:15:05 +02:00
|
|
|
out += "<uninitialized>";
|
2018-09-19 20:32:18 +02:00
|
|
|
break;
|
2004-01-07 01:48:02 +01:00
|
|
|
}
|
2003-10-23 01:00:57 +02:00
|
|
|
}
|
2018-10-02 08:57:50 +02:00
|
|
|
|
|
|
|
void print_list(std::string& out, entry const& e
|
|
|
|
, int const indent, bool const single_line)
|
|
|
|
{
|
|
|
|
out += single_line ? "[ " : "[\n";
|
|
|
|
bool first = true;
|
|
|
|
for (auto const& item : e.list())
|
|
|
|
{
|
|
|
|
if (!first) out += single_line ? ", " : ",\n";
|
|
|
|
first = false;
|
|
|
|
if (!single_line) add_indent(out, indent);
|
|
|
|
to_string_impl(out, item, indent, single_line);
|
|
|
|
}
|
|
|
|
out += " ]";
|
|
|
|
}
|
|
|
|
|
|
|
|
void print_dict(std::string& out, entry const& e
|
|
|
|
, int const indent, bool const single_line)
|
|
|
|
{
|
|
|
|
out += single_line ? "{ " : "{\n";
|
|
|
|
bool first = true;
|
|
|
|
for (auto const& item : e.dict())
|
|
|
|
{
|
|
|
|
if (!first) out += single_line ? ", " : ",\n";
|
|
|
|
first = false;
|
|
|
|
if (!single_line) add_indent(out, indent);
|
|
|
|
out += "'";
|
|
|
|
out += print_string(item.first);
|
|
|
|
out += "': ";
|
|
|
|
|
|
|
|
to_string_impl(out, item.second, indent+1, single_line);
|
|
|
|
}
|
|
|
|
out += " }";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string entry::to_string(bool const single_line) const
|
|
|
|
{
|
|
|
|
std::string ret;
|
|
|
|
to_string_impl(ret, *this, 0, single_line);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
}
|