diff --git a/libtransmission/announcer.h b/libtransmission/announcer.h index 2853a8e89..c35ac7b0c 100644 --- a/libtransmission/announcer.h +++ b/libtransmission/announcer.h @@ -16,7 +16,7 @@ #include "transmission.h" -#include "quark.h" +#include "interned-string.h" struct tr_announcer; struct tr_announcer_tiers; diff --git a/libtransmission/file-piece-map.cc b/libtransmission/file-piece-map.cc index 663c1830b..d9b1be941 100644 --- a/libtransmission/file-piece-map.cc +++ b/libtransmission/file-piece-map.cc @@ -59,7 +59,7 @@ void tr_file_piece_map::reset(tr_info const& info) { 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)); } tr_file_piece_map::piece_span_t tr_file_piece_map::pieceSpan(tr_file_index_t file) const diff --git a/libtransmission/magnet-metainfo.cc b/libtransmission/magnet-metainfo.cc index 028a95494..e86e8ce2e 100644 --- a/libtransmission/magnet-metainfo.cc +++ b/libtransmission/magnet-metainfo.cc @@ -239,14 +239,14 @@ void tr_magnet_metainfo::toVariant(tr_variant* top) const } // webseeds - n = std::size(this->webseeds()); + n = this->webseedCount(); if (n != 0) { tr_variant* list = tr_variantDictAddList(top, TR_KEY_url_list, n); - for (auto& url : this->webseeds()) + for (size_t i = 0; i < n; ++i) { - tr_variantListAddStr(list, url); + tr_variantListAddStr(list, this->webseed(i)); } } diff --git a/libtransmission/magnet-metainfo.h b/libtransmission/magnet-metainfo.h index d04345951..5b2512f96 100644 --- a/libtransmission/magnet-metainfo.h +++ b/libtransmission/magnet-metainfo.h @@ -34,9 +34,15 @@ public: { return name_; } - auto const& webseeds() const + + auto webseedCount() const { - return webseed_urls_; + return std::size(webseed_urls_); + } + + auto const& webseed(size_t i) const + { + return webseed_urls_[i]; } auto& announceList() diff --git a/libtransmission/metainfo.cc b/libtransmission/metainfo.cc index ddf467a89..16ee014fc 100644 --- a/libtransmission/metainfo.cc +++ b/libtransmission/metainfo.cc @@ -151,7 +151,7 @@ static bool getfile(std::string* setme, std::string_view root, tr_variant* path, static char const* parseFiles(tr_info* inf, tr_variant* files, tr_variant const* length) { int64_t len = 0; - inf->totalSize = 0; + inf->total_size_ = 0; auto root_name = std::string{}; if (!tr_metainfoAppendSanitizedPathComponent(root_name, inf->name())) @@ -166,7 +166,6 @@ static char const* parseFiles(tr_info* inf, tr_variant* files, tr_variant const* auto buf = std::string{}; errstr = nullptr; - inf->isFolder = true; tr_file_index_t const n = tr_variantListSize(files); inf->files.resize(n); for (tr_file_index_t i = 0; i < n; ++i) @@ -199,16 +198,15 @@ static char const* parseFiles(tr_info* inf, tr_variant* files, tr_variant const* } inf->files[i].size_ = len; - inf->totalSize += len; + inf->total_size_ += len; } } else if (tr_variantGetInt(length, &len)) /* single-file mode */ { - inf->isFolder = false; inf->files.resize(1); inf->files[0].subpath_ = root_name; inf->files[0].size_ = len; - inf->totalSize += len; + inf->total_size_ += len; } else { @@ -289,24 +287,22 @@ static char* fix_webseed_url(tr_info const* inf, std::string_view url) static void geturllist(tr_info* inf, tr_variant* meta) { - tr_variant* urls = nullptr; - auto url = std::string_view{}; + inf->webseeds_.clear(); + auto url = std::string_view{}; + tr_variant* urls = nullptr; if (tr_variantDictFindList(meta, TR_KEY_url_list, &urls)) { int const n = tr_variantListSize(urls); - inf->webseedCount = 0; - inf->webseeds = tr_new0(char*, n); - - for (int i = 0; i < n; i++) + for (int i = 0; i < n; ++i) { if (tr_variantGetStrView(tr_variantListChild(urls, i), &url)) { char* const fixed_url = fix_webseed_url(inf, url); if (fixed_url != nullptr) { - inf->webseeds[inf->webseedCount++] = fixed_url; + inf->webseeds_.emplace_back(fixed_url); } } } @@ -316,9 +312,7 @@ static void geturllist(tr_info* inf, tr_variant* meta) char* const fixed_url = fix_webseed_url(inf, url); if (fixed_url != nullptr) { - inf->webseedCount = 1; - inf->webseeds = tr_new0(char*, 1); - inf->webseeds[0] = fixed_url; + inf->webseeds_.emplace_back(fixed_url); } } } @@ -432,7 +426,7 @@ static char const* tr_metainfoParseImpl( i = 0; } - inf->isPrivate = i != 0; + inf->is_private_ = i != 0; /* source */ if (!tr_variantDictFindStrView(infoDict, TR_KEY_source, &sv) && !tr_variantDictFindStrView(meta, TR_KEY_source, &sv)) @@ -450,7 +444,7 @@ static char const* tr_metainfoParseImpl( return "piece length"; } - inf->pieceSize = i; + inf->piece_size_ = i; } /* pieces and files */ @@ -467,7 +461,7 @@ static char const* tr_metainfoParseImpl( } auto const n_pieces = std::size(sv) / std::size(tr_sha1_digest_t{}); - inf->pieceCount = n_pieces; + inf->piece_count_ = n_pieces; pieces->resize(n_pieces); std::copy_n(std::data(sv), std::size(sv), reinterpret_cast(std::data(*pieces))); @@ -480,12 +474,12 @@ static char const* tr_metainfoParseImpl( return errstr; } - if (inf->fileCount() == 0 || inf->totalSize == 0) + if (inf->fileCount() == 0 || inf->total_size_ == 0) { return "files"; } - if ((uint64_t)inf->pieceCount != (inf->totalSize + inf->pieceSize - 1) / inf->pieceSize) + if ((uint64_t)inf->piece_count_ != (inf->total_size_ + inf->piece_size_ - 1) / inf->piece_size_) { return "files"; } @@ -524,17 +518,6 @@ std::optional tr_metainfoParse(tr_session const* session, tr void tr_metainfoFree(tr_info* inf) { - if (inf->webseeds != nullptr) - { - for (unsigned int i = 0; i < inf->webseedCount; i++) - { - tr_free(inf->webseeds[i]); - } - } - - tr_free(inf->webseeds); - - inf->webseeds = nullptr; - + inf->webseeds_.clear(); inf->announce_list.reset(); } diff --git a/libtransmission/peer-common.h b/libtransmission/peer-common.h index cdae9d6ef..e2fda1ee7 100644 --- a/libtransmission/peer-common.h +++ b/libtransmission/peer-common.h @@ -13,9 +13,10 @@ #endif #include "transmission.h" + #include "bitfield.h" #include "history.h" -#include "quark.h" +#include "interned-string.h" /** * @addtogroup peers Peers diff --git a/libtransmission/torrent-magnet.cc b/libtransmission/torrent-magnet.cc index 874fdfb5c..1c6f5454e 100644 --- a/libtransmission/torrent-magnet.cc +++ b/libtransmission/torrent-magnet.cc @@ -302,7 +302,7 @@ void tr_torrentSetMetadataPiece(tr_torrent* tor, int piece, void const* data, in auto info = tr_metainfoParse(tor->session, &newMetainfo, nullptr); success = !!info; - if (info && tr_block_info::bestBlockSize(info->info.pieceSize) == 0) + if (info && tr_block_info::bestBlockSize(info->info.pieceSize()) == 0) { tor->setLocalError(_("Magnet torrent's metadata is not usable")); success = false; @@ -409,10 +409,10 @@ char* tr_torrentInfoGetMagnetLink(tr_info const* inf) tr_http_escape(buf, inf->announce_list->at(i).announce.full, true); } - for (unsigned int i = 0; i < inf->webseedCount; i++) + for (size_t i = 0, n = inf->webseedCount(); i < n; ++i) { buf += "&ws="sv; - tr_http_escape(buf, inf->webseeds[i], true); + tr_http_escape(buf, inf->webseed(i), true); } return tr_strvDup(buf); diff --git a/libtransmission/torrent.cc b/libtransmission/torrent.cc index 6c25db795..6ce072d86 100644 --- a/libtransmission/torrent.cc +++ b/libtransmission/torrent.cc @@ -561,7 +561,7 @@ static void tr_torrentFireMetadataCompleted(tr_torrent* tor); static void torrentInitFromInfoDict(tr_torrent* tor) { - tor->block_info.initSizes(tor->info.totalSize, tor->info.pieceSize); + tor->block_info.initSizes(tor->info.totalSize(), tor->info.pieceSize()); tor->completion = tr_completion{ tor, &tor->block_info }; auto const obfuscated = tr_sha1("req2"sv, tor->infoHash()); if (obfuscated) diff --git a/libtransmission/torrent.h b/libtransmission/torrent.h index 784128919..9cc7b6e4f 100644 --- a/libtransmission/torrent.h +++ b/libtransmission/torrent.h @@ -109,7 +109,7 @@ struct tr_torrent : public tr_completion::torrent_view { public: explicit tr_torrent(tr_info const& inf) - : block_info{ inf.totalSize, inf.pieceSize } + : block_info{ inf.totalSize(), inf.pieceSize() } , completion{ this, &this->block_info } { } @@ -435,14 +435,12 @@ public: [[nodiscard]] auto webseedCount() const { - return info.webseedCount; + return info.webseedCount(); } [[nodiscard]] auto const& webseed(size_t i) const { - TR_ASSERT(i < webseedCount()); - - return info.webseeds[i]; + return info.webseed(i); } /// METAINFO - OTHER @@ -461,7 +459,7 @@ public: [[nodiscard]] auto isPrivate() const { - return this->info.isPrivate; + return this->info.isPrivate(); } [[nodiscard]] auto isPublic() const diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h index 2795e3c06..aa80a58fe 100644 --- a/libtransmission/transmission.h +++ b/libtransmission/transmission.h @@ -21,7 +21,9 @@ ***/ #include +#include #include +#include #include /* bool */ #include /* size_t */ @@ -40,8 +42,6 @@ using tr_tracker_tier_t = uint32_t; using tr_tracker_id_t = uint32_t; using tr_byte_index_t = uint64_t; -#include "announce-list.h" - struct tr_block_span_t { tr_block_index_t begin; @@ -54,6 +54,8 @@ struct tr_byte_span_t uint64_t end; }; +class tr_announce_list; + struct tr_ctor; struct tr_error; struct tr_info; @@ -1511,26 +1513,34 @@ struct tr_file /** @brief information about a torrent that comes from its metainfo file */ struct tr_info { - /* total size of the torrent, in bytes */ - uint64_t totalSize; - - /* The torrent's name. */ - std::string name_; - - /* Path to torrent Transmission's internal copy of the .torrent file. */ - std::string torrent_file_; - - char** webseeds; - - std::string comment_; - std::string creator_; - - /* torrent's source. empty if not set. */ - std::string source_; - - auto const& torrentFile() const + auto totalSize() const { - return torrent_file_; + return total_size_; + } + + auto pieceSize() const + { + return piece_size_; + } + + auto pieceCount() const + { + return piece_count_; + } + + auto dateCreated() const + { + return date_created_; + } + + auto const& infoHash() const + { + return hash_; + } + + auto const& infoHashString() const + { + return info_hash_string_; } auto const& name() const @@ -1538,6 +1548,11 @@ struct tr_info return name_; } + void setName(std::string_view name) + { + name_ = name; + } + auto const& creator() const { return creator_; @@ -1553,25 +1568,21 @@ struct tr_info return source_; } - auto const& infoHash() const + auto const& torrentFile() const { - return hash_; + return torrent_file_; } - void setName(std::string_view name) - { - name_ = name; - } - - // Private. - // Use tr_torrentFile() and tr_torrentFileCount() instead. - std::vector files; - tr_file_index_t fileCount() const { return std::size(files); } + auto fileSize(tr_file_index_t i) const + { + return files[i].size_; + } + std::string const& fileSubpath(tr_file_index_t i) const { return files[i].subpath_; @@ -1582,38 +1593,36 @@ struct tr_info files[i].subpath_ = subpath; } - auto fileSize(tr_file_index_t i) const + auto webseedCount() const { - return files[i].size_; + return std::size(webseeds_); } - auto const& infoHashString() const + auto const& webseed(size_t i) const { - return info_hash_string_; + return webseeds_[i]; } - auto dateCreated() const + auto isPrivate() const { - return date_created_; + return is_private_; } - // TODO(ckerr) aggregate this directly, rather than using a shared_ptr, when tr_info is private - std::shared_ptr announce_list; - - /* Torrent info */ - time_t date_created_; - - unsigned int webseedCount; - uint32_t pieceSize; - tr_piece_index_t pieceCount; - - /* General info */ tr_sha1_digest_t hash_; + std::shared_ptr announce_list; + std::vector files; + std::vector webseeds_; + std::string comment_; + std::string creator_; std::string info_hash_string_; - - /* Flags */ - bool isPrivate; - bool isFolder; + std::string name_; + std::string source_; + std::string torrent_file_; + uint64_t total_size_ = 0; + tr_piece_index_t piece_count_ = 0; + time_t date_created_ = 0; + uint32_t piece_size_ = 0; + bool is_private_ = false; }; bool tr_torrentHasMetadata(tr_torrent const* tor); diff --git a/macosx/QuickLookPlugin/GeneratePreviewForURL.mm b/macosx/QuickLookPlugin/GeneratePreviewForURL.mm index 3487511d3..67fdcdcc9 100644 --- a/macosx/QuickLookPlugin/GeneratePreviewForURL.mm +++ b/macosx/QuickLookPlugin/GeneratePreviewForURL.mm @@ -133,7 +133,7 @@ OSStatus GeneratePreviewForURL(void* thisInterface, QLPreviewRequestRef preview, NSMutableArray* lists = [NSMutableArray array]; - auto const n_webseeds = std::size(metainfo.webseeds()); + auto const n_webseeds = metainfo.webseedCount(); if (n_webseeds > 0) { NSMutableString* listSection = [NSMutableString string]; @@ -145,9 +145,9 @@ OSStatus GeneratePreviewForURL(void* thisInterface, QLPreviewRequestRef preview, [NSString formattedUInteger:n_webseeds]]; [listSection appendFormat:@"%@", headerTitleString]; - for (auto const& url : metainfo.webseeds()) + for (size_t i = 0; i < n_webseeds; ++i) { - [listSection appendFormat:@"%s", url.c_str()]; + [listSection appendFormat:@"%s", metainfo.webseed(i).c_str()]; } [listSection appendString:@""]; diff --git a/tests/libtransmission/magnet-metainfo-test.cc b/tests/libtransmission/magnet-metainfo-test.cc index fd74c6f59..627875f2a 100644 --- a/tests/libtransmission/magnet-metainfo-test.cc +++ b/tests/libtransmission/magnet-metainfo-test.cc @@ -55,8 +55,8 @@ TEST(MagnetMetainfo, magnetParse) EXPECT_EQ(1, it->tier); EXPECT_EQ("http://tracker.opentracker.org/announce", it->announce.full); EXPECT_EQ("http://tracker.opentracker.org/scrape", it->scrape.full); - EXPECT_EQ(1, std::size(mm.webseeds())); - EXPECT_EQ("http://server.webseed.org/path/to/file"sv, mm.webseeds().front()); + EXPECT_EQ(1, mm.webseedCount()); + EXPECT_EQ("http://server.webseed.org/path/to/file"sv, mm.webseed(0)); EXPECT_EQ("Display Name"sv, mm.name()); EXPECT_EQ(ExpectedHash, mm.infoHash()); } diff --git a/utils/show.cc b/utils/show.cc index 8acb1d6e7..95bcdc740 100644 --- a/utils/show.cc +++ b/utils/show.cc @@ -160,13 +160,14 @@ void showInfo(app_opts const& opts, tr_torrent_metainfo const& metainfo) *** **/ - if (auto const& webseeds = metainfo.webseeds(); !std::empty(webseeds)) + auto const n_webseeds = metainfo.webseedCount(); + if (n_webseeds > 0) { printf("\nWEBSEEDS\n\n"); - for (auto const& webseed : webseeds) + for (size_t i = 0; i < n_webseeds; ++i) { - printf(" %s\n", webseed.c_str()); + printf(" %s\n", metainfo.webseed(i).c_str()); } }