Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: don't store torrent hashes in QStrings #1428

Merged
merged 3 commits into from
Sep 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 10 additions & 13 deletions qt/DetailsDialog.cc
Original file line number Diff line number Diff line change
Expand Up @@ -794,20 +794,17 @@ void DetailsDialog::refreshUI()
ui_.sizeValueLabel->setText(string);

// myHashLabel
string = none;

if (!torrents.empty())
if (torrents.empty())
{
string = torrents[0]->hashString();

for (Torrent const* const t : torrents)
{
if (string != t->hashString())
{
string = mixed;
break;
}
}
string = none;
}
else if (torrents.size() > 1)
{
string = mixed;
}
else
{
string = torrents.front()->hash().toString();
}

ui_.hashValueLabel->setText(string);
Expand Down
2 changes: 1 addition & 1 deletion qt/Torrent.cc
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ Torrent::fields_t Torrent::update(tr_quark const* keys, tr_variant const* const*
HANDLE_KEY(eta, eta, ETA)
HANDLE_KEY(fileStats, files, FILES)
HANDLE_KEY(files, files, FILES)
HANDLE_KEY(hashString, hash_string, HASH_STRING)
HANDLE_KEY(hashString, hash, HASH)
HANDLE_KEY(haveUnchecked, have_unchecked, HAVE_UNCHECKED)
HANDLE_KEY(haveValid, have_verified, HAVE_VERIFIED)
HANDLE_KEY(honorsSessionLimits, honors_session_limits, HONORS_SESSION_LIMITS)
Expand Down
53 changes: 48 additions & 5 deletions qt/Torrent.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#pragma once

#include <array>
#include <bitset>
#include <ctime> // time_t

Expand All @@ -17,6 +18,7 @@
#include <QString>

#include <libtransmission/transmission.h>
#include <libtransmission/crypto-utils.h>
#include <libtransmission/quark.h>

#include "FaviconCache.h"
Expand Down Expand Up @@ -84,7 +86,6 @@ struct TrackerStat
int tier;
FaviconCache::Key favicon_key;
QString announce;
QString host;
QString last_announce_result;
QString last_scrape_result;
};
Expand All @@ -103,6 +104,47 @@ struct TorrentFile

using FileList = QVector<TorrentFile>;

class TorrentHash
{
private:
std::array<uint8_t, SHA_DIGEST_LENGTH> data_ = {};

public:
TorrentHash() {}

TorrentHash(char const* str)
{
tr_hex_to_sha1(data_.data(), str);
}

TorrentHash(QString const& str)
{
tr_hex_to_sha1(data_.data(), str.toUtf8().constData());
}

bool operator ==(TorrentHash const& that) const
{
return data_ == that.data_;
}

bool operator !=(TorrentHash const& that) const
{
return data_ != that.data_;
}

bool operator <(TorrentHash const& that) const
{
return data_ < that.data_;
}

QString toString() const
{
char str[SHA_DIGEST_LENGTH * 2 + 1];
tr_sha1_to_hex(str, data_.data());
return QString::fromUtf8(str, SHA_DIGEST_LENGTH * 2);
}
};

class Torrent : public QObject
{
Q_OBJECT
Expand Down Expand Up @@ -148,9 +190,9 @@ class Torrent : public QObject

QString getError() const;

QString const& hashString() const
TorrentHash const& hash() const
{
return hash_string_;
return hash_;
}

bool hasError() const
Expand Down Expand Up @@ -523,7 +565,7 @@ class Torrent : public QObject
ETA,
FAILED_EVER,
FILES,
HASH_STRING,
HASH,
HAVE_UNCHECKED,
HAVE_VERIFIED,
HONORS_SESSION_LIMITS,
Expand Down Expand Up @@ -622,7 +664,6 @@ class Torrent : public QObject
QString creator_;
QString download_dir_;
QString error_string_;
QString hash_string_;
QString name_;

QIcon icon_;
Expand All @@ -637,6 +678,8 @@ class Torrent : public QObject
Speed download_speed_;

Prefs const& prefs_;

TorrentHash hash_;
};

Q_DECLARE_METATYPE(Torrent const*)
6 changes: 2 additions & 4 deletions qt/TorrentFilter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ bool TorrentFilter::lessThan(QModelIndex const& left, QModelIndex const& right)

if (val == 0)
{
val = compare(a->hashString(), b->hashString());
val = compare(a->hash(), b->hash());
}

return val < 0;
Expand Down Expand Up @@ -253,9 +253,7 @@ bool TorrentFilter::filterAcceptsRow(int source_row, QModelIndex const& source_p
if (accepts)
{
auto const text = prefs_.getString(Prefs::FILTER_TEXT);
accepts = text.isEmpty() ||
tor.name().contains(text, Qt::CaseInsensitive) ||
tor.hashString().contains(text, Qt::CaseInsensitive);
accepts = text.isEmpty() || tor.name().contains(text, Qt::CaseInsensitive);
}

return accepts;
Expand Down
4 changes: 2 additions & 2 deletions qt/TorrentModel.cc
Original file line number Diff line number Diff line change
Expand Up @@ -485,8 +485,8 @@ void TorrentModel::rowsRemove(torrents_t const& torrents)
****
***/

bool TorrentModel::hasTorrent(QString const& hash_string) const
bool TorrentModel::hasTorrent(TorrentHash const& hash) const
{
auto test = [hash_string](auto const& tor) { return tor->hashString() == hash_string; };
auto test = [hash](auto const& tor) { return tor->hash() == hash; };
return std::any_of(torrents_.cbegin(), torrents_.cend(), test);
}
2 changes: 1 addition & 1 deletion qt/TorrentModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class TorrentModel : public QAbstractListModel
virtual ~TorrentModel() override;
void clear();

bool hasTorrent(QString const& hash_string) const;
bool hasTorrent(TorrentHash const& hash) const;

Torrent* getTorrentFromId(int id);
Torrent const* getTorrentFromId(int id) const;
Expand Down
7 changes: 6 additions & 1 deletion qt/VariantHelpers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ bool change(Speed& setme, tr_variant const* variant)
return value && change(setme, Speed::fromBps(*value));
}

bool change(TorrentHash& setme, tr_variant const* value)
{
auto const hash_string = getValue<std::string_view>(value);
return hash_string && change(setme, TorrentHash(hash_string->data()));
}

bool change(Peer& setme, tr_variant const* value)
{
bool changed = false;
Expand Down Expand Up @@ -130,7 +136,6 @@ bool change(TrackerStat& setme, tr_variant const* value)
HANDLE_KEY(downloadCount, download_count)
HANDLE_KEY(hasAnnounced, has_announced)
HANDLE_KEY(hasScraped, has_scraped)
HANDLE_KEY(host, host)
HANDLE_KEY(id, id)
HANDLE_KEY(isBackup, is_backup)
HANDLE_KEY(lastAnnouncePeerCount, last_announce_peer_count)
Expand Down
16 changes: 16 additions & 0 deletions qt/VariantHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
class QByteArray;

class Speed;
class TorrentHash;
struct Peer;
struct TorrentFile;
struct TrackerStat;
Expand Down Expand Up @@ -88,6 +89,20 @@ auto getValue(tr_variant const* variant)
return ret;
}

template<typename T, typename std::enable_if<std::is_same_v<T, std::string_view>>::type* = nullptr>
auto getValue(tr_variant const* variant)
{
std::optional<T> ret;
char const* str;
size_t len;
if (tr_variantGetStr(variant, &str, &len))
{
ret = std::string_view(str, len);
}

return ret;
}

template<typename T>
bool change(T& setme, T const& value)
{
Expand All @@ -105,6 +120,7 @@ bool change(double& setme, double const& value);
bool change(Speed& setme, tr_variant const* value);
bool change(Peer& setme, tr_variant const* value);
bool change(TorrentFile& setme, tr_variant const* value);
bool change(TorrentHash& setme, tr_variant const* value);
bool change(TrackerStat& setme, tr_variant const* value);

template<typename T>
Expand Down
2 changes: 1 addition & 1 deletion qt/WatchDir.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ int WatchDir::metainfoTest(QString const& filename) const
{
ret = ERROR;
}
else if (model_.hasTorrent(QString::fromUtf8(inf.hashString)))
else if (model_.hasTorrent(TorrentHash(inf.hashString)))
{
ret = DUPLICATE;
}
Expand Down
6 changes: 3 additions & 3 deletions tests/libtransmission/clients-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@

TEST(Client, clientForId)
{
struct Test_local
struct LocalTest
{
char const* peer_id;
char const* expected_client;
};

auto constexpr Tests = std::array<Test_local, 24>{
Test_local{ "-BT791B-", "BitTorrent 7.9.1 (Beta)" },
auto constexpr Tests = std::array<LocalTest, 24>{
LocalTest{ "-BT791B-", "BitTorrent 7.9.1 (Beta)" },
{ "-BT791\0-", "BitTorrent 7.9.1" },
{ "-FC1013-", "FileCroc 1.0.1.3" },
{ "-FC1013-", "FileCroc 1.0.1.3" },
Expand Down
6 changes: 3 additions & 3 deletions tests/libtransmission/crypto-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,14 @@ TEST(Crypto, sha1)

TEST(Crypto, ssha1)
{
struct Test_local
struct LocalTest
{
char const* const plain_text;
char const* const ssha1;
};

auto constexpr Tests = std::array<Test_local, 2>{
Test_local{ "test", "{15ad0621b259a84d24dcd4e75b09004e98a3627bAMbyRHJy" },
auto constexpr Tests = std::array<LocalTest, 2>{
LocalTest{ "test", "{15ad0621b259a84d24dcd4e75b09004e98a3627bAMbyRHJy" },
{ "QNY)(*#$B)!_X$B !_B#($^!)*&$%CV!#)&$C!@$(P*)", "{10e2d7acbb104d970514a147cd16d51dfa40fb3c0OSwJtOL" }
};

Expand Down
6 changes: 3 additions & 3 deletions tests/libtransmission/file-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -976,15 +976,15 @@ TEST_F(FileTest, pathNativeSeparators)
{
EXPECT_EQ(nullptr, tr_sys_path_native_separators(nullptr));

struct Test_local
struct LocalTest
{
std::string input;
std::string expected_output;
};

auto const tests = std::array<Test_local, 5>
auto const tests = std::array<LocalTest, 5>
{
Test_local{ "", "" },
LocalTest{ "", "" },
{ "a", TR_IF_WIN32("a", "a") },
{ "/", TR_IF_WIN32("\\", "/") },
{ "/a/b/c", TR_IF_WIN32("\\a\\b\\c", "/a/b/c") },
Expand Down
12 changes: 6 additions & 6 deletions tests/libtransmission/metainfo-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,15 @@ TEST(Metainfo, magnetLink)
// FIXME: split these into parameterized tests?
TEST(Metainfo, bucket)
{
struct Test_local
struct LocalTest
{
int expected_benc_err;
int expected_parse_result;
void const* benc;
};

auto constexpr Tests = std::array<Test_local, 9>{
Test_local{ 0, TR_PARSE_OK, BEFORE_PATH "5:a.txt" AFTER_PATH },
auto constexpr Tests = std::array<LocalTest, 9>{
LocalTest{ 0, TR_PARSE_OK, BEFORE_PATH "5:a.txt" AFTER_PATH },

/* allow empty components, but not =all= empty components, see bug #5517 */
{ 0, TR_PARSE_OK, BEFORE_PATH "0:5:a.txt" AFTER_PATH },
Expand Down Expand Up @@ -101,17 +101,17 @@ TEST(Metainfo, bucket)

TEST(Metainfo, sanitize)
{
struct Test_local
struct LocalTest
{
char const* str;
size_t len;
char const* expected_result;
bool expected_is_adjusted;
};

auto constexpr Tests = std::array<Test_local, 29>{
auto constexpr Tests = std::array<LocalTest, 29>{
// skipped
Test_local{ "", 0, nullptr, false },
LocalTest{ "", 0, nullptr, false },
{ ".", 1, nullptr, false },
{ "..", 2, nullptr, true },
{ ".....", 5, nullptr, false },
Expand Down
12 changes: 6 additions & 6 deletions tests/libtransmission/variant-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -249,14 +249,14 @@ TEST_F(VariantTest, parse)
}

TEST_F(VariantTest, bencParseAndReencode) {
struct Test_local
struct LocalTest
{
std::string benc;
bool is_good;
};

auto const tests = std::array<Test_local, 9>{
Test_local{ "llleee", true },
auto const tests = std::array<LocalTest, 9>{
LocalTest{ "llleee", true },
{ "d3:cow3:moo4:spam4:eggse", true },
{ "d4:spaml1:a1:bee", true },
{ "d5:greenli1ei2ei3ee4:spamd1:ai123e3:keyi214eee", true },
Expand Down Expand Up @@ -343,14 +343,14 @@ TEST_F(VariantTest, bencMalformedIncompleteString)

TEST_F(VariantTest, bencToJson)
{
struct Test_local
struct LocalTest
{
std::string benc;
std::string expected;
};

auto const tests = std::array<Test_local, 5>{
Test_local{ "i6e", "6" },
auto const tests = std::array<LocalTest, 5>{
LocalTest{ "i6e", "6" },
{ "d5:helloi1e5:worldi2ee", R"({"hello":1,"world":2})" },
{ "d5:helloi1e5:worldi2e3:fooli1ei2ei3eee", R"({"foo":[1,2,3],"hello":1,"world":2})" },
{ "d5:helloi1e5:worldi2e3:fooli1ei2ei3ed1:ai0eeee", R"({"foo":[1,2,3,{"a":0}],"hello":1,"world":2})" },
Expand Down