lt exception tweaks 1719

This commit is contained in:
Marcos Pinto 2007-11-02 02:29:33 +00:00
parent 2eec0a766d
commit b144525cab
3 changed files with 85 additions and 23 deletions

View File

@ -135,26 +135,38 @@ namespace libtorrent
} }
template <class InIt> template <class InIt>
std::string read_until(InIt& in, InIt end, char end_token) std::string read_until(InIt& in, InIt end, char end_token, bool& err)
{ {
if (in == end) throw invalid_encoding();
std::string ret; std::string ret;
if (in == end)
{
err = true;
return ret;
}
while (*in != end_token) while (*in != end_token)
{ {
ret += *in; ret += *in;
++in; ++in;
if (in == end) throw invalid_encoding(); if (in == end)
{
err = true;
return ret;
}
} }
return ret; return ret;
} }
template<class InIt> template<class InIt>
void read_string(InIt& in, InIt end, int len, std::string& str) void read_string(InIt& in, InIt end, int len, std::string& str, bool& err)
{ {
TORRENT_ASSERT(len >= 0); TORRENT_ASSERT(len >= 0);
for (int i = 0; i < len; ++i) for (int i = 0; i < len; ++i)
{ {
if (in == end) throw invalid_encoding(); if (in == end)
{
err = true;
return;
}
str += *in; str += *in;
++in; ++in;
} }
@ -202,9 +214,13 @@ namespace libtorrent
} }
template<class InIt> template<class InIt>
void bdecode_recursive(InIt& in, InIt end, entry& ret) void bdecode_recursive(InIt& in, InIt end, entry& ret, bool& err)
{ {
if (in == end) throw invalid_encoding(); if (in == end)
{
err = true;
return;
}
switch (*in) switch (*in)
{ {
@ -213,7 +229,8 @@ namespace libtorrent
case 'i': case 'i':
{ {
++in; // 'i' ++in; // 'i'
std::string val = read_until(in, end, 'e'); std::string val = read_until(in, end, 'e', err);
if (err) return;
TORRENT_ASSERT(*in == 'e'); TORRENT_ASSERT(*in == 'e');
++in; // 'e' ++in; // 'e'
ret = entry(entry::int_t); ret = entry(entry::int_t);
@ -230,8 +247,13 @@ namespace libtorrent
{ {
ret.list().push_back(entry()); ret.list().push_back(entry());
entry& e = ret.list().back(); entry& e = ret.list().back();
bdecode_recursive(in, end, e); bdecode_recursive(in, end, e, err);
if (in == end) throw invalid_encoding(); if (err) return;
if (in == end)
{
err = true;
return;
}
} }
TORRENT_ASSERT(*in == 'e'); TORRENT_ASSERT(*in == 'e');
++in; // 'e' ++in; // 'e'
@ -246,10 +268,16 @@ namespace libtorrent
while (*in != 'e') while (*in != 'e')
{ {
entry key; entry key;
bdecode_recursive(in, end, key); bdecode_recursive(in, end, key, err);
if (err) return;
entry& e = ret[key.string()]; entry& e = ret[key.string()];
bdecode_recursive(in, end, e); bdecode_recursive(in, end, e, err);
if (in == end) throw invalid_encoding(); if (err) return;
if (in == end)
{
err = true;
return;
}
} }
TORRENT_ASSERT(*in == 'e'); TORRENT_ASSERT(*in == 'e');
++in; // 'e' ++in; // 'e'
@ -260,16 +288,19 @@ namespace libtorrent
default: default:
if (isdigit((unsigned char)*in)) if (isdigit((unsigned char)*in))
{ {
std::string len_s = read_until(in, end, ':'); std::string len_s = read_until(in, end, ':', err);
if (err) return;
TORRENT_ASSERT(*in == ':'); TORRENT_ASSERT(*in == ':');
++in; // ':' ++in; // ':'
int len = std::atoi(len_s.c_str()); int len = std::atoi(len_s.c_str());
ret = entry(entry::string_t); ret = entry(entry::string_t);
read_string(in, end, len, ret.string()); read_string(in, end, len, ret.string(), err);
if (err) return;
} }
else else
{ {
throw invalid_encoding(); err = true;
return;
} }
} }
} }
@ -283,17 +314,19 @@ namespace libtorrent
template<class InIt> template<class InIt>
entry bdecode(InIt start, InIt end) entry bdecode(InIt start, InIt end)
{
try
{ {
entry e; entry e;
detail::bdecode_recursive(start, end, e); bool err = false;
return e; detail::bdecode_recursive(start, end, e, err);
} if (err)
catch(type_error&)
{ {
#ifdef BOOST_NO_EXCEPTIONS
return entry();
#else
throw invalid_encoding(); throw invalid_encoding();
#endif
} }
return e;
} }
} }

View File

@ -161,8 +161,10 @@ namespace libtorrent
// is a dictionary, otherwise they will throw // is a dictionary, otherwise they will throw
entry& operator[](char const* key); entry& operator[](char const* key);
entry& operator[](std::string const& key); entry& operator[](std::string const& key);
#ifndef BOOST_NO_EXCEPTIONS
const entry& operator[](char const* key) const; const entry& operator[](char const* key) const;
const entry& operator[](std::string const& key) const; const entry& operator[](std::string const& key) const;
#endif
entry* find_key(char const* key); entry* find_key(char const* key);
entry const* find_key(char const* key) const; entry const* find_key(char const* key) const;
@ -221,55 +223,80 @@ namespace libtorrent
copy(e); copy(e);
} }
inline entry::integer_type& entry::integer() inline entry::integer_type& entry::integer()
{ {
if (m_type == undefined_t) construct(int_t); if (m_type == undefined_t) construct(int_t);
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != int_t) throw type_error("invalid type requested from entry"); if (m_type != int_t) throw type_error("invalid type requested from entry");
#endif
TORRENT_ASSERT(m_type == int_t);
return *reinterpret_cast<integer_type*>(data); return *reinterpret_cast<integer_type*>(data);
} }
inline entry::integer_type const& entry::integer() const inline entry::integer_type const& entry::integer() const
{ {
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != int_t) throw type_error("invalid type requested from entry"); if (m_type != int_t) throw type_error("invalid type requested from entry");
#endif
TORRENT_ASSERT(m_type == int_t);
return *reinterpret_cast<const integer_type*>(data); return *reinterpret_cast<const integer_type*>(data);
} }
inline entry::string_type& entry::string() inline entry::string_type& entry::string()
{ {
if (m_type == undefined_t) construct(string_t); if (m_type == undefined_t) construct(string_t);
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != string_t) throw type_error("invalid type requested from entry"); if (m_type != string_t) throw type_error("invalid type requested from entry");
#endif
TORRENT_ASSERT(m_type == string_t);
return *reinterpret_cast<string_type*>(data); return *reinterpret_cast<string_type*>(data);
} }
inline entry::string_type const& entry::string() const inline entry::string_type const& entry::string() const
{ {
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != string_t) throw type_error("invalid type requested from entry"); if (m_type != string_t) throw type_error("invalid type requested from entry");
#endif
TORRENT_ASSERT(m_type == string_t);
return *reinterpret_cast<const string_type*>(data); return *reinterpret_cast<const string_type*>(data);
} }
inline entry::list_type& entry::list() inline entry::list_type& entry::list()
{ {
if (m_type == undefined_t) construct(list_t); if (m_type == undefined_t) construct(list_t);
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != list_t) throw type_error("invalid type requested from entry"); if (m_type != list_t) throw type_error("invalid type requested from entry");
#endif
TORRENT_ASSERT(m_type == list_t);
return *reinterpret_cast<list_type*>(data); return *reinterpret_cast<list_type*>(data);
} }
inline entry::list_type const& entry::list() const inline entry::list_type const& entry::list() const
{ {
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != list_t) throw type_error("invalid type requested from entry"); if (m_type != list_t) throw type_error("invalid type requested from entry");
#endif
TORRENT_ASSERT(m_type == list_t);
return *reinterpret_cast<const list_type*>(data); return *reinterpret_cast<const list_type*>(data);
} }
inline entry::dictionary_type& entry::dict() inline entry::dictionary_type& entry::dict()
{ {
if (m_type == undefined_t) construct(dictionary_t); if (m_type == undefined_t) construct(dictionary_t);
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != dictionary_t) throw type_error("invalid type requested from entry"); if (m_type != dictionary_t) throw type_error("invalid type requested from entry");
#endif
TORRENT_ASSERT(m_type == dictionary_t);
return *reinterpret_cast<dictionary_type*>(data); return *reinterpret_cast<dictionary_type*>(data);
} }
inline entry::dictionary_type const& entry::dict() const inline entry::dictionary_type const& entry::dict() const
{ {
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != dictionary_t) throw type_error("invalid type requested from entry"); if (m_type != dictionary_t) throw type_error("invalid type requested from entry");
#endif
TORRENT_ASSERT(m_type == dictionary_t);
return *reinterpret_cast<const dictionary_type*>(data); return *reinterpret_cast<const dictionary_type*>(data);
} }

View File

@ -126,6 +126,7 @@ namespace libtorrent
return &i->second; return &i->second;
} }
#ifndef BOOST_NO_EXCEPTIONS
const entry& entry::operator[](char const* key) const const entry& entry::operator[](char const* key) const
{ {
dictionary_type::const_iterator i = dict().find(key); dictionary_type::const_iterator i = dict().find(key);
@ -138,6 +139,7 @@ namespace libtorrent
{ {
return (*this)[key.c_str()]; return (*this)[key.c_str()];
} }
#endif
entry::entry(dictionary_type const& v) entry::entry(dictionary_type const& v)
{ {