refactor: use std::unordered_set for tr_torrent.labels (#1856)

This commit is contained in:
Charles Kerr 2021-09-29 14:52:19 -05:00 committed by GitHub
parent e03bc8e5bc
commit baafb68bfd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 44 additions and 112 deletions

View File

@ -106,12 +106,11 @@ static uint64_t loadPeers(tr_variant* dict, tr_torrent* tor)
static void saveLabels(tr_variant* dict, tr_torrent const* tor)
{
size_t const n = tr_ptrArraySize(&tor->labels);
tr_variant* list = tr_variantDictAddList(dict, TR_KEY_labels, n);
char const* const* labels = (char const* const*)tr_ptrArrayBase(&tor->labels);
for (size_t i = 0; i < n; ++i)
auto const& labels = tor->labels;
tr_variant* list = tr_variantDictAddList(dict, TR_KEY_labels, std::size(labels));
for (auto const& label : labels)
{
tr_variantListAddStr(list, labels[i]);
tr_variantListAddStr(list, label.c_str());
}
}
@ -128,7 +127,7 @@ static uint64_t loadLabels(tr_variant* dict, tr_torrent* tor)
{
if (tr_variantGetStr(tr_variantListChild(list, i), &str, &str_len) && str != nullptr && str_len != 0)
{
tr_ptrArrayAppend(&tor->labels, tr_strndup(str, str_len));
tor->labels.emplace(str, str_len);
}
}

View File

@ -472,12 +472,10 @@ static char const* torrentVerify(
static void addLabels(tr_torrent const* tor, tr_variant* list)
{
int const labelsCount = tr_ptrArraySize(&tor->labels);
tr_variantInitList(list, labelsCount);
char const* const* labels = (char const* const*)tr_ptrArrayBase(&tor->labels);
for (int i = 0; i < labelsCount; ++i)
tr_variantInitList(list, std::size(tor->labels));
for (auto const& label : tor->labels)
{
tr_variantListAddStr(list, labels[i]);
tr_variantListAddStr(list, label.c_str());
}
}
@ -1079,8 +1077,7 @@ static char const* setLabels(tr_torrent* tor, tr_variant* list)
{
size_t const n = tr_variantListSize(list);
char const* errmsg = nullptr;
auto labels = tr_ptrArray{};
int labelcount = 0;
auto labels = tr_labels_t{};
for (size_t i = 0; i < n; ++i)
{
char const* str;
@ -1099,26 +1096,13 @@ static char const* setLabels(tr_torrent* tor, tr_variant* list)
errmsg = "labels cannot contain comma (,) character";
}
if (errmsg == nullptr)
if (errmsg == nullptr && labels.count(label) != 0)
{
bool dup = false;
for (int j = 0; j < labelcount; j++)
{
if (tr_strcmp0(label, (char*)tr_ptrArrayNth(&labels, j)) == 0)
{
dup = true;
break;
}
}
if (dup)
{
errmsg = "labels cannot contain duplicates";
}
errmsg = "labels cannot contain duplicates";
}
tr_ptrArrayAppend(&labels, label);
labelcount++;
labels.emplace(label);
tr_free(label);
if (errmsg != nullptr)
{
@ -1129,10 +1113,9 @@ static char const* setLabels(tr_torrent* tor, tr_variant* list)
if (errmsg == nullptr)
{
tr_torrentSetLabels(tor, &labels);
tr_torrentSetLabels(tor, std::move(labels));
}
tr_ptrArrayDestruct(&labels, tr_free);
return errmsg;
}

View File

@ -15,6 +15,7 @@
#include <cstdlib> /* qsort */
#include <cstring> /* memcmp */
#include <set>
#include <sstream>
#include <string>
#ifndef _WIN32
@ -42,7 +43,6 @@
#include "peer-common.h" /* MAX_BLOCK_SIZE */
#include "peer-mgr.h"
#include "platform.h" /* TR_PATH_DELIMITER_STR */
#include "ptrarray.h"
#include "resume.h"
#include "session.h"
#include "subprocess.h"
@ -867,7 +867,6 @@ static void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
tor->uniqueId = nextUniqueId++;
tor->magicNumber = TORRENT_MAGIC_NUMBER;
tor->queuePosition = tr_sessionCountTorrents(session);
tor->labels = {};
tr_sha1(tor->obfuscatedHash, "req2", 4, tor->info.hash, SHA_DIGEST_LENGTH, nullptr);
@ -1077,7 +1076,7 @@ tr_torrent* tr_torrentNew(tr_ctor const* ctor, int* setme_error, int* setme_dupl
if (r == TR_PARSE_OK)
{
tor = tr_new0(tr_torrent, 1);
tor = new tr_torrent{};
tor->info = tmpInfo;
if (hasInfo)
@ -1639,11 +1638,9 @@ static void freeTorrent(tr_torrent* tor)
TR_ASSERT(queueIsSequenced(session));
tr_bandwidthDestruct(&tor->bandwidth);
tr_ptrArrayDestruct(&tor->labels, tr_free);
tr_metainfoFree(inf);
memset(tor, ~0, sizeof(tr_torrent));
tr_free(tor);
delete tor;
tr_sessionUnlock(session);
}
@ -2109,6 +2106,23 @@ void tr_torrentClearIdleLimitHitCallback(tr_torrent* torrent)
tr_torrentSetIdleLimitHitCallback(torrent, nullptr, nullptr);
}
static std::string buildLabelsString(tr_torrent const* tor)
{
auto buf = std::stringstream{};
for (auto it = std::begin(tor->labels), end = std::end(tor->labels); it != end;)
{
buf << *it;
if (++it != end)
{
buf << ',';
}
}
return buf.str();
}
static void torrentCallScript(tr_torrent const* tor, char const* script)
{
if (tr_str_is_empty(script))
@ -2129,8 +2143,6 @@ static void torrentCallScript(tr_torrent const* tor, char const* script)
nullptr,
};
char* labels = tr_strjoin((char const* const*)tr_ptrArrayBase(&tor->labels), tr_ptrArraySize(&tor->labels), ",");
char* const env[] = {
tr_strdup_printf("TR_APP_VERSION=%s", SHORT_VERSION_STRING),
tr_strdup_printf("TR_TIME_LOCALTIME=%s", ctime_str),
@ -2138,7 +2150,7 @@ static void torrentCallScript(tr_torrent const* tor, char const* script)
tr_strdup_printf("TR_TORRENT_HASH=%s", tor->info.hashString),
tr_strdup_printf("TR_TORRENT_ID=%d", tr_torrentId(tor)),
tr_strdup_printf("TR_TORRENT_NAME=%s", tr_torrentName(tor)),
tr_strdup_printf("TR_TORRENT_LABELS=%s", labels),
tr_strdup_printf("TR_TORRENT_LABELS=%s", buildLabelsString(tor).c_str()),
nullptr,
};
@ -2154,7 +2166,6 @@ static void torrentCallScript(tr_torrent const* tor, char const* script)
tr_free_ptrv((void* const*)env);
tr_free_ptrv((void* const*)cmd);
tr_free(labels);
tr_free(torrent_dir);
}
@ -2412,21 +2423,13 @@ void tr_torrentSetFileDLs(tr_torrent* tor, tr_file_index_t const* files, tr_file
****
***/
void tr_torrentSetLabels(tr_torrent* tor, tr_ptrArray* labels)
void tr_torrentSetLabels(tr_torrent* tor, tr_labels_t&& labels)
{
TR_ASSERT(tr_isTorrent(tor));
tr_torrentLock(tor);
tr_ptrArrayDestruct(&tor->labels, tr_free);
tor->labels = {};
char** l = (char**)tr_ptrArrayBase(labels);
int const n = tr_ptrArraySize(labels);
for (int i = 0; i < n; i++)
{
tr_ptrArrayAppend(&tor->labels, tr_strdup(l[i]));
}
tor->labels = std::move(labels);
tr_torrentSetDirty(tor);
tr_torrentUnlock(tor);

View File

@ -12,13 +12,15 @@
#error only libtransmission should #include this header.
#endif
#include <string>
#include <unordered_set>
#include "bandwidth.h" /* tr_bandwidth */
#include "completion.h" /* tr_completion */
#include "session.h" /* tr_sessionLock(), tr_sessionUnlock() */
#include "tr-assert.h"
#include "tr-macros.h"
#include "utils.h" /* TR_GNUC_PRINTF */
#include "ptrarray.h"
struct tr_torrent_tiers;
struct tr_magnet_info;
@ -44,7 +46,9 @@ void tr_ctorInitTorrentWanted(tr_ctor const* ctor, tr_torrent* tor);
/* just like tr_torrentSetFileDLs but doesn't trigger a fastresume save */
void tr_torrentInitFileDLs(tr_torrent* tor, tr_file_index_t const* files, tr_file_index_t fileCount, bool do_download);
void tr_torrentSetLabels(tr_torrent* tor, tr_ptrArray* labels);
using tr_labels_t = std::unordered_set<std::string>;
void tr_torrentSetLabels(tr_torrent* tor, tr_labels_t&& labels);
void tr_torrentRecheckCompleteness(tr_torrent*);
@ -264,7 +268,7 @@ struct tr_torrent
tr_idlelimit idleLimitMode;
bool finishedSeedingByIdle;
tr_ptrArray labels;
tr_labels_t labels;
};
/* what piece index is this block in? */

View File

@ -608,37 +608,6 @@ char* tr_strsep(char** str, char const* delims)
#endif
}
char* tr_strjoin(char const* const* arr, size_t len, char const* delim)
{
size_t total_len = 1;
size_t delim_len = strlen(delim);
for (size_t i = 0; i < len; ++i)
{
total_len += strlen(arr[i]);
}
total_len += len > 0 ? (len - 1) * delim_len : 0;
char* const ret = tr_new(char, total_len);
char* p = ret;
for (size_t i = 0; i < len; ++i)
{
if (i > 0)
{
memcpy(p, delim, delim_len);
p += delim_len;
}
size_t const part_len = strlen(arr[i]);
memcpy(p, arr[i], part_len);
p += part_len;
}
*p = '\0';
return ret;
}
char* tr_strstrip(char* str)
{
if (str != nullptr)

View File

@ -250,9 +250,6 @@ char const* tr_strcasestr(char const* haystack, char const* needle);
/** @brief Portability wrapper for strsep() that uses the system implementation if available */
char* tr_strsep(char** str, char const* delim);
/** @brief Concatenates array of strings with delimiter in between elements */
char* tr_strjoin(char const* const* arr, size_t len, char const* delim);
/***
****
***/

View File

@ -68,29 +68,6 @@ TEST_F(UtilsTest, trStrstrip)
tr_free(in);
}
TEST_F(UtilsTest, trStrjoin)
{
auto const in1 = std::array<char const*, 2>{ "one", "two" };
auto out = makeString(tr_strjoin(in1.data(), in1.size(), ", "));
EXPECT_EQ("one, two", out);
auto const in2 = std::array<char const*, 1>{ "hello" };
out = makeString(tr_strjoin(in2.data(), in2.size(), "###"));
EXPECT_EQ("hello", out);
auto const in3 = std::array<char const*, 5>{ "a", "b", "ccc", "d", "eeeee" };
out = makeString(tr_strjoin(in3.data(), in3.size(), " "));
EXPECT_EQ("a b ccc d eeeee", out);
auto const in4 = std::array<char const*, 3>{ "7", "ate", "9" };
out = makeString(tr_strjoin(in4.data(), in4.size(), ""));
EXPECT_EQ("7ate9", out);
char const** in5 = nullptr;
out = makeString(tr_strjoin(in5, 0, "a"));
EXPECT_EQ("", out);
}
TEST_F(UtilsTest, trBuildpath)
{
auto out = makeString(tr_buildPath("foo", "bar", nullptr));