From 8c404cc5c1ae166faac67f8457ad0c9f541991a8 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Mon, 15 Nov 2010 05:10:36 +0000 Subject: [PATCH] optimized memory usage of torrent_info --- bindings/python/src/create_torrent.cpp | 18 ++++-- docs/make_torrent.rst | 14 +++++ docs/manual.rst | 73 +++++++++++++--------- examples/dump_torrent.cpp | 4 +- include/libtorrent/file_storage.hpp | 52 ++++++++++++++-- include/libtorrent/torrent_info.hpp | 27 +++++---- src/create_torrent.cpp | 12 ++-- src/file_storage.cpp | 21 ++++++- src/torrent.cpp | 2 +- src/torrent_info.cpp | 83 +++++++++++++++----------- 10 files changed, 211 insertions(+), 95 deletions(-) diff --git a/bindings/python/src/create_torrent.cpp b/bindings/python/src/create_torrent.cpp index 50f5e0853..9938b28a8 100644 --- a/bindings/python/src/create_torrent.cpp +++ b/bindings/python/src/create_torrent.cpp @@ -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") .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<>()) diff --git a/docs/make_torrent.rst b/docs/make_torrent.rst index 8875f12ea..68549d6ae 100644 --- a/docs/make_torrent.rst +++ b/docs/make_torrent.rst @@ -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 ============== diff --git a/docs/manual.rst b/docs/manual.rst index 08311d9e8..abefcd260 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -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 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 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() --------------------- diff --git a/examples/dump_torrent.cpp b/examples/dump_torrent.cpp index f922d4342..ceba6e02d 100644 --- a/examples/dump_torrent.cpp +++ b/examples/dump_torrent.cpp @@ -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; diff --git a/include/libtorrent/file_storage.hpp b/include/libtorrent/file_storage.hpp index 291c644db..9af262126 100644 --- a/include/libtorrent/file_storage.hpp +++ b/include/libtorrent/file_storage.hpp @@ -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 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 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 m_file_hashes; + + // for files that are symlinks, the symlink + // path_index in the file_entry indexes + // this vector of strings + std::vector m_symlinks; + + // name of torrent. For multi-file torrents + // this is always the root directory std::string m_name; // the sum of all filesizes diff --git a/include/libtorrent/torrent_info.hpp b/include/libtorrent/torrent_info.hpp index 7004e103c..c58058a13 100644 --- a/include/libtorrent/torrent_info.hpp +++ b/include/libtorrent/torrent_info.hpp @@ -225,22 +225,25 @@ namespace libtorrent class TORRENT_EXPORT torrent_info : public intrusive_ptr_base { 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 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; diff --git a/src/create_torrent.cpp b/src/create_torrent.cpp index 3d65c8b5f..dacd4fd95 100644 --- a/src/create_torrent.cpp +++ b/src/create_torrent.cpp @@ -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)); } diff --git a/src/file_storage.cpp b/src/file_storage.cpp index d4018f1df..edc3fbf5e 100644 --- a/src/file_storage.cpp +++ b/src/file_storage.cpp @@ -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) diff --git a/src/torrent.cpp b/src/torrent.cpp index 9494cb05e..b28022752 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -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 diff --git a/src/torrent_info.cpp b/src/torrent_info.cpp index da95be645..c3ed4555a 100644 --- a/src/torrent_info.cpp +++ b/src/torrent_info.cpp @@ -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 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