optimized memory usage of torrent_info

This commit is contained in:
Arvid Norberg 2010-11-15 05:10:36 +00:00
parent 79f6b5856b
commit 8c404cc5c1
10 changed files with 211 additions and 95 deletions

View File

@ -47,14 +47,20 @@ namespace
{
ct.add_node(std::make_pair(addr, port));
}
void add_file(file_storage& ct, file_entry const& fe
, std::string const& hash, std::string const& linkpath)
{
ct.add_file(fe, hash.empty() ? 0 : &sha1_hash(hash)
, linkpath.empty() ? 0 : &linkpath);
}
}
void bind_create_torrent()
{
void (file_storage::*add_file0)(file_entry const&) = &file_storage::add_file;
void (file_storage::*add_file1)(std::string const&, size_type, int, std::time_t, std::string const&) = &file_storage::add_file;
void (file_storage::*add_file0)(std::string const&, size_type, int, std::time_t, std::string const&) = &file_storage::add_file;
#if TORRENT_USE_WSTRING
void (file_storage::*add_file2)(std::wstring const&, size_type, int, std::time_t, std::string const&) = &file_storage::add_file;
void (file_storage::*add_file1)(std::wstring const&, size_type, int, std::time_t, std::string const&) = &file_storage::add_file;
#endif
void (file_storage::*set_name0)(std::string const&) = &file_storage::set_name;
@ -69,10 +75,10 @@ void bind_create_torrent()
class_<file_storage>("file_storage")
.def("is_valid", &file_storage::is_valid)
.def("add_file", add_file0)
.def("add_file", add_file1, (arg("path"), arg("size"), arg("flags") = 0, arg("mtime") = 0, arg("linkpath") = ""))
.def("add_file", add_file, (arg("entry"), arg("hash") = std::string(), arg("symlink") = std::string()))
.def("add_file", add_file0, (arg("path"), arg("size"), arg("flags") = 0, arg("mtime") = 0, arg("linkpath") = ""))
#if TORRENT_USE_WSTRING
.def("add_file", add_file2, (arg("path"), arg("size"), arg("flags") = 0, arg("mtime") = 0, arg("linkpath") = ""))
.def("add_file", add_file1, (arg("path"), arg("size"), arg("flags") = 0, arg("mtime") = 0, arg("linkpath") = ""))
#endif
.def("num_files", &file_storage::num_files)
.def("at", &file_storage::at, return_internal_reference<>())

View File

@ -172,6 +172,9 @@ file structure. Its synopsis::
int piece_length() const;
int piece_size(int index) const;
sha1_hash const& hash(int index) const;
std::string const& symlink(int index) const;
void set_name(std::string const& n);
void set_name(std::wstring const& n);
const std::string& name() const;
@ -215,6 +218,17 @@ can be changed by calling ``set_name``.
The built in functions to traverse a directory to add files will
make sure this requirement is fulfilled.
hash() symlink()
----------------
::
sha1_hash const& hash(int index) const;
std::string const& symlink(int index) const;
These functions are used to resolve the symlink index and file hash
index in ``file_entry``.
create_torrent
==============

View File

@ -1345,19 +1345,22 @@ The ``torrent_info`` has the following synopsis::
{
public:
// flags for torrent_info constructor
enum flags_t { ommit_filehashes = 1 };
// these constructors throws exceptions on error
torrent_info(sha1_hash const& info_hash);
torrent_info(lazy_entry const& torrent_file);
torrent_info(char const* buffer, int size);
torrent_info(boost::filesystem::path const& filename);
torrent_info(boost::filesystem::wpath const& filename);
torrent_info(sha1_hash const& info_hash, int flags = 0);
torrent_info(lazy_entry const& torrent_file, int flags = 0);
torrent_info(char const* buffer, int size, int flags = 0);
torrent_info(boost::filesystem::path const& filename, int flags = 0);
torrent_info(boost::filesystem::wpath const& filename, int flags = 0);
// these constructors sets the error code on error
torrent_info(sha1_hash const& info_hash, error_code& ec);
torrent_info(lazy_entry const& torrent_file, error_code& ec);
torrent_info(char const* buffer, int size, error_code& ec);
torrent_info(fs::path const& filename, error_code& ec);
torrent_info(fs::wpath const& filename, error_code& ec);
torrent_info(sha1_hash const& info_hash, error_code& ec, int flags = 0);
torrent_info(lazy_entry const& torrent_file, error_code& ec, int flags = 0);
torrent_info(char const* buffer, int size, error_code& ec, int flags = 0);
torrent_info(fs::path const& filename, error_code& ec, int flags = 0);
torrent_info(fs::wpath const& filename, error_code& ec, int flags = 0);
void add_tracker(std::string const& url, int tier = 0);
std::vector<announce_entry> const& trackers() const;
@ -1418,17 +1421,17 @@ torrent_info()
::
torrent_info(sha1_hash const& info_hash);
torrent_info(lazy_entry const& torrent_file);
torrent_info(char const* buffer, int size);
torrent_info(boost::filesystem::path const& filename);
torrent_info(boost::filesystem::wpath const& filename);
torrent_info(sha1_hash const& info_hash, int flags = 0);
torrent_info(lazy_entry const& torrent_file, int flags = 0);
torrent_info(char const* buffer, int size, int flags = 0);
torrent_info(boost::filesystem::path const& filename, int flags = 0);
torrent_info(boost::filesystem::wpath const& filename, int flags = 0);
torrent_info(sha1_hash const& info_hash, error_code& ec);
torrent_info(lazy_entry const& torrent_file, error_code& ec);
torrent_info(char const* buffer, int size, error_code& ec);
torrent_info(fs::path const& filename, error_code& ec);
torrent_info(fs::wpath const& filename, error_code& ec);
torrent_info(sha1_hash const& info_hash, error_code& ec, int flags = 0);
torrent_info(lazy_entry const& torrent_file, error_code& ec, int flags = 0);
torrent_info(char const* buffer, int size, error_code& ec, int flags = 0);
torrent_info(fs::path const& filename, error_code& ec, int flags = 0);
torrent_info(fs::wpath const& filename, error_code& ec, int flags = 0);
The constructor that takes an info-hash will initialize the info-hash to the given value,
but leave all other fields empty. This is used internally when downloading torrents without
@ -1453,6 +1456,11 @@ torrent_info object. The overloads that do not take the extra error_code_ parame
always throw if an error occurs. These overloads are not available when building without
exception support.
The ``flags`` argument can be used to disable loading of potentially unnecessary hashes
for individual files (if included in the torrent file). This is especially useful if
you're loading torrents with thousands of files on a memory constrained system. If so,
pass in ``torrent_info::ommit_filehashes`` as the flags argument.
add_tracker()
-------------
@ -1534,12 +1542,13 @@ iterators with the type ``file_entry``.
struct file_entry
{
boost::filesystem::path path;
std::string path;
size_type offset;
size_type size;
size_type file_base;
std::string symlink_path;
boost::shared_ptr<sha1_hash> filehash;
time_t mtime;
int symlink_index;
int filehash_index;
bool pad_file:1;
bool hidden_attribute:1;
bool executable_attribute:1;
@ -1561,6 +1570,17 @@ the ``file_base`` should be set to an offset so that the different regions do
not overlap. This is used when mapping "unselected" files into a so-called part
file.
``mtime`` is the modification time of this file specified in posix time.
``symlink_index`` is an index into an array of paths in ``file_storage``, or
-1 if this file is not a symlink. This field is only used if the ``symlink_attribute``
is set. To resolve the symlink, call ``file_storage::symlink(e.symlink_index)``.
``filehash_index`` is an index into an array of sha-1 hashes in ``file_storage``, or
-1 if this file doesn't have a hash specified. The hash is the hash of the actual
content of the file, and can be used to potentially find alternative sources for it.
To resolve the hash, use ``file_storage::hash(e.filehash_index)``.
``pad_file`` is set to true for files that are not part of the data of the torrent.
They are just there to make sure the next file is aligned to a particular byte offset
or piece boundry. These files should typically be hidden from an end user. They are
@ -1571,11 +1591,8 @@ not written to disk.
``executable_attribute`` is true if the file was marked as executable (posix)
``symlink_attribute`` is true if the file was a symlink. If this is the case
the ``symlink_path`` specifies the original location where the data for this file
was found.
``filehash`` is a pointer that is set in case the torrent file included a sha1 hash
for this file. This may be use to look up more sources for this file on other networks.
the ``symlink_index`` refers to a string which specifies the original location
where the data for this file was found.
num_files() file_at()
---------------------

View File

@ -127,10 +127,10 @@ int main(int argc, char* argv[])
, (i->hidden_attribute?'h':'-')
, (i->symlink_attribute?'l':'-')
, first, last
, i->filehash ? to_hex(i->filehash->to_string()).c_str() : ""
, i->filehash_index != -1 ? to_hex(t.files().hash(i->filehash_index).to_string()).c_str() : ""
, i->path.c_str()
, i->symlink_attribute ? "-> ": ""
, i->symlink_attribute ? i->symlink_path.c_str() : "");
, i->symlink_attribute && i->symlink_index != -1 ? t.files().symlink(i->symlink_index).c_str() : "");
}
return 0;

View File

@ -49,15 +49,21 @@ namespace libtorrent
struct TORRENT_EXPORT file_entry
{
file_entry(): offset(0), size(0), file_base(0), file_index(0)
, mtime(0), pad_file(false), hidden_attribute(false)
file_entry()
: offset(0)
, size(0)
, file_base(0)
, mtime(0)
, file_index(0)
, filehash_index(-1)
, symlink_index(-1)
, pad_file(false)
, hidden_attribute(false)
, executable_attribute(false)
, symlink_attribute(false)
{}
std::string path;
std::string symlink_path;
copy_ptr<sha1_hash> filehash;
// the offset of this file inside the torrent
size_type offset;
// the size of this file
@ -66,9 +72,16 @@ namespace libtorrent
// This is always 0 unless parts of the torrent is
// compressed into a single file, such as a so-called part file.
size_type file_base;
// modification time
time_t mtime;
// the index of this file, as ordered in the torrent
int file_index;
time_t mtime;
// index into file_storage::m_file_hashes or -1
// if this file does not have a hash
int filehash_index;
// index into file_storage::m_symlinks or -1
// if this is not a symlink
int symlink_index;
bool pad_file:1;
bool hidden_attribute:1;
bool executable_attribute:1;
@ -101,7 +114,9 @@ namespace libtorrent
void reserve(int num_files);
void add_file(file_entry const& e);
void add_file(file_entry const& e, sha1_hash const* filehash = 0
, std::string const* symlink = 0);
void add_file(std::string const& p, size_type size, int flags = 0
, std::time_t mtime = 0, std::string const& s_p = "");
void rename_file(int index, std::string const& new_filename);
@ -133,7 +148,19 @@ namespace libtorrent
TORRENT_ASSERT(index >= 0 && index < int(m_files.size()));
return m_files[index];
}
sha1_hash const& hash(int index) const
{
TORRENT_ASSERT(index >= 0 && index < int(m_file_hashes.size()));
return m_file_hashes[index];
}
std::string const& symlink(int index) const
{
TORRENT_ASSERT(index >= 0 && index < int(m_symlinks.size()));
return m_symlinks[index];
}
size_type total_size() const { return m_total_size; }
void set_num_pieces(int n) { m_num_pieces = n; }
int num_pieces() const { TORRENT_ASSERT(m_piece_length > 0); return m_num_pieces; }
@ -160,9 +187,22 @@ namespace libtorrent
void optimize(int pad_file_limit = -1);
private:
// the list of files that this torrent consists of
std::vector<file_entry> m_files;
// if there are sha1 hashes for each individual file
// each file_entry has an index into this vector
// and the actual hashes are in here
std::vector<sha1_hash> m_file_hashes;
// for files that are symlinks, the symlink
// path_index in the file_entry indexes
// this vector of strings
std::vector<std::string> m_symlinks;
// name of torrent. For multi-file torrents
// this is always the root directory
std::string m_name;
// the sum of all filesizes

View File

@ -225,22 +225,25 @@ namespace libtorrent
class TORRENT_EXPORT torrent_info : public intrusive_ptr_base<torrent_info>
{
public:
enum flags_t { ommit_filehashes = 1 };
#ifndef BOOST_NO_EXCEPTIONS
torrent_info(lazy_entry const& torrent_file);
torrent_info(char const* buffer, int size);
torrent_info(std::string const& filename);
torrent_info(lazy_entry const& torrent_file, int flags = 0);
torrent_info(char const* buffer, int size, int flags = 0);
torrent_info(std::string const& filename, int flags = 0);
#if TORRENT_USE_WSTRING
torrent_info(std::wstring const& filename);
torrent_info(std::wstring const& filename, int flags = 0);
#endif // TORRENT_USE_WSTRING
#endif
torrent_info(torrent_info const& t);
torrent_info(sha1_hash const& info_hash);
torrent_info(lazy_entry const& torrent_file, error_code& ec);
torrent_info(char const* buffer, int size, error_code& ec);
torrent_info(std::string const& filename, error_code& ec);
torrent_info(torrent_info const& t, int flags = 0);
torrent_info(sha1_hash const& info_hash, int flags = 0);
torrent_info(lazy_entry const& torrent_file, error_code& ec, int flags = 0);
torrent_info(char const* buffer, int size, error_code& ec, int flags = 0);
torrent_info(std::string const& filename, error_code& ec, int flags = 0);
#if TORRENT_USE_WSTRING
torrent_info(std::wstring const& filename, error_code& ec);
torrent_info(std::wstring const& filename, error_code& ec, int flags = 0);
#endif // TORRENT_USE_WSTRING
~torrent_info();
@ -369,7 +372,7 @@ namespace libtorrent
void add_node(std::pair<std::string, int> const& node)
{ m_nodes.push_back(node); }
bool parse_info_section(lazy_entry const& e, error_code& ex);
bool parse_info_section(lazy_entry const& e, error_code& ec, int flags);
lazy_entry const* info(char const* key) const
{
@ -406,7 +409,7 @@ namespace libtorrent
torrent_info const& operator=(torrent_info const&);
void copy_on_write();
bool parse_torrent_file(lazy_entry const& libtorrent, error_code& ec);
bool parse_torrent_file(lazy_entry const& libtorrent, error_code& ec, int flags);
file_storage m_files;

View File

@ -314,11 +314,13 @@ namespace libtorrent
if (m_files.at(0).executable_attribute) attr += 'x';
if (m_include_symlinks && m_files.at(0).symlink_attribute) attr += 'l';
}
if (m_include_symlinks && m_files.at(0).symlink_attribute)
if (m_include_symlinks
&& m_files.at(0).symlink_attribute
&& m_files.at(0).symlink_index != -1)
{
entry& sympath_e = info["symlink path"];
std::string split = split_path(m_files.at(0).symlink_path);
std::string split = split_path(m_files.symlink(m_files.at(0).symlink_index));
for (char const* e = split.c_str(); e != 0; e = next_path_element(e))
sympath_e.list().push_back(entry(e));
}
@ -362,11 +364,13 @@ namespace libtorrent
if (i->executable_attribute) attr += 'x';
if (m_include_symlinks && i->symlink_attribute) attr += 'l';
}
if (m_include_symlinks && i->symlink_attribute)
if (m_include_symlinks
&& i->symlink_attribute
&& i->symlink_index != -1)
{
entry& sympath_e = file_e["symlink path"];
std::string split = split_path(i->symlink_path);
std::string split = split_path(m_files.symlink(i->symlink_index));
for (char const* e = split.c_str(); e != 0; e = next_path_element(e))
sympath_e.list().push_back(entry(e));
}

View File

@ -204,12 +204,18 @@ namespace libtorrent
e.hidden_attribute = (flags & attribute_hidden) != 0;
e.executable_attribute = (flags & attribute_executable) != 0;
e.symlink_attribute = (flags & attribute_symlink) != 0;
if (e.symlink_attribute) e.symlink_path = symlink_path;
if (e.symlink_attribute)
{
e.symlink_index = m_symlinks.size();
m_symlinks.push_back(symlink_path);
}
e.mtime = mtime;
m_total_size += size;
}
void file_storage::add_file(file_entry const& ent)
void file_storage::add_file(file_entry const& ent, sha1_hash const* filehash
, std::string const* symlink)
{
if (!has_parent_path(ent.path))
{
@ -230,6 +236,17 @@ namespace libtorrent
e.offset = m_total_size;
e.file_index = m_files.size() - 1;
m_total_size += ent.size;
if (filehash)
{
e.filehash_index = m_file_hashes.size();
m_file_hashes.push_back(*filehash);
}
if (symlink)
{
e.symlink_index = m_symlinks.size();
m_symlinks.push_back(*symlink);
}
}
void file_storage::optimize(int pad_file_limit)

View File

@ -4486,7 +4486,7 @@ namespace libtorrent
lazy_entry metadata;
error_code ec;
int ret = lazy_bdecode(metadata_buf, metadata_buf + metadata_size, metadata, ec);
if (ret != 0 || !m_torrent_file->parse_info_section(metadata, ec))
if (ret != 0 || !m_torrent_file->parse_info_section(metadata, ec, 0))
{
// this means the metadata is correct, since we
// verified it against the info-hash, but we

View File

@ -233,7 +233,7 @@ namespace libtorrent
}
bool extract_single_file(lazy_entry const& dict, file_entry& target
, std::string const& root_dir)
, std::string const& root_dir, sha1_hash* filehash, std::string* symlink)
{
if (dict.type() != lazy_entry::dict_t) return false;
lazy_entry const* length = dict.dict_find("length");
@ -287,21 +287,24 @@ namespace libtorrent
}
lazy_entry const* fh = dict.dict_find_string("sha1");
if (fh && fh->string_length() == 20)
if (fh && fh->string_length() == 20 && filehash)
{
target.filehash.reset(new sha1_hash);
std::memcpy(&(*target.filehash)[0], fh->string_ptr(), 20);
std::memcpy(&(*filehash)[0], fh->string_ptr(), 20);
// indicate that the file has a filehash
target.filehash_index = 0;
}
lazy_entry const* s_p = dict.dict_find("symlink path");
if (s_p != 0 && s_p->type() == lazy_entry::list_t)
if (s_p != 0 && s_p->type() == lazy_entry::list_t && symlink)
{
for (int i = 0, end(s_p->list_size()); i < end; ++i)
{
std::string path_element = s_p->list_at(i)->string_value();
trim_path_element(path_element);
target.symlink_path = combine_path(target.symlink_path, path_element);
*symlink = combine_path(*symlink, path_element);
}
// indeicate that we have a symlink
target.symlink_index = 0;
}
return true;
@ -335,9 +338,15 @@ namespace libtorrent
target.reserve(list.list_size());
for (int i = 0, end(list.list_size()); i < end; ++i)
{
sha1_hash file_hash;
std::string symlink;
file_entry e;
if (!extract_single_file(*list.list_at(i), e, root_dir))
if (!extract_single_file(*list.list_at(i), e, root_dir, &file_hash, &symlink))
return false;
// TODO: this logic should be a separate step
// done once the torrent is loaded, and the original
// filenames should be preserved!
int cnt = 0;
std::set<std::string, string_less_no_case> files;
@ -350,7 +359,8 @@ namespace libtorrent
snprintf(suffix, sizeof(suffix), ".%d%s", cnt, extension(e.path).c_str());
replace_extension(e.path, suffix);
}
target.add_file(e);
target.add_file(e, e.filehash_index != -1 ? &file_hash : 0
, e.symlink_index != -1 ? &symlink : 0);
}
return true;
}
@ -436,7 +446,7 @@ namespace libtorrent
url.erase(url.begin());
}
torrent_info::torrent_info(torrent_info const& t)
torrent_info::torrent_info(torrent_info const& t, int flags)
: m_files(t.m_files)
, m_orig_files(t.m_orig_files)
, m_urls(t.m_urls)
@ -508,7 +518,7 @@ namespace libtorrent
return;
}
#ifndef BOOST_NO_EXCEPTIONS
if (!parse_torrent_file(e, ec))
if (!parse_torrent_file(e, ec, 0))
throw invalid_torrent_file(ec);
#else
parse_torrent_file(e, ec);
@ -517,7 +527,7 @@ namespace libtorrent
#endif
#ifndef BOOST_NO_EXCEPTIONS
torrent_info::torrent_info(lazy_entry const& torrent_file)
torrent_info::torrent_info(lazy_entry const& torrent_file, int flags)
: m_piece_hashes(0)
, m_creation_date(0)
, m_merkle_first_leaf(0)
@ -527,11 +537,11 @@ namespace libtorrent
, m_i2p(false)
{
error_code ec;
if (!parse_torrent_file(torrent_file, ec))
if (!parse_torrent_file(torrent_file, ec, flags))
throw invalid_torrent_file(ec);
}
torrent_info::torrent_info(char const* buffer, int size)
torrent_info::torrent_info(char const* buffer, int size, int flags)
: m_piece_hashes(0)
, m_creation_date(0)
, m_merkle_first_leaf(0)
@ -545,11 +555,11 @@ namespace libtorrent
if (lazy_bdecode(buffer, buffer + size, e, ec) != 0)
throw invalid_torrent_file(ec);
if (!parse_torrent_file(e, ec))
if (!parse_torrent_file(e, ec, flags))
throw invalid_torrent_file(ec);
}
torrent_info::torrent_info(std::string const& filename)
torrent_info::torrent_info(std::string const& filename, int flags)
: m_piece_hashes(0)
, m_creation_date(0)
, m_info_section_size(0)
@ -566,12 +576,12 @@ namespace libtorrent
if (buf.size() == 0 || lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec) != 0)
throw invalid_torrent_file(ec);
if (!parse_torrent_file(e, ec))
if (!parse_torrent_file(e, ec, flags))
throw invalid_torrent_file(ec);
}
#if TORRENT_USE_WSTRING
torrent_info::torrent_info(std::wstring const& filename)
torrent_info::torrent_info(std::wstring const& filename, int flags)
: m_piece_hashes(0)
, m_creation_date(0)
, m_merkle_first_leaf(0)
@ -591,13 +601,13 @@ namespace libtorrent
if (buf.size() == 0 || lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec) != 0)
throw invalid_torrent_file(ec);
if (!parse_torrent_file(e, ec))
if (!parse_torrent_file(e, ec, flags))
throw invalid_torrent_file(ec);
}
#endif
#endif
torrent_info::torrent_info(lazy_entry const& torrent_file, error_code& ec)
torrent_info::torrent_info(lazy_entry const& torrent_file, error_code& ec, int flags)
: m_piece_hashes(0)
, m_creation_date(0)
, m_info_section_size(0)
@ -605,10 +615,10 @@ namespace libtorrent
, m_private(false)
, m_i2p(false)
{
parse_torrent_file(torrent_file, ec);
parse_torrent_file(torrent_file, ec, flags);
}
torrent_info::torrent_info(char const* buffer, int size, error_code& ec)
torrent_info::torrent_info(char const* buffer, int size, error_code& ec, int flags)
: m_piece_hashes(0)
, m_creation_date(0)
, m_merkle_first_leaf(0)
@ -620,10 +630,10 @@ namespace libtorrent
lazy_entry e;
if (lazy_bdecode(buffer, buffer + size, e, ec) != 0)
return;
parse_torrent_file(e, ec);
parse_torrent_file(e, ec, flags);
}
torrent_info::torrent_info(std::string const& filename, error_code& ec)
torrent_info::torrent_info(std::string const& filename, error_code& ec, int flags)
: m_piece_hashes(0)
, m_creation_date(0)
, m_info_section_size(0)
@ -638,11 +648,11 @@ namespace libtorrent
lazy_entry e;
if (buf.size() == 0 || lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec) != 0)
return;
parse_torrent_file(e, ec);
parse_torrent_file(e, ec, flags);
}
#if TORRENT_USE_WSTRING
torrent_info::torrent_info(std::wstring const& filename, error_code& ec)
torrent_info::torrent_info(std::wstring const& filename, error_code& ec, int flags)
: m_piece_hashes(0)
, m_creation_date(0)
, m_info_section_size(0)
@ -659,7 +669,7 @@ namespace libtorrent
lazy_entry e;
if (buf.size() == 0 || lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec) != 0)
return;
parse_torrent_file(e, ec);
parse_torrent_file(e, ec, flags);
}
#endif
@ -667,7 +677,7 @@ namespace libtorrent
// will not contain any hashes, comments, creation date
// just the necessary to use it with piece manager
// used for torrents with no metadata
torrent_info::torrent_info(sha1_hash const& info_hash)
torrent_info::torrent_info(sha1_hash const& info_hash, int flags)
: m_piece_hashes(0)
, m_creation_date(time(0))
, m_info_hash(info_hash)
@ -717,7 +727,7 @@ namespace libtorrent
#undef SWAP
bool torrent_info::parse_info_section(lazy_entry const& info, error_code& ec)
bool torrent_info::parse_info_section(lazy_entry const& info, error_code& ec, int flags)
{
if (info.type() != lazy_entry::dict_t)
{
@ -796,20 +806,23 @@ namespace libtorrent
}
lazy_entry const* s_p = info.dict_find("symlink path");
std::string symlink;
if (s_p != 0 && s_p->type() == lazy_entry::list_t)
{
for (int i = 0, end(s_p->list_size()); i < end; ++i)
{
std::string path_element = s_p->list_at(i)->string_value();
trim_path_element(path_element);
e.symlink_path = combine_path(e.symlink_path, path_element);
symlink = combine_path(symlink, path_element);
}
e.symlink_index = 0;
}
lazy_entry const* fh = info.dict_find_string("sha1");
sha1_hash filehash;
if (fh && fh->string_length() == 20)
{
e.filehash.reset(new sha1_hash);
std::memcpy(&(*e.filehash)[0], fh->string_ptr(), 20);
std::memcpy(&filehash[0], fh->string_ptr(), 20);
e.filehash_index = 0;
}
// bitcomet pad file
@ -820,7 +833,9 @@ namespace libtorrent
ec = errors::torrent_invalid_length;
return false;
}
m_files.add_file(e);
bool ommit_hash = (flags & torrent_info::ommit_filehashes) || e.filehash_index == -1;
m_files.add_file(e, ommit_hash ? 0 : &filehash
, e.symlink_index != -1 ? &symlink : 0);
m_multifile = false;
}
else
@ -965,7 +980,7 @@ namespace libtorrent
}
#endif
bool torrent_info::parse_torrent_file(lazy_entry const& torrent_file, error_code& ec)
bool torrent_info::parse_torrent_file(lazy_entry const& torrent_file, error_code& ec, int flags)
{
if (torrent_file.type() != lazy_entry::dict_t)
{
@ -1103,7 +1118,7 @@ namespace libtorrent
ec = errors::torrent_missing_info;
return false;
}
return parse_info_section(*info, ec);
return parse_info_section(*info, ec, flags);
}
boost::optional<time_t>