refactor: use std::string in tr_info (#2384)
This commit is contained in:
parent
79d244db82
commit
49f2823d6f
|
@ -50,7 +50,7 @@ std::string tr_buildTorrentFilename(
|
|||
|
||||
static std::string getTorrentFilename(tr_session const* session, tr_info const* inf, enum tr_metainfo_basename_format format)
|
||||
{
|
||||
return tr_buildTorrentFilename(tr_getTorrentDir(session), inf->name, inf->hashString, format, ".torrent"sv);
|
||||
return tr_buildTorrentFilename(tr_getTorrentDir(session), inf->name(), inf->infoHashString(), format, ".torrent"sv);
|
||||
}
|
||||
|
||||
/***
|
||||
|
@ -160,7 +160,7 @@ static char const* parseFiles(tr_info* inf, tr_variant* files, tr_variant const*
|
|||
inf->totalSize = 0;
|
||||
|
||||
auto root_name = std::string{};
|
||||
if (!tr_metainfoAppendSanitizedPathComponent(root_name, inf->name))
|
||||
if (!tr_metainfoAppendSanitizedPathComponent(root_name, inf->name()))
|
||||
{
|
||||
return "path";
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ static char const* parseFiles(tr_info* inf, tr_variant* files, tr_variant const*
|
|||
break;
|
||||
}
|
||||
|
||||
if (!getfile(&inf->files[i].subpath, root_name, path, buf))
|
||||
if (!getfile(&inf->files[i].subpath_, root_name, path, buf))
|
||||
{
|
||||
errstr = "path";
|
||||
break;
|
||||
|
@ -204,7 +204,7 @@ static char const* parseFiles(tr_info* inf, tr_variant* files, tr_variant const*
|
|||
break;
|
||||
}
|
||||
|
||||
inf->files[i].size = len;
|
||||
inf->files[i].size_ = len;
|
||||
inf->totalSize += len;
|
||||
}
|
||||
}
|
||||
|
@ -212,8 +212,8 @@ static char const* parseFiles(tr_info* inf, tr_variant* files, tr_variant const*
|
|||
{
|
||||
inf->isFolder = false;
|
||||
inf->files.resize(1);
|
||||
inf->files[0].subpath = root_name;
|
||||
inf->files[0].size = len;
|
||||
inf->files[0].subpath_ = root_name;
|
||||
inf->files[0].size_ = len;
|
||||
inf->totalSize += len;
|
||||
}
|
||||
else
|
||||
|
@ -358,25 +358,17 @@ static char const* tr_metainfoParseImpl(
|
|||
return "info_hash";
|
||||
}
|
||||
|
||||
if (std::size(sv) != std::size(inf->hash))
|
||||
if (std::size(sv) != std::size(inf->hash_))
|
||||
{
|
||||
return "info_hash";
|
||||
}
|
||||
|
||||
(void)memcpy(std::data(inf->hash), std::data(sv), std::size(sv));
|
||||
tr_sha1_to_string(inf->hash, inf->hashString);
|
||||
std::copy(std::begin(sv), std::end(sv), reinterpret_cast<char*>(std::data(inf->hash_)));
|
||||
inf->info_hash_string_ = tr_sha1_to_string(inf->hash_);
|
||||
|
||||
// maybe get the display name
|
||||
if (tr_variantDictFindStrView(d, TR_KEY_display_name, &sv))
|
||||
{
|
||||
tr_free(inf->name);
|
||||
inf->name = tr_strvDup(sv);
|
||||
}
|
||||
|
||||
if (inf->name == nullptr)
|
||||
{
|
||||
inf->name = tr_strdup(inf->hashString);
|
||||
}
|
||||
tr_variantDictFindStrView(d, TR_KEY_display_name, &sv);
|
||||
inf->setName(!std::empty(sv) ? sv : inf->info_hash_string_);
|
||||
}
|
||||
else // not a magnet link and has no info dict...
|
||||
{
|
||||
|
@ -392,8 +384,8 @@ static char const* tr_metainfoParseImpl(
|
|||
return "hash";
|
||||
}
|
||||
|
||||
inf->hash = *hash;
|
||||
tr_sha1_to_string(inf->hash, inf->hashString);
|
||||
inf->hash_ = *hash;
|
||||
inf->info_hash_string_ = tr_sha1_to_string(inf->hash_);
|
||||
|
||||
if (info_dict_size != nullptr)
|
||||
{
|
||||
|
@ -415,8 +407,7 @@ static char const* tr_metainfoParseImpl(
|
|||
return "name";
|
||||
}
|
||||
|
||||
tr_free(inf->name);
|
||||
inf->name = tr_utf8clean(sv);
|
||||
inf->name_ = tr_strvUtf8Clean(sv);
|
||||
}
|
||||
|
||||
/* comment */
|
||||
|
@ -425,8 +416,7 @@ static char const* tr_metainfoParseImpl(
|
|||
sv = ""sv;
|
||||
}
|
||||
|
||||
tr_free(inf->comment);
|
||||
inf->comment = tr_utf8clean(sv);
|
||||
inf->comment_ = tr_strvUtf8Clean(sv);
|
||||
|
||||
/* created by */
|
||||
if (!tr_variantDictFindStrView(meta, TR_KEY_created_by_utf_8, &sv) &&
|
||||
|
@ -435,13 +425,12 @@ static char const* tr_metainfoParseImpl(
|
|||
sv = ""sv;
|
||||
}
|
||||
|
||||
tr_free(inf->creator);
|
||||
inf->creator = tr_utf8clean(sv);
|
||||
inf->creator_ = tr_strvUtf8Clean(sv);
|
||||
|
||||
/* creation date */
|
||||
i = 0;
|
||||
(void)!tr_variantDictFindInt(meta, TR_KEY_creation_date, &i);
|
||||
inf->dateCreated = i;
|
||||
inf->date_created_ = i;
|
||||
|
||||
/* private */
|
||||
if (!tr_variantDictFindInt(infoDict, TR_KEY_private, &i) && !tr_variantDictFindInt(meta, TR_KEY_private, &i))
|
||||
|
@ -457,8 +446,7 @@ static char const* tr_metainfoParseImpl(
|
|||
sv = ""sv;
|
||||
}
|
||||
|
||||
tr_free(inf->source);
|
||||
inf->source = tr_utf8clean(sv);
|
||||
inf->source_ = tr_strvUtf8Clean(sv);
|
||||
|
||||
/* piece length */
|
||||
if (!isMagnet)
|
||||
|
@ -520,8 +508,7 @@ static char const* tr_metainfoParseImpl(
|
|||
geturllist(inf, meta);
|
||||
|
||||
/* filename of Transmission's copy */
|
||||
tr_free(inf->torrent);
|
||||
inf->torrent = session != nullptr ? tr_strvDup(getTorrentFilename(session, inf, TR_METAINFO_BASENAME_HASH)) : nullptr;
|
||||
inf->torrent_file_ = session != nullptr ? getTorrentFilename(session, inf, TR_METAINFO_BASENAME_HASH) : ""sv;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -551,18 +538,8 @@ void tr_metainfoFree(tr_info* inf)
|
|||
}
|
||||
}
|
||||
|
||||
tr_free(inf->comment);
|
||||
tr_free(inf->creator);
|
||||
tr_free(inf->name);
|
||||
tr_free(inf->source);
|
||||
tr_free(inf->torrent);
|
||||
tr_free(inf->webseeds);
|
||||
|
||||
inf->comment = nullptr;
|
||||
inf->creator = nullptr;
|
||||
inf->name = nullptr;
|
||||
inf->source = nullptr;
|
||||
inf->torrent = nullptr;
|
||||
inf->webseeds = nullptr;
|
||||
|
||||
inf->announce_list.reset();
|
||||
|
@ -589,7 +566,7 @@ void tr_metainfoMigrateFile(
|
|||
if (tr_sys_path_rename(old_filename.c_str(), new_filename.c_str(), nullptr))
|
||||
{
|
||||
tr_logAddNamedError(
|
||||
info->name,
|
||||
info->name().c_str(),
|
||||
"Migrated torrent file from \"%s\" to \"%s\"",
|
||||
old_filename.c_str(),
|
||||
new_filename.c_str());
|
||||
|
|
|
@ -484,12 +484,7 @@ static void addPeers(tr_torrent const* tor, tr_variant* list)
|
|||
tr_torrentPeersFree(peers, peerCount);
|
||||
}
|
||||
|
||||
static void initField(
|
||||
tr_torrent* const tor,
|
||||
tr_torrent_view const* view,
|
||||
tr_stat const* const st,
|
||||
tr_variant* const initme,
|
||||
tr_quark key)
|
||||
static void initField(tr_torrent* const tor, tr_stat const* const st, tr_variant* const initme, tr_quark key)
|
||||
{
|
||||
char* str = nullptr;
|
||||
|
||||
|
@ -508,7 +503,7 @@ static void initField(
|
|||
break;
|
||||
|
||||
case TR_KEY_comment:
|
||||
tr_variantInitStr(initme, std::string_view{ view->comment != nullptr ? view->comment : "" });
|
||||
tr_variantInitStr(initme, tor->comment());
|
||||
break;
|
||||
|
||||
case TR_KEY_corruptEver:
|
||||
|
@ -516,11 +511,11 @@ static void initField(
|
|||
break;
|
||||
|
||||
case TR_KEY_creator:
|
||||
tr_variantInitStr(initme, std::string_view{ view->creator != nullptr ? view->creator : "" });
|
||||
tr_variantInitStrView(initme, tor->creator());
|
||||
break;
|
||||
|
||||
case TR_KEY_dateCreated:
|
||||
tr_variantInitInt(initme, view->date_created);
|
||||
tr_variantInitInt(initme, tor->dateCreated());
|
||||
break;
|
||||
|
||||
case TR_KEY_desiredAvailable:
|
||||
|
@ -692,11 +687,11 @@ static void initField(
|
|||
break;
|
||||
|
||||
case TR_KEY_pieceCount:
|
||||
tr_variantInitInt(initme, view->n_pieces);
|
||||
tr_variantInitInt(initme, tor->pieceCount());
|
||||
break;
|
||||
|
||||
case TR_KEY_pieceSize:
|
||||
tr_variantInitInt(initme, view->piece_size);
|
||||
tr_variantInitInt(initme, tor->pieceSize());
|
||||
break;
|
||||
|
||||
case TR_KEY_primary_mime_type:
|
||||
|
@ -755,7 +750,7 @@ static void initField(
|
|||
break;
|
||||
|
||||
case TR_KEY_source:
|
||||
tr_variantDictAddStr(initme, key, view->source ? view->source : "");
|
||||
tr_variantInitStrView(initme, tor->source());
|
||||
break;
|
||||
|
||||
case TR_KEY_startDate:
|
||||
|
@ -792,11 +787,11 @@ static void initField(
|
|||
}
|
||||
|
||||
case TR_KEY_torrentFile:
|
||||
tr_variantInitStr(initme, view->torrent_filename);
|
||||
tr_variantInitStrView(initme, tor->torrentFile());
|
||||
break;
|
||||
|
||||
case TR_KEY_totalSize:
|
||||
tr_variantInitInt(initme, view->total_size);
|
||||
tr_variantInitInt(initme, tor->totalSize());
|
||||
break;
|
||||
|
||||
case TR_KEY_uploadedEver:
|
||||
|
@ -853,14 +848,13 @@ static void addTorrentInfo(tr_torrent* tor, tr_format format, tr_variant* entry,
|
|||
|
||||
if (fieldCount > 0)
|
||||
{
|
||||
auto const torrent_view = tr_torrentView(tor);
|
||||
tr_stat const* const st = tr_torrentStat(tor);
|
||||
|
||||
for (size_t i = 0; i < fieldCount; ++i)
|
||||
{
|
||||
tr_variant* child = format == TR_FORMAT_TABLE ? tr_variantListAdd(entry) : tr_variantDictAdd(entry, fields[i]);
|
||||
|
||||
initField(tor, &torrent_view, st, child, fields[i]);
|
||||
initField(tor, st, child, fields[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <climits> /* INT_MAX */
|
||||
#include <cstring> /* memcpy(), memset(), memcmp() */
|
||||
#include <ctime>
|
||||
|
@ -168,7 +169,7 @@ void* tr_torrentGetMetadataPiece(tr_torrent* tor, int piece, size_t* len)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
auto const fd = tr_sys_file_open(tor->torrentFile(), TR_SYS_FILE_READ, 0, nullptr);
|
||||
auto const fd = tr_sys_file_open(tor->torrentFile().c_str(), TR_SYS_FILE_READ, 0, nullptr);
|
||||
if (fd == TR_BAD_SYS_FILE)
|
||||
{
|
||||
return nullptr;
|
||||
|
@ -261,7 +262,7 @@ void tr_torrentSetMetadataPiece(tr_torrent* tor, int piece, void const* data, in
|
|||
}
|
||||
|
||||
size_t const offset = piece * METADATA_PIECE_SIZE;
|
||||
memcpy(m->metadata + offset, data, len);
|
||||
std::copy_n(reinterpret_cast<char const*>(data), len, m->metadata + offset);
|
||||
|
||||
tr_removeElementFromArray(m->piecesNeeded, idx, sizeof(struct metadata_node), m->piecesNeededCount);
|
||||
--m->piecesNeededCount;
|
||||
|
@ -288,15 +289,15 @@ void tr_torrentSetMetadataPiece(tr_torrent* tor, int piece, void const* data, in
|
|||
{
|
||||
/* yay we have bencoded metainfo... merge it into our .torrent file */
|
||||
tr_variant newMetainfo;
|
||||
char* path = tr_strdup(tor->torrentFile());
|
||||
auto const path = tor->torrentFile();
|
||||
|
||||
if (tr_variantFromFile(&newMetainfo, TR_VARIANT_PARSE_BENC, path, nullptr))
|
||||
{
|
||||
/* remove any old .torrent and .resume files */
|
||||
tr_sys_path_remove(path, nullptr);
|
||||
tr_sys_path_remove(path.c_str(), nullptr);
|
||||
tr_torrentRemoveResume(tor);
|
||||
|
||||
dbgmsg(tor, "Saving completed metadata to \"%s\"", path);
|
||||
dbgmsg(tor, "Saving completed metadata to \"%s\"", path.c_str());
|
||||
tr_variantMergeDicts(tr_variantDictAddDict(&newMetainfo, TR_KEY_info, 0), &infoDict);
|
||||
|
||||
auto info = tr_metainfoParse(tor->session, &newMetainfo, nullptr);
|
||||
|
@ -322,7 +323,6 @@ void tr_torrentSetMetadataPiece(tr_torrent* tor, int piece, void const* data, in
|
|||
}
|
||||
|
||||
tr_variantFree(&infoDict);
|
||||
tr_free(path);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -394,10 +394,10 @@ char* tr_torrentInfoGetMagnetLink(tr_info const* inf)
|
|||
auto buf = std::string{};
|
||||
|
||||
buf += "magnet:?xt=urn:btih:"sv;
|
||||
buf += inf->hashString;
|
||||
buf += inf->infoHashString();
|
||||
|
||||
char const* const name = inf->name;
|
||||
if (!tr_str_is_empty(name))
|
||||
auto const& name = inf->name();
|
||||
if (!std::empty(name))
|
||||
{
|
||||
buf += "&dn="sv;
|
||||
tr_http_escape(buf, name, true);
|
||||
|
|
|
@ -77,7 +77,7 @@ using namespace std::literals;
|
|||
|
||||
char const* tr_torrentName(tr_torrent const* tor)
|
||||
{
|
||||
return tor != nullptr ? tor->info.name : "";
|
||||
return tor != nullptr ? tor->name().c_str() : "";
|
||||
}
|
||||
|
||||
uint64_t tr_torrentTotalSize(tr_torrent const* tor)
|
||||
|
@ -727,7 +727,7 @@ static void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
|
|||
tr_sessionAddTorrent(session, tor);
|
||||
|
||||
/* if we don't have a local .torrent file already, assume the torrent is new */
|
||||
bool const isNewTorrent = !tr_sys_path_exists(tor->torrentFile(), nullptr);
|
||||
bool const isNewTorrent = !tr_sys_path_exists(tor->torrentFile().c_str(), nullptr);
|
||||
|
||||
/* maybe save our own copy of the metainfo */
|
||||
if (tr_ctorGetSave(ctor))
|
||||
|
@ -787,7 +787,7 @@ tr_torrent* tr_torrentNew(tr_ctor const* ctor, tr_torrent** setme_duplicate_of)
|
|||
}
|
||||
|
||||
// is it a duplicate?
|
||||
if (auto* const duplicate_of = session->getTorrent(parsed->info.hash); duplicate_of != nullptr)
|
||||
if (auto* const duplicate_of = session->getTorrent(parsed->info.infoHash()); duplicate_of != nullptr)
|
||||
{
|
||||
if (setme_duplicate_of != nullptr)
|
||||
{
|
||||
|
@ -1158,13 +1158,13 @@ tr_torrent_view tr_torrentView(tr_torrent const* tor)
|
|||
|
||||
auto ret = tr_torrent_view{};
|
||||
ret.name = tr_torrentName(tor);
|
||||
ret.hash_string = tor->infoHashString();
|
||||
ret.torrent_filename = tor->torrentFile();
|
||||
ret.comment = tor->info.comment;
|
||||
ret.creator = tor->info.creator;
|
||||
ret.source = tor->info.source;
|
||||
ret.hash_string = tor->infoHashString().c_str();
|
||||
ret.torrent_filename = tor->torrentFile().c_str();
|
||||
ret.comment = tor->info.comment().c_str();
|
||||
ret.creator = tor->info.creator().c_str();
|
||||
ret.source = tor->info.source().c_str();
|
||||
ret.total_size = tor->totalSize();
|
||||
ret.date_created = tor->info.dateCreated;
|
||||
ret.date_created = tor->dateCreated();
|
||||
ret.piece_size = tor->pieceSize();
|
||||
ret.n_pieces = tor->pieceCount();
|
||||
ret.is_private = tor->isPrivate();
|
||||
|
@ -1983,7 +1983,7 @@ bool tr_torrentReqIsValid(tr_torrent const* tor, tr_piece_index_t index, uint32_
|
|||
}
|
||||
|
||||
// TODO(ckerr) migrate to fpm?
|
||||
tr_block_span_t tr_torGetFileBlockSpan(tr_torrent const* tor, tr_file_index_t const i)
|
||||
tr_block_span_t tr_torGetFileBlockSpan(tr_torrent const* tor, tr_file_index_t i)
|
||||
{
|
||||
auto const [begin_byte, end_byte] = tor->fpm_.byteSpan(i);
|
||||
|
||||
|
@ -3114,16 +3114,10 @@ void tr_torrent::setBlocks(tr_bitfield blocks)
|
|||
|
||||
void tr_torrent::setName(std::string_view name)
|
||||
{
|
||||
if (name == this->info.name)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tr_free(this->info.name);
|
||||
this->info.name = tr_strvDup(name);
|
||||
this->info.setName(name);
|
||||
}
|
||||
|
||||
void tr_torrent::setFileSubpath(tr_file_index_t i, std::string_view subpath)
|
||||
{
|
||||
this->info.files[i].subpath = subpath;
|
||||
this->info.setFileSubpath(i, subpath);
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ void tr_torrentGetBlockLocation(
|
|||
uint32_t* offset,
|
||||
uint32_t* length);
|
||||
|
||||
tr_block_span_t tr_torGetFileBlockSpan(tr_torrent const* tor, tr_file_index_t const file);
|
||||
tr_block_span_t tr_torGetFileBlockSpan(tr_torrent const* tor, tr_file_index_t file);
|
||||
|
||||
void tr_torrentCheckSeedLimit(tr_torrent* tor);
|
||||
|
||||
|
@ -449,9 +449,14 @@ public:
|
|||
|
||||
void setName(std::string_view name);
|
||||
|
||||
[[nodiscard]] auto const& name() const
|
||||
{
|
||||
return this->info.name();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto const& infoHash() const
|
||||
{
|
||||
return this->info.hash;
|
||||
return this->info.infoHash();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto isPrivate() const
|
||||
|
@ -464,14 +469,34 @@ public:
|
|||
return !this->isPrivate();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto infoHashString() const
|
||||
[[nodiscard]] auto const& infoHashString() const
|
||||
{
|
||||
return this->info.hashString;
|
||||
return this->info.infoHashString();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto dateCreated() const
|
||||
{
|
||||
return this->info.dateCreated();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto const& torrentFile() const
|
||||
{
|
||||
return this->info.torrent;
|
||||
return this->info.torrentFile();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto const& comment() const
|
||||
{
|
||||
return this->info.comment();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto const& creator() const
|
||||
{
|
||||
return this->info.creator();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto const& source() const
|
||||
{
|
||||
return this->info.source();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto hasMetadata() const
|
||||
|
|
|
@ -276,7 +276,8 @@ int tr_lpdInit(tr_session* ss, tr_address* /*tr_addr*/)
|
|||
* string handling in tr_lpdSendAnnounce() and tr_lpdConsiderAnnounce().
|
||||
* However, the code should work as long as interfaces to the rest of
|
||||
* libtransmission are compatible with char* strings. */
|
||||
static_assert(std::is_same_v<char const, std::remove_pointer_t<decltype(std::declval<tr_torrent>().infoHashString())>>);
|
||||
static_assert(
|
||||
std::is_same_v<std::string const&, std::remove_pointer_t<decltype(std::declval<tr_torrent>().infoHashString())>>);
|
||||
|
||||
struct ip_mreq mcastReq;
|
||||
int const opt_on = 1;
|
||||
|
@ -456,7 +457,7 @@ bool tr_lpdEnabled(tr_session const* ss)
|
|||
*/
|
||||
bool tr_lpdSendAnnounce(tr_torrent const* t)
|
||||
{
|
||||
char const fmt[] = //
|
||||
char constexpr fmt[] = //
|
||||
"BT-SEARCH * HTTP/%u.%u" CRLF //
|
||||
"Host: %s:%u" CRLF //
|
||||
"Port: %u" CRLF //
|
||||
|
@ -464,23 +465,17 @@ bool tr_lpdSendAnnounce(tr_torrent const* t)
|
|||
"" CRLF //
|
||||
"" CRLF;
|
||||
|
||||
char hashString[SIZEOF_HASH_STRING];
|
||||
char query[lpd_maxDatagramLength + 1] = { 0 };
|
||||
|
||||
if (t == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* make sure the hash string is normalized, just in case */
|
||||
auto const* const sourceHashString = t->infoHashString();
|
||||
for (size_t i = 0; i < TR_N_ELEMENTS(hashString); ++i)
|
||||
{
|
||||
hashString[i] = toupper(sourceHashString[i]);
|
||||
}
|
||||
/* ensure the hash string is capitalized */
|
||||
auto const hash_string = tr_strupper(t->infoHashString());
|
||||
|
||||
/* prepare a zero-terminated announce message */
|
||||
tr_snprintf(query, lpd_maxDatagramLength + 1, fmt, 1, 1, lpd_mcastGroup, lpd_mcastPort, lpd_port, hashString);
|
||||
char query[lpd_maxDatagramLength + 1] = { 0 };
|
||||
tr_snprintf(query, lpd_maxDatagramLength + 1, fmt, 1, 1, lpd_mcastGroup, lpd_mcastPort, lpd_port, hash_string.c_str());
|
||||
|
||||
/* actually send the query out using [lpd_socket2] */
|
||||
{
|
||||
|
@ -488,7 +483,7 @@ bool tr_lpdSendAnnounce(tr_torrent const* t)
|
|||
|
||||
/* destination address info has already been set up in tr_lpdInit(),
|
||||
* so we refrain from preparing another sockaddr_in here */
|
||||
int res = sendto(lpd_socket2, query, len, 0, (struct sockaddr const*)&lpd_mcastAddr, sizeof(lpd_mcastAddr));
|
||||
int const res = sendto(lpd_socket2, query, len, 0, (struct sockaddr const*)&lpd_mcastAddr, sizeof(lpd_mcastAddr));
|
||||
|
||||
if (res != len)
|
||||
{
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
***/
|
||||
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
|
||||
#include <stdbool.h> /* bool */
|
||||
#include <stddef.h> /* size_t */
|
||||
#include <stdint.h> /* uintN_t */
|
||||
|
@ -1502,8 +1504,8 @@ void tr_torrentVerify(tr_torrent* torrent, tr_verify_done_func callback_func_or_
|
|||
struct tr_file
|
||||
{
|
||||
// public
|
||||
std::string subpath; /* Path to the file */
|
||||
uint64_t size; /* Length of the file, in bytes */
|
||||
std::string subpath_; /* Path to the file */
|
||||
uint64_t size_; /* Length of the file, in bytes */
|
||||
};
|
||||
|
||||
/** @brief information about a torrent that comes from its metainfo file */
|
||||
|
@ -1513,18 +1515,53 @@ struct tr_info
|
|||
uint64_t totalSize;
|
||||
|
||||
/* The torrent's name. */
|
||||
char* name;
|
||||
std::string name_;
|
||||
|
||||
/* Path to torrent Transmission's internal copy of the .torrent file. */
|
||||
char* torrent;
|
||||
std::string torrent_file_;
|
||||
|
||||
char** webseeds;
|
||||
|
||||
char* comment;
|
||||
char* creator;
|
||||
std::string comment_;
|
||||
std::string creator_;
|
||||
|
||||
/* torrent's source. empty if not set. */
|
||||
char* source;
|
||||
std::string source_;
|
||||
|
||||
auto const& torrentFile() const
|
||||
{
|
||||
return torrent_file_;
|
||||
}
|
||||
|
||||
auto const& name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
auto const& creator() const
|
||||
{
|
||||
return creator_;
|
||||
}
|
||||
|
||||
auto const& comment() const
|
||||
{
|
||||
return comment_;
|
||||
}
|
||||
|
||||
auto const& source() const
|
||||
{
|
||||
return source_;
|
||||
}
|
||||
|
||||
auto const& infoHash() const
|
||||
{
|
||||
return hash_;
|
||||
}
|
||||
|
||||
void setName(std::string_view name)
|
||||
{
|
||||
name_ = name;
|
||||
}
|
||||
|
||||
// Private.
|
||||
// Use tr_torrentFile() and tr_torrentFileCount() instead.
|
||||
|
@ -1537,27 +1574,42 @@ struct tr_info
|
|||
|
||||
std::string const& fileSubpath(tr_file_index_t i) const
|
||||
{
|
||||
return files[i].subpath;
|
||||
return files[i].subpath_;
|
||||
}
|
||||
|
||||
void setFileSubpath(tr_file_index_t i, std::string_view subpath)
|
||||
{
|
||||
files[i].subpath_ = subpath;
|
||||
}
|
||||
|
||||
auto fileSize(tr_file_index_t i) const
|
||||
{
|
||||
return files[i].size;
|
||||
return files[i].size_;
|
||||
}
|
||||
|
||||
auto const& infoHashString() const
|
||||
{
|
||||
return info_hash_string_;
|
||||
}
|
||||
|
||||
auto dateCreated() const
|
||||
{
|
||||
return date_created_;
|
||||
}
|
||||
|
||||
// TODO(ckerr) aggregate this directly, rather than using a shared_ptr, when tr_info is private
|
||||
std::shared_ptr<tr_announce_list> announce_list;
|
||||
|
||||
/* Torrent info */
|
||||
time_t dateCreated;
|
||||
time_t date_created_;
|
||||
|
||||
unsigned int webseedCount;
|
||||
uint32_t pieceSize;
|
||||
tr_piece_index_t pieceCount;
|
||||
|
||||
/* General info */
|
||||
tr_sha1_digest_t hash;
|
||||
char hashString[2 * SHA_DIGEST_LENGTH + 1];
|
||||
tr_sha1_digest_t hash_;
|
||||
std::string info_hash_string_;
|
||||
|
||||
/* Flags */
|
||||
bool isPrivate;
|
||||
|
|
|
@ -820,13 +820,6 @@ static char* to_utf8(std::string_view sv)
|
|||
return strip_non_utf8(sv);
|
||||
}
|
||||
|
||||
char* tr_utf8clean(std::string_view sv)
|
||||
{
|
||||
char* const ret = tr_utf8_validate(sv, nullptr) ? tr_strvDup(sv) : to_utf8(sv);
|
||||
TR_ASSERT(tr_utf8_validate(ret, nullptr));
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string tr_strvUtf8Clean(std::string_view sv)
|
||||
{
|
||||
if (tr_utf8_validate(sv, nullptr))
|
||||
|
|
|
@ -164,13 +164,6 @@ std::optional<T> tr_parseNum(std::string_view& sv)
|
|||
|
||||
#endif // #if defined(__GNUC__) && !__has_include(<charconv>)
|
||||
|
||||
/**
|
||||
* @brief make a copy of 'str' whose non-utf8 content has been corrected or stripped
|
||||
* @return a newly-allocated string that must be freed with tr_free()
|
||||
* @param str the string to make a clean copy of
|
||||
*/
|
||||
char* tr_utf8clean(std::string_view str) TR_GNUC_MALLOC;
|
||||
|
||||
bool tr_utf8_validate(std::string_view sv, char const** endptr);
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -300,6 +293,14 @@ std::string tr_strlower(T in)
|
|||
return out;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::string tr_strupper(T in)
|
||||
{
|
||||
auto out = std::string{ in };
|
||||
std::for_each(std::begin(out), std::end(out), [](char& ch) { ch = std::toupper(ch); });
|
||||
return out;
|
||||
}
|
||||
|
||||
/***
|
||||
**** std::string_view utils
|
||||
***/
|
||||
|
|
|
@ -387,9 +387,9 @@ TEST_F(AnnounceListTest, save)
|
|||
tr_variantFree(&metainfo);
|
||||
|
||||
// test that non-announce parts of the metainfo are the same
|
||||
EXPECT_STREQ(original->info.name, saved->info.name);
|
||||
EXPECT_EQ(original->info.name(), saved->info.name());
|
||||
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);
|
||||
|
||||
// test that the saved version has the updated announce list
|
||||
|
|
|
@ -264,7 +264,6 @@ TEST_F(RenameTest, multifileTorrent)
|
|||
"MjpwaWVjZSBsZW5ndGhpMzI3NjhlNjpwaWVjZXMyMDp27buFkmy8ICfNX4nsJmt0Ckm2Ljc6cHJp"
|
||||
"dmF0ZWkwZWVl");
|
||||
EXPECT_TRUE(tr_isTorrent(tor));
|
||||
auto& files = tor->info.files;
|
||||
|
||||
// sanity check the info
|
||||
EXPECT_STREQ("Felidae", tr_torrentName(tor));
|
||||
|
@ -320,7 +319,7 @@ TEST_F(RenameTest, multifileTorrent)
|
|||
// (while the branch is renamed: confirm that the .resume file remembers the changes)
|
||||
tr_torrentSaveResume(tor);
|
||||
// this is a bit dodgy code-wise, but let's make sure the .resume file got the name
|
||||
files[1].subpath = "gabba gabba hey";
|
||||
tor->setFileSubpath(1, "gabba gabba hey"sv);
|
||||
auto const loaded = tr_torrentLoadResume(tor, ~0ULL, ctor, nullptr);
|
||||
EXPECT_NE(decltype(loaded){ 0 }, (loaded & TR_FR_FILENAMES));
|
||||
EXPECT_EQ(expected_files[0], tr_torrentFile(tor, 0).name);
|
||||
|
|
|
@ -158,42 +158,6 @@ TEST_F(UtilsTest, trStrvPath)
|
|||
tr_strvPath("foo"sv, "bar", std::string{ "baz" }, "mum"sv));
|
||||
}
|
||||
|
||||
TEST_F(UtilsTest, trUtf8clean)
|
||||
{
|
||||
auto in = "hello world"sv;
|
||||
auto out = makeString(tr_utf8clean(in));
|
||||
EXPECT_EQ(in, out);
|
||||
|
||||
in = "hello world"sv;
|
||||
out = makeString(tr_utf8clean(in.substr(0, 5)));
|
||||
EXPECT_EQ("hello"sv, out);
|
||||
|
||||
// this version is not utf-8 (but cp866)
|
||||
in = "\x92\xE0\xE3\xA4\xAD\xAE \xA1\xEB\xE2\xEC \x81\xAE\xA3\xAE\xAC"sv;
|
||||
out = makeString(tr_utf8clean(in));
|
||||
EXPECT_TRUE(std::size(out) == 17 || std::size(out) == 33);
|
||||
EXPECT_TRUE(tr_utf8_validate(out, nullptr));
|
||||
|
||||
// same string, but utf-8 clean
|
||||
in = "Трудно быть Богом"sv;
|
||||
out = makeString(tr_utf8clean(in));
|
||||
EXPECT_NE(nullptr, out.data());
|
||||
EXPECT_TRUE(tr_utf8_validate(out, nullptr));
|
||||
EXPECT_EQ(in, out);
|
||||
|
||||
in = "\xF4\x00\x81\x82"sv;
|
||||
out = makeString(tr_utf8clean(in));
|
||||
EXPECT_NE(nullptr, out.data());
|
||||
EXPECT_TRUE(out.size() == 1 || out.size() == 2);
|
||||
EXPECT_TRUE(tr_utf8_validate(out, nullptr));
|
||||
|
||||
in = "\xF4\x33\x81\x82"sv;
|
||||
out = makeString(tr_utf8clean(in));
|
||||
EXPECT_NE(nullptr, out.data());
|
||||
EXPECT_TRUE(out.size() == 4 || out.size() == 7);
|
||||
EXPECT_TRUE(tr_utf8_validate(out, nullptr));
|
||||
}
|
||||
|
||||
TEST_F(UtilsTest, trStrvUtf8Clean)
|
||||
{
|
||||
auto in = "hello world"sv;
|
||||
|
|
Loading…
Reference in New Issue