fixed torrent_info copy constructor. restricted copying of lazy_entry. Fixed build. added pascal_string type to be used with lazy_entry (trunk only)

This commit is contained in:
Arvid Norberg 2009-11-26 06:54:52 +00:00
parent 8dd244581d
commit a80b2b0fce
6 changed files with 93 additions and 24 deletions

View File

@ -90,6 +90,8 @@ namespace libtorrent
attribute_symlink = 8
};
void reserve(int num_files);
void add_file(file_entry const& e);
void add_file(std::string const& p, size_type size, int flags = 0
, std::time_t mtime = 0, std::string const& s_p = "");

View File

@ -145,6 +145,7 @@ namespace libtorrent
{ return const_cast<lazy_entry*>(this)->dict_find(name); }
std::string dict_find_string_value(char const* name) const;
pascal_string dict_find_pstr(char const* name) const;
size_type dict_find_int_value(char const* name, size_type default_val = 0) const;
lazy_entry const* dict_find_dict(char const* name) const;
lazy_entry const* dict_find_list(char const* name) const;
@ -187,6 +188,7 @@ namespace libtorrent
{ return const_cast<lazy_entry*>(this)->list_at(i); }
std::string list_string_value_at(int i) const;
pascal_string list_pstr_at(int i) const;
size_type list_int_value_at(int i, size_type default_val = 0) const;
int list_size() const

View File

@ -173,6 +173,7 @@ namespace libtorrent
#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);
@ -320,6 +321,9 @@ namespace libtorrent
private:
// not assignable
torrent_info const& operator=(torrent_info const&);
void copy_on_write();
bool parse_torrent_file(lazy_entry const& libtorrent, error_code& ec);

View File

@ -46,6 +46,11 @@ namespace libtorrent
, m_num_pieces(0)
{}
void file_storage::reserve(int num_files)
{
m_files.reserve(num_files);
}
int file_storage::piece_size(int index) const
{
TORRENT_ASSERT(index >= 0 && index < num_pieces());

View File

@ -49,7 +49,7 @@ namespace libtorrent
{
int fail_bdecode(lazy_entry& ret)
{
ret = lazy_entry();
ret.clear();
return -1;
}
@ -264,6 +264,13 @@ namespace libtorrent
return e->string_value();
}
pascal_string lazy_entry::dict_find_pstr(char const* name) const
{
lazy_entry const* e = dict_find(name);
if (e == 0 || e->type() != lazy_entry::string_t) return pascal_string(0, 0);
return e->string_pstr();
}
lazy_entry const* lazy_entry::dict_find_string(char const* name) const
{
lazy_entry const* e = dict_find(name);
@ -338,6 +345,13 @@ namespace libtorrent
return e->string_value();
}
pascal_string lazy_entry::list_pstr_at(int i) const
{
lazy_entry const* e = list_at(i);
if (e == 0 || e->type() != lazy_entry::string_t) return pascal_string(0, 0);
return e->string_pstr();
}
size_type lazy_entry::list_int_value_at(int i, size_type default_val) const
{
lazy_entry const* e = list_at(i);

View File

@ -303,14 +303,24 @@ namespace libtorrent
return true;
}
struct pascal_string
struct string_less_no_case
{
int len;
char const* ptr;
bool operator<(pascal_string const& rhs) const
bool operator()(std::string const& lhs, std::string const& rhs)
{
return memcmp(ptr, rhs.ptr, (std::min)(len, rhs.len)) < 0
|| len < rhs.len;
char c1, c2;
char const* s1 = lhs.c_str();
char const* s2 = rhs.c_str();
while (*s1 != 0 && *s2 != 0)
{
c1 = to_lower(*s1);
c2 = to_lower(*s2);
if (c1 < c2) return true;
if (c1 > c2) return false;
++s1;
++s2;
}
return false;
}
};
@ -318,29 +328,23 @@ namespace libtorrent
, std::string const& root_dir)
{
if (list.type() != lazy_entry::list_t) return false;
target.reserve(list.list_size());
for (int i = 0, end(list.list_size()); i < end; ++i)
{
file_entry e;
if (!extract_single_file(*list.list_at(i), e, root_dir))
return false;
int cnt = 0;
std::set<pascal_string> files;
pascal_string =
while (!files.insert(path).second)
for (file_storage::iterator k = target.begin()
, end(target.end()); k != end; ++k)
std::set<std::string, string_less_no_case> files;
// as long as we this file already exists
// increase the counter
while (!files.insert(e.path).second)
{
if (string_equal_no_case(e.path.c_str()
, k->path.c_str())) ++cnt;
}
if (cnt)
{
char suffix[15];
snprintf(suffix, sizeof(suffix), ".%d", cnt);
replace_extension(e.path, suffix + extension(e.path));
// TODO: we should really make sure that this new name
// doesn't already exist as well, otherwise we might
// just create another collision
++cnt;
char suffix[50];
snprintf(suffix, sizeof(suffix), ".%d%s", cnt, extension(e.path).c_str());
replace_extension(e.path, suffix);
}
target.add_file(e);
}
@ -403,6 +407,42 @@ namespace libtorrent
updating = false;
}
torrent_info::torrent_info(torrent_info const& t)
: m_files(t.m_files)
, m_orig_files(t.m_orig_files)
, m_urls(t.m_urls)
, m_url_seeds(t.m_url_seeds)
, m_http_seeds(t.m_http_seeds)
, m_nodes(t.m_nodes)
, m_info_hash(t.m_info_hash)
, m_creation_date(t.m_creation_date)
, m_comment(t.m_comment)
, m_created_by(t.m_created_by)
, m_multifile(t.m_multifile)
, m_private(t.m_private)
, m_i2p(t.m_i2p)
, m_info_section_size(t.m_info_section_size)
, m_piece_hashes(t.m_piece_hashes)
, m_merkle_tree(t.m_merkle_tree)
, m_merkle_first_leaf(t.m_merkle_first_leaf)
{
if (m_info_section_size > 0)
{
m_info_section.reset(new char[m_info_section_size]);
memcpy(m_info_section.get(), t.m_info_section.get(), m_info_section_size);
int ret = lazy_bdecode(m_info_section.get(), m_info_section.get()
+ m_info_section_size, m_info_dict);
lazy_entry const* pieces = m_info_dict.dict_find_string("pieces");
if (pieces && pieces->string_length() == m_files.num_pieces() * 20)
{
m_piece_hashes = m_info_section.get() + (pieces->string_ptr() - m_info_section.get());
TORRENT_ASSERT(m_piece_hashes >= m_info_section.get());
TORRENT_ASSERT(m_piece_hashes < m_info_section.get() + m_info_section_size);
}
}
}
#ifndef TORRENT_NO_DEPRECATE
// standard constructor that parses a torrent file
torrent_info::torrent_info(entry const& torrent_file)
@ -638,7 +678,9 @@ namespace libtorrent
swap(m_info_section, ti.m_info_section);
swap(m_info_section_size, ti.m_info_section_size);
swap(m_piece_hashes, ti.m_piece_hashes);
swap(m_info_dict, ti.m_info_dict);
m_info_dict.swap(ti.m_info_dict);
swap(m_merkle_tree, ti.m_merkle_tree);
swap(m_merkle_first_leaf, ti.m_merkle_first_leaf);
}
bool torrent_info::parse_info_section(lazy_entry const& info, error_code& ec)