refactor: use std::string in tr_file (#2382)
This commit is contained in:
parent
0c16c454ba
commit
8b65b660c8
|
@ -53,9 +53,12 @@ void tr_file_piece_map::reset(tr_block_info const& block_info, uint64_t const* f
|
||||||
|
|
||||||
void tr_file_piece_map::reset(tr_info const& info)
|
void tr_file_piece_map::reset(tr_info const& info)
|
||||||
{
|
{
|
||||||
tr_file_index_t const n = info.fileCount;
|
auto const n = info.fileCount();
|
||||||
auto file_sizes = std::vector<uint64_t>(n);
|
auto file_sizes = std::vector<uint64_t>(n);
|
||||||
std::transform(info.files, info.files + n, std::begin(file_sizes), [](tr_file const& file) { return file.length; });
|
for (tr_file_index_t i = 0; i < n; ++i)
|
||||||
|
{
|
||||||
|
file_sizes[i] = info.fileSize(i);
|
||||||
|
}
|
||||||
reset({ info.totalSize, info.pieceSize }, std::data(file_sizes), std::size(file_sizes));
|
reset({ info.totalSize, info.pieceSize }, std::data(file_sizes), std::size(file_sizes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,7 @@ static int readOrWriteBytes(
|
||||||
if (!tr_sys_file_read_at(fd, buf, buflen, file_offset, nullptr, &error))
|
if (!tr_sys_file_read_at(fd, buf, buflen, file_offset, nullptr, &error))
|
||||||
{
|
{
|
||||||
err = error->code;
|
err = error->code;
|
||||||
tr_logAddTorErr(tor, "read failed for \"%s\": %s", tor->fileSubpath(file_index), error->message);
|
tr_logAddTorErr(tor, "read failed for \"%s\": %s", tor->fileSubpath(file_index).c_str(), error->message);
|
||||||
tr_error_free(error);
|
tr_error_free(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ static int readOrWriteBytes(
|
||||||
if (!tr_sys_file_write_at(fd, buf, buflen, file_offset, nullptr, &error))
|
if (!tr_sys_file_write_at(fd, buf, buflen, file_offset, nullptr, &error))
|
||||||
{
|
{
|
||||||
err = error->code;
|
err = error->code;
|
||||||
tr_logAddTorErr(tor, "write failed for \"%s\": %s", tor->fileSubpath(file_index), error->message);
|
tr_logAddTorErr(tor, "write failed for \"%s\": %s", tor->fileSubpath(file_index).c_str(), error->message);
|
||||||
tr_error_free(error);
|
tr_error_free(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,11 +110,11 @@ bool tr_metainfoAppendSanitizedPathComponent(std::string& out, std::string_view
|
||||||
return std::size(out) > original_out_len;
|
return std::size(out) > original_out_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool getfile(char** setme, std::string_view root, tr_variant* path, std::string& buf)
|
static bool getfile(std::string* setme, std::string_view root, tr_variant* path, std::string& buf)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
*setme = nullptr;
|
setme->clear();
|
||||||
|
|
||||||
if (tr_variantIsList(path))
|
if (tr_variantIsList(path))
|
||||||
{
|
{
|
||||||
|
@ -148,7 +148,7 @@ static bool getfile(char** setme, std::string_view root, tr_variant* path, std::
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
*setme = tr_utf8clean(buf);
|
*setme = tr_strvUtf8Clean(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
|
@ -173,10 +173,9 @@ static char const* parseFiles(tr_info* inf, tr_variant* files, tr_variant const*
|
||||||
errstr = nullptr;
|
errstr = nullptr;
|
||||||
|
|
||||||
inf->isFolder = true;
|
inf->isFolder = true;
|
||||||
inf->fileCount = tr_variantListSize(files);
|
tr_file_index_t const n = tr_variantListSize(files);
|
||||||
inf->files = tr_new0(tr_file, inf->fileCount);
|
inf->files.resize(n);
|
||||||
|
for (tr_file_index_t i = 0; i < n; ++i)
|
||||||
for (tr_file_index_t i = 0; i < inf->fileCount; i++)
|
|
||||||
{
|
{
|
||||||
auto* const file = tr_variantListChild(files, i);
|
auto* const file = tr_variantListChild(files, i);
|
||||||
|
|
||||||
|
@ -193,7 +192,7 @@ static char const* parseFiles(tr_info* inf, tr_variant* files, tr_variant const*
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!getfile(&inf->files[i].name, root_name, path, buf))
|
if (!getfile(&inf->files[i].subpath, root_name, path, buf))
|
||||||
{
|
{
|
||||||
errstr = "path";
|
errstr = "path";
|
||||||
break;
|
break;
|
||||||
|
@ -205,17 +204,16 @@ static char const* parseFiles(tr_info* inf, tr_variant* files, tr_variant const*
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
inf->files[i].length = len;
|
inf->files[i].size = len;
|
||||||
inf->totalSize += len;
|
inf->totalSize += len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tr_variantGetInt(length, &len)) /* single-file mode */
|
else if (tr_variantGetInt(length, &len)) /* single-file mode */
|
||||||
{
|
{
|
||||||
inf->isFolder = false;
|
inf->isFolder = false;
|
||||||
inf->fileCount = 1;
|
inf->files.resize(1);
|
||||||
inf->files = tr_new0(tr_file, 1);
|
inf->files[0].subpath = root_name;
|
||||||
inf->files[0].name = tr_strvDup(root_name);
|
inf->files[0].size = len;
|
||||||
inf->files[0].length = len;
|
|
||||||
inf->totalSize += len;
|
inf->totalSize += len;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -287,7 +285,7 @@ static char* fix_webseed_url(tr_info const* inf, std::string_view url)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inf->fileCount > 1 && !std::empty(url) && url.back() != '/')
|
if (inf->fileCount() > 1 && !std::empty(url) && url.back() != '/')
|
||||||
{
|
{
|
||||||
return tr_strvDup(tr_strvJoin(url, "/"sv));
|
return tr_strvDup(tr_strvJoin(url, "/"sv));
|
||||||
}
|
}
|
||||||
|
@ -500,7 +498,7 @@ static char const* tr_metainfoParseImpl(
|
||||||
return errstr;
|
return errstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inf->fileCount == 0 || inf->totalSize == 0)
|
if (inf->fileCount() == 0 || inf->totalSize == 0)
|
||||||
{
|
{
|
||||||
return "files";
|
return "files";
|
||||||
}
|
}
|
||||||
|
@ -553,17 +551,8 @@ void tr_metainfoFree(tr_info* inf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inf->files != nullptr)
|
|
||||||
{
|
|
||||||
for (tr_file_index_t ff = 0; ff < inf->fileCount; ff++)
|
|
||||||
{
|
|
||||||
tr_free(inf->files[ff].name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tr_free(inf->comment);
|
tr_free(inf->comment);
|
||||||
tr_free(inf->creator);
|
tr_free(inf->creator);
|
||||||
tr_free(inf->files);
|
|
||||||
tr_free(inf->name);
|
tr_free(inf->name);
|
||||||
tr_free(inf->source);
|
tr_free(inf->source);
|
||||||
tr_free(inf->torrent);
|
tr_free(inf->torrent);
|
||||||
|
@ -571,7 +560,6 @@ void tr_metainfoFree(tr_info* inf)
|
||||||
|
|
||||||
inf->comment = nullptr;
|
inf->comment = nullptr;
|
||||||
inf->creator = nullptr;
|
inf->creator = nullptr;
|
||||||
inf->files = nullptr;
|
|
||||||
inf->name = nullptr;
|
inf->name = nullptr;
|
||||||
inf->source = nullptr;
|
inf->source = nullptr;
|
||||||
inf->torrent = nullptr;
|
inf->torrent = nullptr;
|
||||||
|
|
|
@ -106,7 +106,7 @@ std::string_view tr_ctorGetContents(tr_ctor const* ctor)
|
||||||
|
|
||||||
char const* tr_ctorGetSourceFile(tr_ctor const* ctor)
|
char const* tr_ctorGetSourceFile(tr_ctor const* ctor)
|
||||||
{
|
{
|
||||||
return ctor->metainfo.parsedTorrentFile().c_str();
|
return ctor->metainfo.torrentFile().c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tr_ctorSaveContents(tr_ctor const* ctor, std::string_view filename, tr_error** error)
|
bool tr_ctorSaveContents(tr_ctor const* ctor, std::string_view filename, tr_error** error)
|
||||||
|
@ -298,7 +298,7 @@ bool tr_ctorGetIncompleteDir(tr_ctor const* ctor, char const** setme)
|
||||||
|
|
||||||
tr_torrent_metainfo const* tr_ctorGetMetainfo(tr_ctor const* ctor)
|
tr_torrent_metainfo const* tr_ctorGetMetainfo(tr_ctor const* ctor)
|
||||||
{
|
{
|
||||||
return std::empty(ctor->metainfo.files()) ? nullptr : &ctor->metainfo;
|
return !std::empty(ctor->metainfo) ? &ctor->metainfo : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
tr_session* tr_ctorGetSession(tr_ctor const* ctor)
|
tr_session* tr_ctorGetSession(tr_ctor const* ctor)
|
||||||
|
|
|
@ -163,46 +163,46 @@ void* tr_torrentGetMetadataPiece(tr_torrent* tor, int piece, size_t* len)
|
||||||
TR_ASSERT(piece >= 0);
|
TR_ASSERT(piece >= 0);
|
||||||
TR_ASSERT(len != nullptr);
|
TR_ASSERT(len != nullptr);
|
||||||
|
|
||||||
char* ret = nullptr;
|
if (!tor->hasMetadata())
|
||||||
|
|
||||||
if (tor->hasMetadata())
|
|
||||||
{
|
{
|
||||||
ensureInfoDictOffsetIsCached(tor);
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
auto const info_dict_length = tor->infoDictLength();
|
auto const fd = tr_sys_file_open(tor->torrentFile(), TR_SYS_FILE_READ, 0, nullptr);
|
||||||
TR_ASSERT(info_dict_length > 0);
|
if (fd == TR_BAD_SYS_FILE)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
auto const fd = tr_sys_file_open(tor->torrentFile(), TR_SYS_FILE_READ, 0, nullptr);
|
ensureInfoDictOffsetIsCached(tor);
|
||||||
if (fd != TR_BAD_SYS_FILE)
|
|
||||||
|
auto const info_dict_length = tor->infoDictLength();
|
||||||
|
TR_ASSERT(info_dict_length > 0);
|
||||||
|
|
||||||
|
char* ret = nullptr;
|
||||||
|
if (size_t o = piece * METADATA_PIECE_SIZE; tr_sys_file_seek(fd, tor->infoDictOffset + o, TR_SEEK_SET, nullptr, nullptr))
|
||||||
|
{
|
||||||
|
size_t const l = o + METADATA_PIECE_SIZE <= info_dict_length ? METADATA_PIECE_SIZE : info_dict_length - o;
|
||||||
|
|
||||||
|
if (0 < l && l <= METADATA_PIECE_SIZE)
|
||||||
{
|
{
|
||||||
size_t const o = piece * METADATA_PIECE_SIZE;
|
char* buf = tr_new(char, l);
|
||||||
|
auto n = uint64_t{};
|
||||||
|
|
||||||
if (tr_sys_file_seek(fd, tor->infoDictOffset + o, TR_SEEK_SET, nullptr, nullptr))
|
if (tr_sys_file_read(fd, buf, l, &n, nullptr) && n == l)
|
||||||
{
|
{
|
||||||
size_t const l = o + METADATA_PIECE_SIZE <= info_dict_length ? METADATA_PIECE_SIZE : info_dict_length - o;
|
*len = l;
|
||||||
|
ret = buf;
|
||||||
if (0 < l && l <= METADATA_PIECE_SIZE)
|
buf = nullptr;
|
||||||
{
|
|
||||||
char* buf = tr_new(char, l);
|
|
||||||
auto n = uint64_t{};
|
|
||||||
|
|
||||||
if (tr_sys_file_read(fd, buf, l, &n, nullptr) && n == l)
|
|
||||||
{
|
|
||||||
*len = l;
|
|
||||||
ret = buf;
|
|
||||||
buf = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
tr_free(buf);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tr_sys_file_close(fd, nullptr);
|
tr_free(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TR_ASSERT(ret == nullptr || *len > 0);
|
tr_sys_file_close(fd, nullptr);
|
||||||
|
|
||||||
|
TR_ASSERT(ret == nullptr || *len > 0);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,11 +24,6 @@ struct tr_info;
|
||||||
|
|
||||||
struct tr_torrent_metainfo : public tr_magnet_metainfo
|
struct tr_torrent_metainfo : public tr_magnet_metainfo
|
||||||
{
|
{
|
||||||
[[nodiscard]] constexpr auto const& blockInfo() const
|
|
||||||
{
|
|
||||||
return block_info_;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
tr_torrent_metainfo() = default;
|
tr_torrent_metainfo() = default;
|
||||||
~tr_torrent_metainfo() override = default;
|
~tr_torrent_metainfo() override = default;
|
||||||
|
@ -48,6 +43,11 @@ public:
|
||||||
|
|
||||||
/// BLOCK INFO
|
/// BLOCK INFO
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr auto const& blockInfo() const
|
||||||
|
{
|
||||||
|
return block_info_;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr auto blockCount() const
|
[[nodiscard]] constexpr auto blockCount() const
|
||||||
{
|
{
|
||||||
return blockInfo().blockCount();
|
return blockInfo().blockCount();
|
||||||
|
@ -114,9 +114,17 @@ public:
|
||||||
return source_;
|
return source_;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const& files() const
|
auto fileCount() const
|
||||||
{
|
{
|
||||||
return files_;
|
return std::size(files_);
|
||||||
|
}
|
||||||
|
std::string const& fileSubpath(tr_file_index_t i) const
|
||||||
|
{
|
||||||
|
return files_.at(i).path();
|
||||||
|
}
|
||||||
|
auto fileSize(tr_file_index_t i) const
|
||||||
|
{
|
||||||
|
return files_.at(i).size();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto const& isPrivate() const
|
[[nodiscard]] auto const& isPrivate() const
|
||||||
|
@ -124,7 +132,7 @@ public:
|
||||||
return is_private_;
|
return is_private_;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto const& parsedTorrentFile() const
|
[[nodiscard]] auto const& torrentFile() const
|
||||||
{
|
{
|
||||||
return torrent_file_;
|
return torrent_file_;
|
||||||
}
|
}
|
||||||
|
@ -165,20 +173,20 @@ private:
|
||||||
{
|
{
|
||||||
return path_;
|
return path_;
|
||||||
}
|
}
|
||||||
uint64_t length() const
|
uint64_t size() const
|
||||||
{
|
{
|
||||||
return length_;
|
return size_;
|
||||||
}
|
}
|
||||||
|
|
||||||
file_t(std::string_view path, uint64_t length)
|
file_t(std::string_view path, uint64_t size)
|
||||||
: path_{ path }
|
: path_{ path }
|
||||||
, length_{ length }
|
, size_{ size }
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string path_;
|
std::string path_;
|
||||||
uint64_t length_ = 0;
|
uint64_t size_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
tr_block_info block_info_ = tr_block_info{ 0, 0 };
|
tr_block_info block_info_ = tr_block_info{ 0, 0 };
|
||||||
|
|
|
@ -1109,18 +1109,18 @@ tr_file_view tr_torrentFile(tr_torrent const* tor, tr_file_index_t i)
|
||||||
{
|
{
|
||||||
TR_ASSERT(tr_isTorrent(tor));
|
TR_ASSERT(tr_isTorrent(tor));
|
||||||
|
|
||||||
auto const* subpath = tor->fileSubpath(i);
|
auto const& subpath = tor->fileSubpath(i);
|
||||||
auto const priority = tor->file_priorities_.filePriority(i);
|
auto const priority = tor->file_priorities_.filePriority(i);
|
||||||
auto const wanted = tor->files_wanted_.fileWanted(i);
|
auto const wanted = tor->files_wanted_.fileWanted(i);
|
||||||
auto const length = tor->fileSize(i);
|
auto const length = tor->fileSize(i);
|
||||||
|
|
||||||
if (tor->completeness == TR_SEED || length == 0)
|
if (tor->completeness == TR_SEED || length == 0)
|
||||||
{
|
{
|
||||||
return { subpath, length, length, 1.0, priority, wanted };
|
return { subpath.c_str(), length, length, 1.0, priority, wanted };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const have = tor->completion.countHasBytesInSpan(tor->fpm_.byteSpan(i));
|
auto const have = tor->completion.countHasBytesInSpan(tor->fpm_.byteSpan(i));
|
||||||
return { subpath, have, length, have >= length ? 1.0 : have / double(length), priority, wanted };
|
return { subpath.c_str(), have, length, have >= length ? 1.0 : have / double(length), priority, wanted };
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t tr_torrentFileCount(tr_torrent const* torrent)
|
size_t tr_torrentFileCount(tr_torrent const* torrent)
|
||||||
|
@ -2513,7 +2513,7 @@ static void tr_torrentFileCompleted(tr_torrent* tor, tr_file_index_t i)
|
||||||
char* sub = nullptr;
|
char* sub = nullptr;
|
||||||
if (tr_torrentFindFile2(tor, i, &base, &sub, nullptr))
|
if (tr_torrentFindFile2(tor, i, &base, &sub, nullptr))
|
||||||
{
|
{
|
||||||
if (char const* file_subpath = tor->fileSubpath(i); strcmp(sub, file_subpath) != 0)
|
if (auto const& file_subpath = tor->fileSubpath(i); file_subpath != sub)
|
||||||
{
|
{
|
||||||
auto const oldpath = tr_strvPath(base, sub);
|
auto const oldpath = tr_strvPath(base, sub);
|
||||||
auto const newpath = tr_strvPath(base, file_subpath);
|
auto const newpath = tr_strvPath(base, file_subpath);
|
||||||
|
@ -2858,26 +2858,21 @@ static bool renameArgsAreValid(char const* oldpath, char const* newname)
|
||||||
strchr(newname, TR_PATH_DELIMITER) == nullptr;
|
strchr(newname, TR_PATH_DELIMITER) == nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static tr_file_index_t* renameFindAffectedFiles(tr_torrent* tor, char const* oldpath, size_t* setme_n)
|
static auto renameFindAffectedFiles(tr_torrent* tor, std::string_view oldpath)
|
||||||
{
|
{
|
||||||
|
auto indices = std::vector<tr_file_index_t>{};
|
||||||
|
auto oldpath_as_dir = tr_strvJoin(oldpath, "/"sv);
|
||||||
auto const n_files = tor->fileCount();
|
auto const n_files = tor->fileCount();
|
||||||
auto n_affected_files = size_t{};
|
|
||||||
auto* const indices = tr_new0(tr_file_index_t, n_files);
|
|
||||||
|
|
||||||
auto const oldpath_len = strlen(oldpath);
|
|
||||||
|
|
||||||
for (tr_file_index_t i = 0; i < n_files; ++i)
|
for (tr_file_index_t i = 0; i < n_files; ++i)
|
||||||
{
|
{
|
||||||
char const* name = tor->fileSubpath(i);
|
auto const& name = tor->fileSubpath(i);
|
||||||
size_t const len = strlen(name);
|
if (name == oldpath || tr_strvStartsWith(name, oldpath_as_dir))
|
||||||
|
|
||||||
if ((len == oldpath_len || (len > oldpath_len && name[oldpath_len] == '/')) && memcmp(oldpath, name, oldpath_len) == 0)
|
|
||||||
{
|
{
|
||||||
indices[n_affected_files++] = i;
|
indices.push_back(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*setme_n = n_affected_files;
|
|
||||||
return indices;
|
return indices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2999,10 +2994,8 @@ static void torrentRenamePath(void* vdata)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto n = size_t{};
|
auto const file_indices = renameFindAffectedFiles(tor, oldpath);
|
||||||
tr_file_index_t* const file_indices = renameFindAffectedFiles(tor, oldpath, &n);
|
if (std::empty(file_indices))
|
||||||
|
|
||||||
if (n == 0)
|
|
||||||
{
|
{
|
||||||
error = EINVAL;
|
error = EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -3013,13 +3006,13 @@ static void torrentRenamePath(void* vdata)
|
||||||
if (error == 0)
|
if (error == 0)
|
||||||
{
|
{
|
||||||
/* update tr_info.files */
|
/* update tr_info.files */
|
||||||
for (size_t i = 0; i < n; ++i)
|
for (auto const& file_index : file_indices)
|
||||||
{
|
{
|
||||||
renameTorrentFileString(tor, oldpath, newname, file_indices[i]);
|
renameTorrentFileString(tor, oldpath, newname, file_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update tr_info.name if user changed the toplevel */
|
/* update tr_info.name if user changed the toplevel */
|
||||||
if (n == tor->fileCount() && strchr(oldpath, '/') == nullptr)
|
if (std::size(file_indices) == tor->fileCount() && strchr(oldpath, '/') == nullptr)
|
||||||
{
|
{
|
||||||
tor->setName(newname);
|
tor->setName(newname);
|
||||||
}
|
}
|
||||||
|
@ -3028,8 +3021,6 @@ static void torrentRenamePath(void* vdata)
|
||||||
tor->setDirty();
|
tor->setDirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tr_free(file_indices);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
|
@ -3134,10 +3125,5 @@ void tr_torrent::setName(std::string_view name)
|
||||||
|
|
||||||
void tr_torrent::setFileSubpath(tr_file_index_t i, std::string_view subpath)
|
void tr_torrent::setFileSubpath(tr_file_index_t i, std::string_view subpath)
|
||||||
{
|
{
|
||||||
if (fileSubpath(i) != subpath)
|
this->info.files[i].subpath = subpath;
|
||||||
{
|
|
||||||
auto* old = this->info.files[i].name;
|
|
||||||
this->info.files[i].name = tr_strvDup(subpath);
|
|
||||||
tr_free(old);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -372,21 +372,17 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] tr_file_index_t fileCount() const
|
[[nodiscard]] tr_file_index_t fileCount() const
|
||||||
{
|
{
|
||||||
return info.fileCount;
|
return std::size(info.files);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] char const* fileSubpath(tr_file_index_t i) const
|
[[nodiscard]] std::string const& fileSubpath(tr_file_index_t i) const
|
||||||
{
|
{
|
||||||
TR_ASSERT(i < this->fileCount());
|
return info.fileSubpath(i);
|
||||||
|
|
||||||
return info.files[i].name ? info.files[i].name : "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto fileSize(tr_file_index_t i) const
|
[[nodiscard]] auto fileSize(tr_file_index_t i) const
|
||||||
{
|
{
|
||||||
TR_ASSERT(i < this->fileCount());
|
return info.fileSize(i);
|
||||||
|
|
||||||
return info.files[i].length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFileSubpath(tr_file_index_t i, std::string_view subpath);
|
void setFileSubpath(tr_file_index_t i, std::string_view subpath);
|
||||||
|
|
|
@ -1502,8 +1502,8 @@ void tr_torrentVerify(tr_torrent* torrent, tr_verify_done_func callback_func_or_
|
||||||
struct tr_file
|
struct tr_file
|
||||||
{
|
{
|
||||||
// public
|
// public
|
||||||
char* name; /* Path to the file */
|
std::string subpath; /* Path to the file */
|
||||||
uint64_t length; /* Length of the file, in bytes */
|
uint64_t size; /* Length of the file, in bytes */
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @brief information about a torrent that comes from its metainfo file */
|
/** @brief information about a torrent that comes from its metainfo file */
|
||||||
|
@ -1528,7 +1528,22 @@ struct tr_info
|
||||||
|
|
||||||
// Private.
|
// Private.
|
||||||
// Use tr_torrentFile() and tr_torrentFileCount() instead.
|
// Use tr_torrentFile() and tr_torrentFileCount() instead.
|
||||||
tr_file* files;
|
std::vector<tr_file> files;
|
||||||
|
|
||||||
|
tr_file_index_t fileCount() const
|
||||||
|
{
|
||||||
|
return std::size(files);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string const& fileSubpath(tr_file_index_t i) const
|
||||||
|
{
|
||||||
|
return files[i].subpath;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto fileSize(tr_file_index_t i) const
|
||||||
|
{
|
||||||
|
return files[i].size;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(ckerr) aggregate this directly, rather than using a shared_ptr, when tr_info is private
|
// TODO(ckerr) aggregate this directly, rather than using a shared_ptr, when tr_info is private
|
||||||
std::shared_ptr<tr_announce_list> announce_list;
|
std::shared_ptr<tr_announce_list> announce_list;
|
||||||
|
@ -1537,7 +1552,6 @@ struct tr_info
|
||||||
time_t dateCreated;
|
time_t dateCreated;
|
||||||
|
|
||||||
unsigned int webseedCount;
|
unsigned int webseedCount;
|
||||||
tr_file_index_t fileCount;
|
|
||||||
uint32_t pieceSize;
|
uint32_t pieceSize;
|
||||||
tr_piece_index_t pieceCount;
|
tr_piece_index_t pieceCount;
|
||||||
|
|
||||||
|
|
|
@ -1102,7 +1102,7 @@ static void removeKeRangerRansomware()
|
||||||
}
|
}
|
||||||
|
|
||||||
//determine to show the options window
|
//determine to show the options window
|
||||||
auto const is_multifile = std::size(metainfo.files()) > 1;
|
auto const is_multifile = metainfo.fileCount() > 1;
|
||||||
BOOL const showWindow = type == ADD_SHOW_OPTIONS ||
|
BOOL const showWindow = type == ADD_SHOW_OPTIONS ||
|
||||||
([fDefaults boolForKey:@"DownloadAsk"] && (is_multifile || ![fDefaults boolForKey:@"DownloadAskMulti"]) &&
|
([fDefaults boolForKey:@"DownloadAsk"] && (is_multifile || ![fDefaults boolForKey:@"DownloadAskMulti"]) &&
|
||||||
(type != ADD_AUTO || ![fDefaults boolForKey:@"DownloadAskManual"]));
|
(type != ADD_AUTO || ![fDefaults boolForKey:@"DownloadAskManual"]));
|
||||||
|
|
|
@ -100,7 +100,7 @@
|
||||||
|
|
||||||
size += metainfo.totalSize();
|
size += metainfo.totalSize();
|
||||||
|
|
||||||
auto const n_files = std::size(metainfo.files());
|
auto const n_files = metainfo.fileCount();
|
||||||
fileCount += n_files;
|
fileCount += n_files;
|
||||||
if (n_files == 1)
|
if (n_files == 1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -69,7 +69,7 @@ OSStatus GeneratePreviewForURL(void* thisInterface, QLPreviewRequestRef preview,
|
||||||
|
|
||||||
NSString* name = [NSString stringWithUTF8String:metainfo.name().c_str()];
|
NSString* name = [NSString stringWithUTF8String:metainfo.name().c_str()];
|
||||||
|
|
||||||
auto const n_files = std::size(metainfo.files());
|
auto const n_files = metainfo.fileCount();
|
||||||
auto const is_multifile = n_files > 1;
|
auto const is_multifile = n_files > 1;
|
||||||
NSString* fileTypeString = is_multifile ? NSFileTypeForHFSTypeCode(kGenericFolderIcon) : [name pathExtension];
|
NSString* fileTypeString = is_multifile ? NSFileTypeForHFSTypeCode(kGenericFolderIcon) : [name pathExtension];
|
||||||
|
|
||||||
|
@ -190,9 +190,9 @@ OSStatus GeneratePreviewForURL(void* thisInterface, QLPreviewRequestRef preview,
|
||||||
|
|
||||||
#warning display size?
|
#warning display size?
|
||||||
#warning display folders?
|
#warning display folders?
|
||||||
for (auto const& file : metainfo.files())
|
for (tr_file_index_t i = 0; i < n_files; ++i)
|
||||||
{
|
{
|
||||||
NSString* fullFilePath = [NSString stringWithUTF8String:file.path().c_str()];
|
NSString* fullFilePath = [NSString stringWithUTF8String:metainfo.fileSubpath(i).c_str()];
|
||||||
NSCAssert([fullFilePath hasPrefix:[name stringByAppendingString:@"/"]], @"Expected file path %@ to begin with %@/", fullFilePath, name);
|
NSCAssert([fullFilePath hasPrefix:[name stringByAppendingString:@"/"]], @"Expected file path %@ to begin with %@/", fullFilePath, name);
|
||||||
|
|
||||||
NSString* shortenedFilePath = [fullFilePath substringFromIndex:[name length] + 1];
|
NSString* shortenedFilePath = [fullFilePath substringFromIndex:[name length] + 1];
|
||||||
|
|
|
@ -172,30 +172,27 @@ void OptionsDialog::reload()
|
||||||
metainfo_ = metainfo;
|
metainfo_ = metainfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool const have_files_to_show = metainfo_ && !std::empty(metainfo_->files());
|
bool const have_files_to_show = metainfo_ && !std::empty(*metainfo_);
|
||||||
|
|
||||||
ui_.filesView->setVisible(have_files_to_show);
|
ui_.filesView->setVisible(have_files_to_show);
|
||||||
layout()->setSizeConstraint(have_files_to_show ? QLayout::SetDefaultConstraint : QLayout::SetFixedSize);
|
layout()->setSizeConstraint(have_files_to_show ? QLayout::SetDefaultConstraint : QLayout::SetFixedSize);
|
||||||
|
|
||||||
if (metainfo_)
|
if (metainfo_)
|
||||||
{
|
{
|
||||||
int i = 0;
|
auto const n_files = metainfo_->fileCount();
|
||||||
auto const n_files = std::size(metainfo_->files());
|
|
||||||
priorities_.assign(n_files, TR_PRI_NORMAL);
|
priorities_.assign(n_files, TR_PRI_NORMAL);
|
||||||
wanted_.assign(n_files, true);
|
wanted_.assign(n_files, true);
|
||||||
|
|
||||||
for (auto const& file : metainfo_->files())
|
for (tr_file_index_t i = 0; i < n_files; ++i)
|
||||||
{
|
{
|
||||||
auto f = TorrentFile{};
|
auto f = TorrentFile{};
|
||||||
f.index = i;
|
f.index = i;
|
||||||
f.priority = priorities_[i];
|
f.priority = priorities_[i];
|
||||||
f.wanted = wanted_[i];
|
f.wanted = wanted_[i];
|
||||||
f.size = file.length();
|
f.size = metainfo_->fileSize(i);
|
||||||
f.have = 0;
|
f.have = 0;
|
||||||
f.filename = QString::fromStdString(file.path());
|
f.filename = QString::fromStdString(metainfo_->fileSubpath(i));
|
||||||
files_.push_back(f);
|
files_.push_back(f);
|
||||||
|
|
||||||
++i;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -388,7 +388,7 @@ TEST_F(AnnounceListTest, save)
|
||||||
|
|
||||||
// test that non-announce parts of the metainfo are the same
|
// test that non-announce parts of the metainfo are the same
|
||||||
EXPECT_STREQ(original->info.name, saved->info.name);
|
EXPECT_STREQ(original->info.name, saved->info.name);
|
||||||
EXPECT_EQ(original->info.fileCount, saved->info.fileCount);
|
EXPECT_EQ(original->info.fileCount(), saved->info.fileCount());
|
||||||
EXPECT_EQ(original->info.dateCreated, saved->info.dateCreated);
|
EXPECT_EQ(original->info.dateCreated, saved->info.dateCreated);
|
||||||
EXPECT_EQ(original->pieces, saved->pieces);
|
EXPECT_EQ(original->pieces, saved->pieces);
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ protected:
|
||||||
EXPECT_EQ(payloadSize, metainfo.totalSize());
|
EXPECT_EQ(payloadSize, metainfo.totalSize());
|
||||||
EXPECT_EQ(makeString(tr_sys_path_basename(input_file.data(), nullptr)), metainfo.name());
|
EXPECT_EQ(makeString(tr_sys_path_basename(input_file.data(), nullptr)), metainfo.name());
|
||||||
EXPECT_EQ(comment, metainfo.comment());
|
EXPECT_EQ(comment, metainfo.comment());
|
||||||
EXPECT_EQ(tr_file_index_t{ 1 }, std::size(metainfo.files()));
|
EXPECT_EQ(tr_file_index_t{ 1 }, metainfo.fileCount());
|
||||||
EXPECT_EQ(isPrivate, metainfo.isPrivate());
|
EXPECT_EQ(isPrivate, metainfo.isPrivate());
|
||||||
EXPECT_EQ(size_t(trackerCount), std::size(metainfo.announceList()));
|
EXPECT_EQ(size_t(trackerCount), std::size(metainfo.announceList()));
|
||||||
|
|
||||||
|
@ -160,7 +160,7 @@ protected:
|
||||||
tr_free(tmpstr);
|
tr_free(tmpstr);
|
||||||
EXPECT_EQ(comment, metainfo.comment());
|
EXPECT_EQ(comment, metainfo.comment());
|
||||||
EXPECT_EQ(source, metainfo.source());
|
EXPECT_EQ(source, metainfo.source());
|
||||||
EXPECT_EQ(payload_count, std::size(metainfo.files()));
|
EXPECT_EQ(payload_count, metainfo.fileCount());
|
||||||
EXPECT_EQ(is_private, metainfo.isPrivate());
|
EXPECT_EQ(is_private, metainfo.isPrivate());
|
||||||
EXPECT_EQ(size_t(tracker_count), std::size(metainfo.announceList()));
|
EXPECT_EQ(size_t(tracker_count), std::size(metainfo.announceList()));
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
#include <cstring> // strcmp()
|
#include <cstring> // strcmp()
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
using namespace std::literals;
|
||||||
|
|
||||||
namespace libtransmission
|
namespace libtransmission
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -262,7 +264,7 @@ TEST_F(RenameTest, multifileTorrent)
|
||||||
"MjpwaWVjZSBsZW5ndGhpMzI3NjhlNjpwaWVjZXMyMDp27buFkmy8ICfNX4nsJmt0Ckm2Ljc6cHJp"
|
"MjpwaWVjZSBsZW5ndGhpMzI3NjhlNjpwaWVjZXMyMDp27buFkmy8ICfNX4nsJmt0Ckm2Ljc6cHJp"
|
||||||
"dmF0ZWkwZWVl");
|
"dmF0ZWkwZWVl");
|
||||||
EXPECT_TRUE(tr_isTorrent(tor));
|
EXPECT_TRUE(tr_isTorrent(tor));
|
||||||
auto* files = tor->info.files;
|
auto& files = tor->info.files;
|
||||||
|
|
||||||
// sanity check the info
|
// sanity check the info
|
||||||
EXPECT_STREQ("Felidae", tr_torrentName(tor));
|
EXPECT_STREQ("Felidae", tr_torrentName(tor));
|
||||||
|
@ -318,8 +320,7 @@ TEST_F(RenameTest, multifileTorrent)
|
||||||
// (while the branch is renamed: confirm that the .resume file remembers the changes)
|
// (while the branch is renamed: confirm that the .resume file remembers the changes)
|
||||||
tr_torrentSaveResume(tor);
|
tr_torrentSaveResume(tor);
|
||||||
// this is a bit dodgy code-wise, but let's make sure the .resume file got the name
|
// this is a bit dodgy code-wise, but let's make sure the .resume file got the name
|
||||||
tr_free(files[1].name);
|
files[1].subpath = "gabba gabba hey";
|
||||||
files[1].name = tr_strdup("gabba gabba hey");
|
|
||||||
auto const loaded = tr_torrentLoadResume(tor, ~0ULL, ctor, nullptr);
|
auto const loaded = tr_torrentLoadResume(tor, ~0ULL, ctor, nullptr);
|
||||||
EXPECT_NE(decltype(loaded){ 0 }, (loaded & TR_FR_FILENAMES));
|
EXPECT_NE(decltype(loaded){ 0 }, (loaded & TR_FR_FILENAMES));
|
||||||
EXPECT_EQ(expected_files[0], tr_torrentFile(tor, 0).name);
|
EXPECT_EQ(expected_files[0], tr_torrentFile(tor, 0).name);
|
||||||
|
@ -461,13 +462,12 @@ TEST_F(RenameTest, partialFile)
|
||||||
***/
|
***/
|
||||||
|
|
||||||
auto* tor = zeroTorrentInit();
|
auto* tor = zeroTorrentInit();
|
||||||
auto const& files = tor->info.files;
|
|
||||||
EXPECT_EQ(TotalSize, tor->totalSize());
|
EXPECT_EQ(TotalSize, tor->totalSize());
|
||||||
EXPECT_EQ(PieceSize, tor->pieceSize());
|
EXPECT_EQ(PieceSize, tor->pieceSize());
|
||||||
EXPECT_EQ(PieceCount, tor->pieceCount());
|
EXPECT_EQ(PieceCount, tor->pieceCount());
|
||||||
EXPECT_STREQ("files-filled-with-zeroes/1048576", files[0].name);
|
EXPECT_EQ("files-filled-with-zeroes/1048576"sv, tor->fileSubpath(0));
|
||||||
EXPECT_STREQ("files-filled-with-zeroes/4096", files[1].name);
|
EXPECT_EQ("files-filled-with-zeroes/4096"sv, tor->fileSubpath(1));
|
||||||
EXPECT_STREQ("files-filled-with-zeroes/512", files[2].name);
|
EXPECT_EQ("files-filled-with-zeroes/512"sv, tor->fileSubpath(2));
|
||||||
|
|
||||||
zeroTorrentPopulate(tor, false);
|
zeroTorrentPopulate(tor, false);
|
||||||
EXPECT_EQ(Length[0], tr_torrentFile(tor, 0).have + PieceSize);
|
EXPECT_EQ(Length[0], tr_torrentFile(tor, 0).have + PieceSize);
|
||||||
|
@ -483,14 +483,14 @@ TEST_F(RenameTest, partialFile)
|
||||||
|
|
||||||
EXPECT_EQ(0, torrentRenameAndWait(tor, "files-filled-with-zeroes", "foo"));
|
EXPECT_EQ(0, torrentRenameAndWait(tor, "files-filled-with-zeroes", "foo"));
|
||||||
EXPECT_EQ(0, torrentRenameAndWait(tor, "foo/1048576", "bar"));
|
EXPECT_EQ(0, torrentRenameAndWait(tor, "foo/1048576", "bar"));
|
||||||
auto strings = std::array<char const*, 3>{};
|
auto strings = std::array<std::string_view, 3>{};
|
||||||
strings[0] = "foo/bar";
|
strings[0] = "foo/bar"sv;
|
||||||
strings[1] = "foo/4096";
|
strings[1] = "foo/4096"sv;
|
||||||
strings[2] = "foo/512";
|
strings[2] = "foo/512"sv;
|
||||||
|
|
||||||
for (tr_file_index_t i = 0; i < 3; ++i)
|
for (tr_file_index_t i = 0; i < 3; ++i)
|
||||||
{
|
{
|
||||||
EXPECT_STREQ(strings[i], files[i].name);
|
EXPECT_EQ(strings[i], tor->fileSubpath(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
strings[0] = "foo/bar.part";
|
strings[0] = "foo/bar.part";
|
||||||
|
|
|
@ -43,7 +43,7 @@ TEST_F(TorrentMetainfoTest, magnetLink)
|
||||||
|
|
||||||
auto metainfo = tr_torrent_metainfo{};
|
auto metainfo = tr_torrent_metainfo{};
|
||||||
EXPECT_TRUE(metainfo.parseMagnet(MagnetLink));
|
EXPECT_TRUE(metainfo.parseMagnet(MagnetLink));
|
||||||
EXPECT_EQ(0, std::size(metainfo.files())); // because it's a magnet link
|
EXPECT_EQ(0, metainfo.fileCount()); // because it's a magnet link
|
||||||
EXPECT_EQ(2, std::size(metainfo.announceList()));
|
EXPECT_EQ(2, std::size(metainfo.announceList()));
|
||||||
EXPECT_EQ(MagnetLink, metainfo.magnet());
|
EXPECT_EQ(MagnetLink, metainfo.magnet());
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,11 +177,11 @@ void showInfo(app_opts const& opts, tr_torrent_metainfo const& metainfo)
|
||||||
printf("\nFILES\n\n");
|
printf("\nFILES\n\n");
|
||||||
|
|
||||||
auto filenames = std::vector<std::string>{};
|
auto filenames = std::vector<std::string>{};
|
||||||
for (auto const& file : metainfo.files())
|
for (tr_file_index_t i = 0, n = metainfo.fileCount(); i < n; ++i)
|
||||||
{
|
{
|
||||||
std::string filename = file.path();
|
std::string filename = metainfo.fileSubpath(i);
|
||||||
filename += " (";
|
filename += " (";
|
||||||
filename += tr_formatter_size_B(file.length());
|
filename += tr_formatter_size_B(metainfo.fileSize(i));
|
||||||
filename += ')';
|
filename += ')';
|
||||||
filenames.emplace_back(filename);
|
filenames.emplace_back(filename);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue