2003-10-23 01:00:57 +02:00
|
|
|
/*
|
|
|
|
|
|
|
|
Copyright (c) 2003, Arvid Norberg
|
|
|
|
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.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2004-03-27 23:02:31 +01:00
|
|
|
#include <algorithm>
|
2003-10-23 01:00:57 +02:00
|
|
|
#include "libtorrent/entry.hpp"
|
2004-03-17 13:14:44 +01:00
|
|
|
#include <boost/bind.hpp>
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2003-11-09 19:17:09 +01:00
|
|
|
#if defined(_MSC_VER)
|
2003-10-23 01:00:57 +02:00
|
|
|
namespace std
|
|
|
|
{
|
|
|
|
using ::isprint;
|
|
|
|
}
|
|
|
|
#define for if (false) {} else for
|
|
|
|
#endif
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
template <class T>
|
|
|
|
void call_destructor(T* o)
|
|
|
|
{
|
2004-01-25 23:41:55 +01:00
|
|
|
assert(o);
|
2003-10-23 01:00:57 +02:00
|
|
|
o->~T();
|
|
|
|
}
|
2004-03-17 13:14:44 +01:00
|
|
|
|
|
|
|
struct compare_string
|
|
|
|
{
|
|
|
|
compare_string(char const* s): m_str(s) {}
|
|
|
|
|
|
|
|
bool operator()(
|
|
|
|
std::pair<std::string
|
|
|
|
, libtorrent::entry> const& e) const
|
|
|
|
{
|
|
|
|
return e.first == m_str;
|
|
|
|
}
|
|
|
|
char const* m_str;
|
|
|
|
};
|
2003-10-23 01:00:57 +02:00
|
|
|
}
|
|
|
|
|
2004-01-07 01:48:02 +01:00
|
|
|
namespace libtorrent
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
2004-03-17 13:14:44 +01:00
|
|
|
entry& entry::operator[](char const* key)
|
|
|
|
{
|
|
|
|
dictionary_type::iterator i = std::find_if(
|
|
|
|
dict().begin()
|
|
|
|
, dict().end()
|
|
|
|
, compare_string(key));
|
|
|
|
if (i != dict().end()) return i->second;
|
|
|
|
dictionary_type::iterator ret = dict().insert(
|
|
|
|
dict().end()
|
|
|
|
, std::make_pair(std::string(key), entry()));
|
|
|
|
return ret->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
entry& entry::operator[](std::string const& key)
|
|
|
|
{
|
|
|
|
return (*this)[key.c_str()];
|
|
|
|
}
|
|
|
|
|
|
|
|
entry* entry::find_key(char const* key)
|
|
|
|
{
|
|
|
|
dictionary_type::iterator i = std::find_if(
|
|
|
|
dict().begin()
|
|
|
|
, dict().end()
|
|
|
|
, compare_string(key));
|
|
|
|
if (i == dict().end()) return 0;
|
|
|
|
return &i->second;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
entry const* entry::find_key(char const* key) const
|
|
|
|
{
|
|
|
|
dictionary_type::const_iterator i = std::find_if(
|
|
|
|
dict().begin()
|
|
|
|
, dict().end()
|
|
|
|
, compare_string(key));
|
|
|
|
if (i == dict().end()) return 0;
|
|
|
|
return &i->second;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const entry& entry::operator[](char const* key) const
|
|
|
|
{
|
|
|
|
dictionary_type::const_iterator i = std::find_if(
|
|
|
|
dict().begin()
|
|
|
|
, dict().end()
|
|
|
|
, compare_string(key));
|
|
|
|
if (i == dict().end()) throw type_error("key not found");
|
|
|
|
return i->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
const entry& entry::operator[](std::string const& key) const
|
|
|
|
{
|
|
|
|
return (*this)[key.c_str()];
|
|
|
|
}
|
2004-01-07 01:48:02 +01:00
|
|
|
|
|
|
|
entry::entry(const dictionary_type& v)
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
2004-01-07 01:48:02 +01:00
|
|
|
new(data) dictionary_type(v);
|
|
|
|
m_type = dictionary_t;
|
2003-10-23 01:00:57 +02:00
|
|
|
}
|
|
|
|
|
2004-01-07 01:48:02 +01:00
|
|
|
entry::entry(const string_type& v)
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
2004-01-07 01:48:02 +01:00
|
|
|
new(data) string_type(v);
|
|
|
|
m_type = string_t;
|
2003-10-23 01:00:57 +02:00
|
|
|
}
|
|
|
|
|
2004-01-07 01:48:02 +01:00
|
|
|
entry::entry(const list_type& v)
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
2004-01-07 01:48:02 +01:00
|
|
|
new(data) list_type(v);
|
|
|
|
m_type = list_t;
|
2003-10-23 01:00:57 +02:00
|
|
|
}
|
|
|
|
|
2004-01-07 01:48:02 +01:00
|
|
|
entry::entry(const integer_type& v)
|
|
|
|
{
|
|
|
|
new(data) integer_type(v);
|
|
|
|
m_type = int_t;
|
|
|
|
}
|
|
|
|
|
|
|
|
void entry::operator=(const dictionary_type& v)
|
|
|
|
{
|
|
|
|
destruct();
|
|
|
|
new(data) dictionary_type(v);
|
|
|
|
m_type = dictionary_t;
|
|
|
|
}
|
|
|
|
|
|
|
|
void entry::operator=(const string_type& v)
|
|
|
|
{
|
|
|
|
destruct();
|
|
|
|
new(data) string_type(v);
|
|
|
|
m_type = string_t;
|
|
|
|
}
|
|
|
|
|
|
|
|
void entry::operator=(const list_type& v)
|
|
|
|
{
|
|
|
|
destruct();
|
|
|
|
new(data) list_type(v);
|
|
|
|
m_type = list_t;
|
|
|
|
}
|
|
|
|
|
|
|
|
void entry::operator=(const integer_type& v)
|
|
|
|
{
|
|
|
|
destruct();
|
|
|
|
new(data) integer_type(v);
|
|
|
|
m_type = int_t;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void entry::construct(data_type t)
|
|
|
|
{
|
|
|
|
m_type = t;
|
|
|
|
switch(m_type)
|
|
|
|
{
|
|
|
|
case int_t:
|
|
|
|
new(data) integer_type;
|
|
|
|
break;
|
|
|
|
case string_t:
|
|
|
|
new(data) string_type;
|
|
|
|
break;
|
|
|
|
case list_t:
|
|
|
|
new(data) list_type;
|
|
|
|
break;
|
|
|
|
case dictionary_t:
|
|
|
|
new (data) dictionary_type;
|
|
|
|
break;
|
|
|
|
default:
|
2004-01-12 04:05:10 +01:00
|
|
|
assert(m_type == undefined_t);
|
2004-01-07 01:48:02 +01:00
|
|
|
m_type = undefined_t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void entry::copy(const entry& e)
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
2004-01-07 01:48:02 +01:00
|
|
|
m_type = e.m_type;
|
|
|
|
switch(m_type)
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
2004-01-07 01:48:02 +01:00
|
|
|
case int_t:
|
|
|
|
new(data) integer_type(e.integer());
|
|
|
|
break;
|
|
|
|
case string_t:
|
|
|
|
new(data) string_type(e.string());
|
|
|
|
break;
|
|
|
|
case list_t:
|
|
|
|
new(data) list_type(e.list());
|
|
|
|
break;
|
|
|
|
case dictionary_t:
|
|
|
|
new (data) dictionary_type(e.dict());
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
m_type = undefined_t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void entry::destruct()
|
|
|
|
{
|
|
|
|
switch(m_type)
|
|
|
|
{
|
|
|
|
case int_t:
|
|
|
|
call_destructor(reinterpret_cast<integer_type*>(data));
|
|
|
|
break;
|
|
|
|
case string_t:
|
|
|
|
call_destructor(reinterpret_cast<string_type*>(data));
|
|
|
|
break;
|
|
|
|
case list_t:
|
|
|
|
call_destructor(reinterpret_cast<list_type*>(data));
|
|
|
|
break;
|
|
|
|
case dictionary_t:
|
|
|
|
call_destructor(reinterpret_cast<dictionary_type*>(data));
|
|
|
|
break;
|
|
|
|
default:
|
2004-01-12 04:05:10 +01:00
|
|
|
assert(m_type == undefined_t);
|
2004-01-07 01:48:02 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-10-13 17:36:44 +02:00
|
|
|
void entry::sort()
|
|
|
|
{
|
|
|
|
using boost::bind;
|
|
|
|
if (type() == dictionary_t)
|
|
|
|
{
|
|
|
|
std::stable_sort(dict().begin(), dict().end()
|
|
|
|
, bind(std::less<std::string>()
|
|
|
|
, bind(&entry::dictionary_type::value_type::first, _1)
|
|
|
|
, bind(&entry::dictionary_type::value_type::first, _2)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-01-07 01:48:02 +01:00
|
|
|
void entry::print(std::ostream& os, int indent) const
|
|
|
|
{
|
2004-01-25 23:41:55 +01:00
|
|
|
assert(indent >= 0);
|
2004-01-07 01:48:02 +01:00
|
|
|
for (int i = 0; i < indent; ++i) os << " ";
|
|
|
|
switch (m_type)
|
|
|
|
{
|
|
|
|
case int_t:
|
|
|
|
os << integer() << "\n";
|
|
|
|
break;
|
|
|
|
case string_t:
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
2004-01-07 01:48:02 +01:00
|
|
|
bool binary_string = false;
|
|
|
|
for (std::string::const_iterator i = string().begin(); i != string().end(); ++i)
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
2004-01-07 01:48:02 +01:00
|
|
|
if (!std::isprint(static_cast<unsigned char>(*i)))
|
|
|
|
{
|
|
|
|
binary_string = true;
|
|
|
|
break;
|
|
|
|
}
|
2003-10-23 01:00:57 +02:00
|
|
|
}
|
2004-01-07 01:48:02 +01:00
|
|
|
if (binary_string)
|
|
|
|
{
|
|
|
|
os.unsetf(std::ios_base::dec);
|
|
|
|
os.setf(std::ios_base::hex);
|
|
|
|
for (std::string::const_iterator i = string().begin(); i != string().end(); ++i)
|
|
|
|
os << static_cast<unsigned int>((unsigned char)*i);
|
|
|
|
os.unsetf(std::ios_base::hex);
|
|
|
|
os.setf(std::ios_base::dec);
|
|
|
|
os << "\n";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
os << string() << "\n";
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
case list_t:
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
2004-01-07 01:48:02 +01:00
|
|
|
os << "list\n";
|
|
|
|
for (list_type::const_iterator i = list().begin(); i != list().end(); ++i)
|
|
|
|
{
|
|
|
|
i->print(os, indent+1);
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
case dictionary_t:
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
2004-01-07 01:48:02 +01:00
|
|
|
os << "dictionary\n";
|
|
|
|
for (dictionary_type::const_iterator i = dict().begin(); i != dict().end(); ++i)
|
|
|
|
{
|
|
|
|
for (int j = 0; j < indent+1; ++j) os << " ";
|
|
|
|
os << "[" << i->first << "]";
|
|
|
|
if (i->second.type() != entry::string_t && i->second.type() != entry::int_t) os << "\n";
|
|
|
|
else os << " ";
|
|
|
|
i->second.print(os, indent+2);
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
default:
|
|
|
|
os << "<uninitialized>\n";
|
|
|
|
}
|
2003-10-23 01:00:57 +02:00
|
|
|
}
|
|
|
|
}
|