mirror of
https://github.com/transmission/transmission.git
synced 2026-02-14 23:19:34 +00:00
build: bump to C++20 (#7191)
* build: bump to C++20 Co-authored-by: Cœur <coeur@gmx.fr> * refactor: use designated initializers * refactor: remove redundant SFINAE * fix: clang-tidy warnings * chore: comments about min compiler versions for C++20 features * build: clang objc++ modules build errors Co-authored-by: Dzmitry Neviadomski <nevack.d@gmail.com> * refactor: add `TR_CONSTEXPR_VEC` and `TR_CONSTEXPR_STR` * fix: don't use `std::rel_ops` * chore: housekeeping * fix: possible fix for macOS linker error --------- Co-authored-by: Cœur <coeur@gmx.fr> Co-authored-by: Dzmitry Neviadomski <nevack.d@gmail.com> Co-authored-by: Charles Kerr <charles@charleskerr.com>
This commit is contained in:
@@ -43,7 +43,7 @@ TabWidth: 4
|
||||
UseTab: Never
|
||||
---
|
||||
Language: Cpp
|
||||
Standard: c++17
|
||||
Standard: c++20
|
||||
|
||||
AccessModifierOffset: -4
|
||||
PackConstructorInitializers: Never
|
||||
|
||||
@@ -174,7 +174,7 @@ if(NOT CMAKE_C_STANDARD)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
endif()
|
||||
if(NOT CMAKE_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -483,6 +483,7 @@
|
||||
EDC37BCD2EE9C2AD001E2612 /* api-compat.cc in Sources */ = {isa = PBXBuildFile; fileRef = EDC37BCC2EE9C2AD001E2612 /* api-compat.cc */; };
|
||||
EDC37BCE2EE9C2AD001E2612 /* api-compat.h in Headers */ = {isa = PBXBuildFile; fileRef = EDC37BCB2EE9C2AD001E2612 /* api-compat.h */; };
|
||||
EDC749F92D98AE3000A12D0F /* PowerManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = EDC749F82D98AE2900A12D0F /* PowerManager.mm */; };
|
||||
EDD735D62D83087400852628 /* UniformTypeIdentifiers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDD735D52D83087400852628 /* UniformTypeIdentifiers.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
|
||||
F11545ACA7C4D7A464F703AB /* block-info.h in Headers */ = {isa = PBXBuildFile; fileRef = 6A044CBD8C049AFCBD4DB411 /* block-info.h */; settings = {ATTRIBUTES = (Project, ); }; };
|
||||
F63480631E1D7274005B9E09 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F63480621E1D7274005B9E09 /* Images.xcassets */; };
|
||||
/* End PBXBuildFile section */
|
||||
@@ -1478,6 +1479,7 @@
|
||||
EDC37BCC2EE9C2AD001E2612 /* api-compat.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "api-compat.cc"; sourceTree = "<group>"; };
|
||||
EDC749F72D98ADE200A12D0F /* PowerManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PowerManager.h; sourceTree = "<group>"; };
|
||||
EDC749F82D98AE2900A12D0F /* PowerManager.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PowerManager.mm; sourceTree = "<group>"; };
|
||||
EDD735D52D83087400852628 /* UniformTypeIdentifiers.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UniformTypeIdentifiers.framework; path = System/Library/Frameworks/UniformTypeIdentifiers.framework; sourceTree = SDKROOT; };
|
||||
F63480621E1D7274005B9E09 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Images/Images.xcassets; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
@@ -1505,6 +1507,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
EDD735D62D83087400852628 /* UniformTypeIdentifiers.framework in Frameworks */,
|
||||
C87369652809984200573C90 /* UserNotifications.framework in Frameworks */,
|
||||
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */,
|
||||
4D1838DD09DEC0E80047D688 /* libtransmission.a in Frameworks */,
|
||||
@@ -2185,6 +2188,7 @@
|
||||
A2F35BBA15C5A0A100EBF632 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
EDD735D52D83087400852628 /* UniformTypeIdentifiers.framework */,
|
||||
C87369642809984200573C90 /* UserNotifications.framework */,
|
||||
55869925257074EC00F77A43 /* libcurl.tbd */,
|
||||
C88771AB2803EE53005C7523 /* libiconv.tbd */,
|
||||
@@ -4381,8 +4385,9 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks";
|
||||
OTHER_CPLUSPLUSFLAGS = (
|
||||
"$(inherited)",
|
||||
"-fmodules",
|
||||
"-fcxx-modules",
|
||||
"-fno-modules",
|
||||
"-Xclang",
|
||||
"-fno-cxx-modules",
|
||||
);
|
||||
PRODUCT_NAME = Transmission;
|
||||
SYSTEM_HEADER_SEARCH_PATHS = (
|
||||
@@ -4457,7 +4462,7 @@
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++20";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
@@ -4644,8 +4649,9 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks";
|
||||
OTHER_CPLUSPLUSFLAGS = (
|
||||
"$(inherited)",
|
||||
"-fmodules",
|
||||
"-fcxx-modules",
|
||||
"-fno-modules",
|
||||
"-Xclang",
|
||||
"-fno-cxx-modules",
|
||||
);
|
||||
PRODUCT_NAME = Transmission;
|
||||
SYSTEM_HEADER_SEARCH_PATHS = (
|
||||
@@ -4662,7 +4668,7 @@
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++20";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
@@ -4765,7 +4771,7 @@
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++20";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
@@ -4849,8 +4855,9 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks";
|
||||
OTHER_CPLUSPLUSFLAGS = (
|
||||
"$(inherited)",
|
||||
"-fmodules",
|
||||
"-fcxx-modules",
|
||||
"-fno-modules",
|
||||
"-Xclang",
|
||||
"-fno-cxx-modules",
|
||||
);
|
||||
PRODUCT_NAME = Transmission;
|
||||
SYSTEM_HEADER_SEARCH_PATHS = (
|
||||
@@ -5034,8 +5041,9 @@
|
||||
INSTALL_PATH = /Library/QuickLook;
|
||||
OTHER_CPLUSPLUSFLAGS = (
|
||||
"$(inherited)",
|
||||
"-fmodules",
|
||||
"-fcxx-modules",
|
||||
"-fno-modules",
|
||||
"-Xclang",
|
||||
"-fno-cxx-modules",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.m0k.transmission.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@@ -5061,8 +5069,9 @@
|
||||
INSTALL_PATH = /Library/QuickLook;
|
||||
OTHER_CPLUSPLUSFLAGS = (
|
||||
"$(inherited)",
|
||||
"-fmodules",
|
||||
"-fcxx-modules",
|
||||
"-fno-modules",
|
||||
"-Xclang",
|
||||
"-fno-cxx-modules",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.m0k.transmission.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@@ -5088,8 +5097,9 @@
|
||||
INSTALL_PATH = /Library/QuickLook;
|
||||
OTHER_CPLUSPLUSFLAGS = (
|
||||
"$(inherited)",
|
||||
"-fmodules",
|
||||
"-fcxx-modules",
|
||||
"-fno-modules",
|
||||
"-Xclang",
|
||||
"-fno-cxx-modules",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.m0k.transmission.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
||||
@@ -53,6 +53,7 @@ template<typename... Ts>
|
||||
Glib::VariantContainerBase make_variant_tuple(Ts&&... args)
|
||||
{
|
||||
return Glib::VariantContainerBase::create_tuple(
|
||||
// TODO(c++20): use std::remove_cvref_t (P0550R2) when GCC >= 9.1
|
||||
{ Glib::Variant<std::remove_cv_t<std::remove_reference_t<Ts>>>::create(std::forward<Ts>(args))... });
|
||||
}
|
||||
|
||||
|
||||
@@ -40,8 +40,6 @@ Glib::Value<T>& column_value_cast(Glib::ValueBase& value, Gtk::TreeModelColumn<T
|
||||
template<typename T, typename U, typename = std::enable_if_t<!std::is_floating_point_v<T>>>
|
||||
void update_cache_value(T& value, U&& new_value, Torrent::ChangeFlags& changes, Torrent::ChangeFlag flag)
|
||||
{
|
||||
using std::rel_ops::operator!=;
|
||||
|
||||
if (value != new_value)
|
||||
{
|
||||
value = std::forward<U>(new_value);
|
||||
|
||||
@@ -3,7 +3,15 @@ HeaderFilterRegex: .*/libtransmission/.*
|
||||
|
||||
# TODO: Enable `portability-template-virtual-member-function` after https://github.com/llvm/llvm-project/issues/139031 is fixed
|
||||
# TODO: Enable `cppcoreguidelines-pro-bounds-pointer-arithmetic` after converting all pointers to std::span
|
||||
# TODO: Enable `modernize-use-constraints` after GCC >= 10, clang 10
|
||||
# TODO: Enable `modernize-use-integer-sign-comparison` (P0586R2) after GCC >= 10.1, clang >= 13
|
||||
# PRs welcome to fix & re-enable any of these explicitly-disabled checks
|
||||
#
|
||||
# -modernize-use-ranges: GCC 10.1, clang 15
|
||||
# -modernize-loop-convert (P0896R4): GCC 10.1, clang 15
|
||||
# -readability-container-contains (P0458R2): GCC 9.1, clang 13
|
||||
# Ref: https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html
|
||||
# Ref: https://libcxx.llvm.org/Status/Cxx20.html
|
||||
Checks: >
|
||||
bugprone-*,
|
||||
-bugprone-branch-clone,
|
||||
@@ -36,12 +44,18 @@ Checks: >
|
||||
-misc-no-recursion,
|
||||
-misc-non-private-member-variables-in-classes,
|
||||
modernize-*,
|
||||
-modernize-loop-convert,
|
||||
-modernize-use-constraints,
|
||||
-modernize-use-designated-initializers,
|
||||
-modernize-use-integer-sign-comparison,
|
||||
-modernize-use-ranges,
|
||||
-modernize-use-trailing-return-type,
|
||||
performance-*,
|
||||
-performance-move-const-arg,
|
||||
portability-*,
|
||||
-portability-template-virtual-member-function,
|
||||
readability-*,
|
||||
-readability-container-contains,
|
||||
-readability-enum-initial-value,
|
||||
-readability-function-cognitive-complexity,
|
||||
-readability-identifier-length,
|
||||
|
||||
@@ -82,19 +82,19 @@ public:
|
||||
return std::size(trackers_);
|
||||
}
|
||||
|
||||
[[nodiscard]] TR_CONSTEXPR20 tracker_info const& at(size_t i) const
|
||||
[[nodiscard]] TR_CONSTEXPR_VEC tracker_info const& at(size_t i) const
|
||||
{
|
||||
return trackers_.at(i);
|
||||
}
|
||||
|
||||
[[nodiscard]] tr_tracker_tier_t nextTier() const;
|
||||
|
||||
[[nodiscard]] TR_CONSTEXPR20 bool operator==(tr_announce_list const& that) const
|
||||
[[nodiscard]] TR_CONSTEXPR_VEC bool operator==(tr_announce_list const& that) const
|
||||
{
|
||||
return trackers_ == that.trackers_;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool operator!=(tr_announce_list const& that) const
|
||||
[[nodiscard]] TR_CONSTEXPR_VEC bool operator!=(tr_announce_list const& that) const
|
||||
{
|
||||
return trackers_ != that.trackers_;
|
||||
}
|
||||
@@ -113,7 +113,7 @@ public:
|
||||
bool replace(tr_tracker_id_t id, std::string_view announce_url_sv);
|
||||
size_t set(char const* const* announce_urls, tr_tracker_tier_t const* tiers, size_t n);
|
||||
|
||||
TR_CONSTEXPR20 void clear()
|
||||
TR_CONSTEXPR_VEC void clear()
|
||||
{
|
||||
trackers_.clear();
|
||||
}
|
||||
|
||||
@@ -926,22 +926,22 @@ void on_announce_error(tr_tier* tier, char const* err, tr_announce_event e, time
|
||||
auto const* const current_tracker = tier->currentTracker();
|
||||
TR_ASSERT(current_tracker != nullptr);
|
||||
|
||||
auto req = tr_announce_request{};
|
||||
req.port = announcer->session->advertisedPeerPort();
|
||||
req.announce_url = current_tracker->announce_url;
|
||||
req.tracker_id = current_tracker->tracker_id;
|
||||
req.info_hash = tor->info_hash();
|
||||
req.peer_id = tor->peer_id();
|
||||
req.up = tier->byteCounts[TR_ANN_UP];
|
||||
req.down = tier->byteCounts[TR_ANN_DOWN];
|
||||
req.corrupt = tier->byteCounts[TR_ANN_CORRUPT];
|
||||
req.leftUntilComplete = tor->has_metainfo() ? tor->total_size() - tor->has_total() : INT64_MAX;
|
||||
req.event = event;
|
||||
req.numwant = event == TR_ANNOUNCE_EVENT_STOPPED ? 0 : Numwant;
|
||||
req.key = tor->announce_key();
|
||||
req.partial_seed = tor->is_partial_seed();
|
||||
req.log_name = tier->buildLogName();
|
||||
return req;
|
||||
return {
|
||||
.event = event,
|
||||
.partial_seed = tor->is_partial_seed(),
|
||||
.port = announcer->session->advertisedPeerPort(),
|
||||
.key = tor->announce_key(),
|
||||
.numwant = event == TR_ANNOUNCE_EVENT_STOPPED ? 0 : Numwant,
|
||||
.up = tier->byteCounts[TR_ANN_UP],
|
||||
.down = tier->byteCounts[TR_ANN_DOWN],
|
||||
.corrupt = tier->byteCounts[TR_ANN_CORRUPT],
|
||||
.leftUntilComplete = tor->has_metainfo() ? tor->total_size() - tor->has_total() : INT64_MAX,
|
||||
.announce_url = current_tracker->announce_url,
|
||||
.tracker_id = current_tracker->tracker_id,
|
||||
.peer_id = tor->peer_id(),
|
||||
.info_hash = tor->info_hash(),
|
||||
.log_name = tier->buildLogName(),
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] tr_tier* getTier(tr_announcer_impl* announcer, tr_sha1_digest_t const& info_hash, size_t tier_id)
|
||||
|
||||
@@ -653,6 +653,7 @@ void convert_keys(tr_variant& var, State& state)
|
||||
var.visit(
|
||||
[&state](auto& val)
|
||||
{
|
||||
// TODO(c++20): use std::remove_cvref_t (P0550R2) when GCC >= 9.1
|
||||
using ValueType = std::decay_t<decltype(val)>;
|
||||
|
||||
if constexpr (std::is_same_v<ValueType, std::string> || std::is_same_v<ValueType, std::string_view>)
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
struct tr_error
|
||||
{
|
||||
public:
|
||||
tr_error() = default;
|
||||
TR_CONSTEXPR_STR tr_error() = default;
|
||||
|
||||
tr_error(int code, std::string message)
|
||||
TR_CONSTEXPR_STR tr_error(int code, std::string message)
|
||||
: message_{ std::move(message) }
|
||||
, code_{ code }
|
||||
{
|
||||
@@ -27,7 +27,7 @@ public:
|
||||
return code_;
|
||||
}
|
||||
|
||||
[[nodiscard]] TR_CONSTEXPR20 auto message() const noexcept
|
||||
[[nodiscard]] TR_CONSTEXPR_STR auto message() const noexcept
|
||||
{
|
||||
return std::string_view{ message_ };
|
||||
}
|
||||
@@ -42,24 +42,24 @@ public:
|
||||
return has_value();
|
||||
}
|
||||
|
||||
void set(int code, std::string&& message)
|
||||
TR_CONSTEXPR_STR void set(int code, std::string&& message)
|
||||
{
|
||||
code_ = code;
|
||||
message_ = std::move(message);
|
||||
}
|
||||
|
||||
void set(int code, std::string_view message)
|
||||
TR_CONSTEXPR_STR void set(int code, std::string_view message)
|
||||
{
|
||||
code_ = code;
|
||||
message_.assign(message);
|
||||
}
|
||||
|
||||
void set(int code, char const* const message)
|
||||
TR_CONSTEXPR_STR void set(int code, char const* const message)
|
||||
{
|
||||
set(code, std::string_view{ message != nullptr ? message : "" });
|
||||
}
|
||||
|
||||
void prefix_message(std::string_view prefix)
|
||||
TR_CONSTEXPR_STR void prefix_message(std::string_view prefix)
|
||||
{
|
||||
message_.insert(std::begin(message_), std::begin(prefix), std::end(prefix));
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
explicit tr_file_piece_map(tr_torrent_metainfo const& tm);
|
||||
tr_file_piece_map(tr_block_info const& block_info, uint64_t const* file_sizes, size_t n_files);
|
||||
|
||||
[[nodiscard]] TR_CONSTEXPR20 piece_span_t piece_span_for_file(tr_file_index_t const file) const noexcept
|
||||
[[nodiscard]] TR_CONSTEXPR_VEC piece_span_t piece_span_for_file(tr_file_index_t const file) const noexcept
|
||||
{
|
||||
return file_pieces_[file];
|
||||
}
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
return std::size(file_pieces_);
|
||||
}
|
||||
|
||||
[[nodiscard]] TR_CONSTEXPR20 auto byte_span_for_file(tr_file_index_t const file) const
|
||||
[[nodiscard]] TR_CONSTEXPR_VEC auto byte_span_for_file(tr_file_index_t const file) const
|
||||
{
|
||||
auto const& span = file_bytes_[file];
|
||||
return tr_byte_span_t{ span.begin, span.end };
|
||||
@@ -84,7 +84,7 @@ private:
|
||||
class tr_file_priorities
|
||||
{
|
||||
public:
|
||||
TR_CONSTEXPR20 explicit tr_file_priorities(tr_file_piece_map const* fpm) noexcept
|
||||
TR_CONSTEXPR_VEC explicit tr_file_priorities(tr_file_piece_map const* fpm) noexcept
|
||||
: fpm_{ fpm }
|
||||
{
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public:
|
||||
return std::size(webseed_urls_);
|
||||
}
|
||||
|
||||
[[nodiscard]] TR_CONSTEXPR20 auto const& webseed(size_t i) const
|
||||
[[nodiscard]] TR_CONSTEXPR_VEC auto const& webseed(size_t i) const
|
||||
{
|
||||
return webseed_urls_.at(i);
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ public:
|
||||
return files_.file_count();
|
||||
}
|
||||
|
||||
[[nodiscard]] TR_CONSTEXPR20 auto file_size(tr_file_index_t i) const noexcept
|
||||
[[nodiscard]] TR_CONSTEXPR_VEC auto file_size(tr_file_index_t i) const noexcept
|
||||
{
|
||||
return files_.file_size(i);
|
||||
}
|
||||
@@ -142,7 +142,7 @@ public:
|
||||
return tr_sys_path_basename(top_);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto const& path(tr_file_index_t i) const noexcept
|
||||
[[nodiscard]] TR_CONSTEXPR_VEC auto const& path(tr_file_index_t i) const noexcept
|
||||
{
|
||||
return files_.path(i);
|
||||
}
|
||||
|
||||
@@ -665,7 +665,7 @@ std::optional<tr_address> tr_address::from_ipv4_mapped() const noexcept
|
||||
|
||||
// --- tr_socket_addrses
|
||||
|
||||
std::string tr_socket_address::display_name(tr_address const& address, tr_port port) noexcept
|
||||
std::string tr_socket_address::display_name(tr_address const& address, tr_port port)
|
||||
{
|
||||
return fmt::format(fmt::runtime(address.is_ipv6() ? "[{:s}]:{:d}" : "{:s}:{:d}"), address.display_name(), port.host());
|
||||
}
|
||||
|
||||
@@ -427,9 +427,9 @@ struct tr_address
|
||||
switch (type)
|
||||
{
|
||||
case TR_AF_INET:
|
||||
return tr_address{ TR_AF_INET, { { { { INADDR_ANY } } } } };
|
||||
return tr_address{ TR_AF_INET, { .addr4 = { INADDR_ANY } } };
|
||||
case TR_AF_INET6:
|
||||
return tr_address{ TR_AF_INET6, { IN6ADDR_ANY_INIT } };
|
||||
return tr_address{ TR_AF_INET6, { .addr6 = IN6ADDR_ANY_INIT } };
|
||||
default:
|
||||
TR_ASSERT_MSG(false, "invalid type");
|
||||
return tr_address{};
|
||||
@@ -472,8 +472,8 @@ struct tr_socket_address
|
||||
return port_;
|
||||
}
|
||||
|
||||
[[nodiscard]] static std::string display_name(tr_address const& address, tr_port port) noexcept;
|
||||
[[nodiscard]] auto display_name() const noexcept
|
||||
[[nodiscard]] static std::string display_name(tr_address const& address, tr_port port);
|
||||
[[nodiscard]] auto display_name() const
|
||||
{
|
||||
return display_name(address_, port_);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
[[nodiscard]] std::vector<tr_block_span_t> make_spans(small::vector<tr_block_index_t> const& blocks)
|
||||
[[nodiscard]] TR_CONSTEXPR_VEC std::vector<tr_block_span_t> make_spans(small::vector<tr_block_index_t> const& blocks)
|
||||
{
|
||||
if (std::empty(blocks))
|
||||
{
|
||||
@@ -34,7 +34,7 @@ namespace
|
||||
spans.reserve(std::size(blocks));
|
||||
for (auto span_begin = std::begin(blocks), end = std::end(blocks); span_begin != end;)
|
||||
{
|
||||
static auto constexpr NotAdjacent = [](tr_block_index_t const lhs, tr_block_index_t const rhs)
|
||||
auto constexpr NotAdjacent = [](tr_block_index_t const lhs, tr_block_index_t const rhs)
|
||||
{
|
||||
return lhs + 1U != rhs;
|
||||
};
|
||||
@@ -218,7 +218,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
TR_CONSTEXPR20 void reset_blocks_bitfield(tr_bitfield const& requests)
|
||||
TR_CONSTEXPR_VEC void reset_blocks_bitfield(tr_bitfield const& requests)
|
||||
{
|
||||
for (auto& candidate : candidates_)
|
||||
{
|
||||
@@ -253,7 +253,7 @@ private:
|
||||
|
||||
// ---
|
||||
|
||||
TR_CONSTEXPR20 void peer_disconnect(tr_bitfield const& have, tr_bitfield const& requests)
|
||||
TR_CONSTEXPR_VEC void peer_disconnect(tr_bitfield const& have, tr_bitfield const& requests)
|
||||
{
|
||||
dec_replication_bitfield(have);
|
||||
reset_blocks_bitfield(requests);
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <tuple> // std::tie
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@@ -76,11 +75,11 @@ private:
|
||||
}
|
||||
|
||||
return TorrentInfo{
|
||||
tor->info_hash(), // info_hash
|
||||
tor->peer_id(), // client_peer_id
|
||||
tor->id(), // id
|
||||
tor->is_done(), // is_done
|
||||
tor->is_running() // is_running
|
||||
.info_hash = tor->info_hash(),
|
||||
.client_peer_id = tor->peer_id(),
|
||||
.id = tor->id(),
|
||||
.is_done = tor->is_done(),
|
||||
.is_running = tor->is_running(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -308,8 +307,8 @@ void tr_peer_info::update_canonical_priority()
|
||||
// FFFF:FFFF:FFFF:FFFF:5555:5555:5555:5555, etc...
|
||||
static auto constexpr MaskStartBaseOffset = std::array{ 2U, 6U };
|
||||
auto const base_idx = MaskStartBaseOffset[type];
|
||||
auto const mismatch_idx = std::mismatch(first, second, second).first - first;
|
||||
for (auto i = mismatch_idx >= base_idx ? mismatch_idx + 1 : base_idx; i < address_size; ++i)
|
||||
auto const mismatch_idx = static_cast<size_t>(std::mismatch(first, second, second).first - first);
|
||||
for (auto i = mismatch_idx >= base_idx ? mismatch_idx + 1U : base_idx; i < address_size; ++i)
|
||||
{
|
||||
first[i] &= std::byte{ 0x55 };
|
||||
second[i] &= std::byte{ 0x55 };
|
||||
@@ -354,8 +353,7 @@ constexpr struct
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] constexpr std::enable_if_t<std::is_same_v<std::decay_t<decltype(*std::declval<T>())>, tr_peer_info>, bool>
|
||||
operator()(T const& a, T const& b) const noexcept
|
||||
[[nodiscard]] constexpr bool operator()(T const& a, T const& b) const noexcept
|
||||
{
|
||||
return compare(*a, *b) < 0;
|
||||
}
|
||||
@@ -2460,9 +2458,7 @@ struct ComparePeerInfo
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] std::enable_if_t<std::is_same_v<std::decay_t<decltype(*std::declval<T>())>, tr_peer_info>, bool> operator()(
|
||||
T const& a,
|
||||
T const& b) const noexcept
|
||||
[[nodiscard]] bool operator()(T const& a, T const& b) const noexcept
|
||||
{
|
||||
return compare(*a, *b) < 0;
|
||||
}
|
||||
|
||||
@@ -2606,6 +2606,9 @@ using SessionAccessors = std::pair<SessionGetter, SessionSetter>;
|
||||
[](tr_session const& /*src*/) -> tr_variant { return tr_variant::unmanaged_string(LONG_VERSION_STRING); },
|
||||
nullptr);
|
||||
|
||||
// `row` could have been replaced by structured bindings,
|
||||
// but it's not available until clang 16
|
||||
// https://github.com/llvm/llvm-project/commit/44f2baa3804a62ca793f0ff3e43aa71cea91a795
|
||||
for (auto const& row : tr_session::Scripts)
|
||||
{
|
||||
auto const script = row.script;
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace detail
|
||||
// NOLINTBEGIN(readability-identifier-naming)
|
||||
// use std-style naming for these traits
|
||||
|
||||
// TODO(c++20): use std::remove_cvref_t (P0550R2) when GCC >= 9.1
|
||||
template<typename T>
|
||||
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ void tr_session_alt_speeds::set_active(bool active, ChangeReason reason, bool fo
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] bool tr_session_alt_speeds::is_active_minute(time_t time) const noexcept
|
||||
[[nodiscard]] bool tr_session_alt_speeds::is_active_minute(time_t time) const
|
||||
{
|
||||
auto const tm = *std::localtime(&time);
|
||||
|
||||
|
||||
@@ -189,7 +189,7 @@ private:
|
||||
void set_active(bool active, ChangeReason reason, bool force);
|
||||
|
||||
// whether `time` hits in one of the `minutes_` that is true
|
||||
[[nodiscard]] bool is_active_minute(time_t time) const noexcept;
|
||||
[[nodiscard]] bool is_active_minute(time_t time) const;
|
||||
|
||||
static int constexpr MinutesPerHour = 60;
|
||||
static int constexpr MinutesPerDay = MinutesPerHour * 24;
|
||||
|
||||
@@ -110,13 +110,14 @@ tr_session_id::session_id_t tr_session_id::make_session_id()
|
||||
return session_id;
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(bugprone-exception-escape)
|
||||
tr_session_id::~tr_session_id()
|
||||
{
|
||||
destroy_lockfile(current_lock_file_, std::data(current_value_));
|
||||
destroy_lockfile(previous_lock_file_, std::data(previous_value_));
|
||||
}
|
||||
|
||||
bool tr_session_id::is_local(std::string_view session_id) noexcept
|
||||
bool tr_session_id::is_local(std::string_view session_id)
|
||||
{
|
||||
if (std::empty(session_id))
|
||||
{
|
||||
@@ -158,7 +159,7 @@ bool tr_session_id::is_local(std::string_view session_id) noexcept
|
||||
return is_local;
|
||||
}
|
||||
|
||||
std::string_view tr_session_id::sv() const noexcept
|
||||
std::string_view tr_session_id::sv() const
|
||||
{
|
||||
if (auto const now = get_current_time_(); now >= expires_at_)
|
||||
{
|
||||
@@ -174,7 +175,7 @@ std::string_view tr_session_id::sv() const noexcept
|
||||
return std::string_view{ std::data(current_value_), std::size(current_value_) - 1 };
|
||||
}
|
||||
|
||||
char const* tr_session_id::c_str() const noexcept
|
||||
char const* tr_session_id::c_str() const
|
||||
{
|
||||
return std::data(sv()); // current_value_ is zero-terminated
|
||||
}
|
||||
|
||||
@@ -36,11 +36,11 @@ public:
|
||||
* relative paths to absolute before passing through RPC, or presenting
|
||||
* different UI for local and remote sessions.
|
||||
*/
|
||||
[[nodiscard]] static bool is_local(std::string_view session_id) noexcept;
|
||||
[[nodiscard]] static bool is_local(std::string_view session_id);
|
||||
|
||||
// current session identifier
|
||||
[[nodiscard]] std::string_view sv() const noexcept;
|
||||
[[nodiscard]] char const* c_str() const noexcept;
|
||||
[[nodiscard]] std::string_view sv() const;
|
||||
[[nodiscard]] char const* c_str() const;
|
||||
|
||||
private:
|
||||
static auto constexpr SessionIdSize = size_t{ 48 };
|
||||
|
||||
@@ -555,7 +555,7 @@ public:
|
||||
|
||||
explicit tr_session(std::string_view config_dir, tr_variant const& settings_dict);
|
||||
|
||||
[[nodiscard]] std::string_view sessionId() const noexcept
|
||||
[[nodiscard]] std::string_view sessionId() const
|
||||
{
|
||||
return session_id_.sv();
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public:
|
||||
return std::size(files_);
|
||||
}
|
||||
|
||||
[[nodiscard]] TR_CONSTEXPR20 uint64_t file_size(tr_file_index_t file_index) const
|
||||
[[nodiscard]] TR_CONSTEXPR_VEC uint64_t file_size(tr_file_index_t file_index) const
|
||||
{
|
||||
return files_.at(file_index).size_;
|
||||
}
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
return total_size_;
|
||||
}
|
||||
|
||||
[[nodiscard]] TR_CONSTEXPR20 std::string const& path(tr_file_index_t file_index) const
|
||||
[[nodiscard]] TR_CONSTEXPR_VEC std::string const& path(tr_file_index_t file_index) const
|
||||
{
|
||||
return files_.at(file_index).path_;
|
||||
}
|
||||
@@ -71,17 +71,17 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void reserve(size_t n_files)
|
||||
TR_CONSTEXPR_VEC void reserve(size_t n_files)
|
||||
{
|
||||
files_.reserve(n_files);
|
||||
}
|
||||
|
||||
void shrink_to_fit()
|
||||
TR_CONSTEXPR_VEC void shrink_to_fit()
|
||||
{
|
||||
files_.shrink_to_fit();
|
||||
}
|
||||
|
||||
TR_CONSTEXPR20 void clear() noexcept
|
||||
TR_CONSTEXPR_VEC void clear() noexcept
|
||||
{
|
||||
files_.clear();
|
||||
total_size_ = uint64_t{};
|
||||
@@ -102,7 +102,7 @@ public:
|
||||
return ret;
|
||||
}
|
||||
|
||||
tr_file_index_t add(std::string_view path, uint64_t file_size)
|
||||
TR_CONSTEXPR_VEC tr_file_index_t add(std::string_view path, uint64_t file_size)
|
||||
{
|
||||
auto const ret = static_cast<tr_file_index_t>(std::size(files_));
|
||||
files_.emplace_back(path, file_size);
|
||||
@@ -176,7 +176,7 @@ private:
|
||||
struct file_t
|
||||
{
|
||||
public:
|
||||
void set_path(std::string_view subpath)
|
||||
TR_CONSTEXPR_STR void set_path(std::string_view subpath)
|
||||
{
|
||||
if (path_ != subpath)
|
||||
{
|
||||
@@ -185,7 +185,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
file_t(std::string_view path, uint64_t size)
|
||||
TR_CONSTEXPR_STR file_t(std::string_view path, uint64_t size)
|
||||
: path_{ path }
|
||||
, size_{ size }
|
||||
{
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
return metadata_;
|
||||
}
|
||||
|
||||
[[nodiscard]] TR_CONSTEXPR20 std::string_view log_name() const noexcept
|
||||
[[nodiscard]] TR_CONSTEXPR_STR std::string_view log_name() const noexcept
|
||||
{
|
||||
return log_name_;
|
||||
}
|
||||
|
||||
@@ -46,11 +46,11 @@ public:
|
||||
{
|
||||
return files().file_count();
|
||||
}
|
||||
[[nodiscard]] TR_CONSTEXPR20 auto file_size(tr_file_index_t i) const
|
||||
[[nodiscard]] TR_CONSTEXPR_VEC auto file_size(tr_file_index_t i) const
|
||||
{
|
||||
return files().file_size(i);
|
||||
}
|
||||
[[nodiscard]] TR_CONSTEXPR20 auto const& file_subpath(tr_file_index_t i) const
|
||||
[[nodiscard]] TR_CONSTEXPR_VEC auto const& file_subpath(tr_file_index_t i) const
|
||||
{
|
||||
return files().path(i);
|
||||
}
|
||||
@@ -132,7 +132,7 @@ public:
|
||||
return is_private_;
|
||||
}
|
||||
|
||||
[[nodiscard]] TR_CONSTEXPR20 tr_sha1_digest_t const& piece_hash(tr_piece_index_t piece) const
|
||||
[[nodiscard]] TR_CONSTEXPR_VEC tr_sha1_digest_t const& piece_hash(tr_piece_index_t piece) const
|
||||
{
|
||||
return pieces_[piece];
|
||||
}
|
||||
|
||||
@@ -1434,11 +1434,29 @@ tr_file_view tr_torrentFile(tr_torrent const* tor, tr_file_index_t file)
|
||||
|
||||
if (tor->is_seed() || length == 0)
|
||||
{
|
||||
return { subpath.c_str(), length, length, 1.0, begin, end, priority, wanted };
|
||||
return {
|
||||
.name = subpath.c_str(),
|
||||
.have = length,
|
||||
.length = length,
|
||||
.progress = 1.0,
|
||||
.beginPiece = begin,
|
||||
.endPiece = end,
|
||||
.priority = priority,
|
||||
.wanted = wanted,
|
||||
};
|
||||
}
|
||||
|
||||
auto const have = tor->completion_.count_has_bytes_in_span(tor->byte_span_for_file(file));
|
||||
return { subpath.c_str(), have, length, have >= length ? 1.0 : have / double(length), begin, end, priority, wanted };
|
||||
return {
|
||||
.name = subpath.c_str(),
|
||||
.have = have,
|
||||
.length = length,
|
||||
.progress = have >= length ? 1.0 : have / double(length),
|
||||
.beginPiece = begin,
|
||||
.endPiece = end,
|
||||
.priority = priority,
|
||||
.wanted = wanted,
|
||||
};
|
||||
}
|
||||
|
||||
size_t tr_torrentFileCount(tr_torrent const* torrent)
|
||||
@@ -1473,21 +1491,19 @@ size_t tr_torrentTrackerCount(tr_torrent const* tor)
|
||||
tr_torrent_view tr_torrentView(tr_torrent const* tor)
|
||||
{
|
||||
TR_ASSERT(tr_isTorrent(tor));
|
||||
|
||||
auto ret = tr_torrent_view{};
|
||||
ret.name = tor->name().c_str();
|
||||
ret.hash_string = tor->info_hash_string().c_str();
|
||||
ret.comment = tor->comment().c_str();
|
||||
ret.creator = tor->creator().c_str();
|
||||
ret.source = tor->source().c_str();
|
||||
ret.total_size = tor->total_size();
|
||||
ret.date_created = tor->date_created();
|
||||
ret.piece_size = tor->piece_size();
|
||||
ret.n_pieces = tor->piece_count();
|
||||
ret.is_private = tor->is_private();
|
||||
ret.is_folder = tor->file_count() > 1 || (tor->file_count() == 1 && tr_strv_contains(tor->file_subpath(0), '/'));
|
||||
|
||||
return ret;
|
||||
return {
|
||||
.name = tor->name().c_str(),
|
||||
.hash_string = tor->info_hash_string().c_str(),
|
||||
.comment = tor->comment().c_str(),
|
||||
.creator = tor->creator().c_str(),
|
||||
.source = tor->source().c_str(),
|
||||
.total_size = tor->total_size(),
|
||||
.date_created = tor->date_created(),
|
||||
.piece_size = tor->piece_size(),
|
||||
.n_pieces = tor->piece_count(),
|
||||
.is_private = tor->is_private(),
|
||||
.is_folder = tor->file_count() > 1 || (tor->file_count() == 1 && tr_strv_contains(tor->file_subpath(0), '/')),
|
||||
};
|
||||
}
|
||||
|
||||
std::string tr_torrentFilename(tr_torrent const* tor)
|
||||
|
||||
@@ -480,12 +480,12 @@ struct tr_torrent
|
||||
return metainfo_.file_count();
|
||||
}
|
||||
|
||||
[[nodiscard]] TR_CONSTEXPR20 auto const& file_subpath(tr_file_index_t i) const
|
||||
[[nodiscard]] TR_CONSTEXPR_VEC auto const& file_subpath(tr_file_index_t i) const
|
||||
{
|
||||
return metainfo_.file_subpath(i);
|
||||
}
|
||||
|
||||
[[nodiscard]] TR_CONSTEXPR20 auto file_size(tr_file_index_t i) const
|
||||
[[nodiscard]] TR_CONSTEXPR_VEC auto file_size(tr_file_index_t i) const
|
||||
{
|
||||
return metainfo_.file_size(i);
|
||||
}
|
||||
@@ -517,7 +517,7 @@ struct tr_torrent
|
||||
return metainfo_.webseed_count();
|
||||
}
|
||||
|
||||
[[nodiscard]] TR_CONSTEXPR20 auto const& webseed(size_t i) const
|
||||
[[nodiscard]] TR_CONSTEXPR_VEC auto const& webseed(size_t i) const
|
||||
{
|
||||
return metainfo_.webseed(i);
|
||||
}
|
||||
@@ -1272,7 +1272,7 @@ private:
|
||||
// must be called after the torrent's announce list changes.
|
||||
void on_announce_list_changed();
|
||||
|
||||
[[nodiscard]] TR_CONSTEXPR20 tr_byte_span_t byte_span_for_file(tr_file_index_t file) const
|
||||
[[nodiscard]] TR_CONSTEXPR_VEC tr_byte_span_t byte_span_for_file(tr_file_index_t file) const
|
||||
{
|
||||
return fpm_.byte_span_for_file(file);
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ public:
|
||||
return {};
|
||||
}
|
||||
|
||||
if (auto const n_sent = send(sockfd, reinterpret_cast<char const*>(data()), n_bytes, 0); n_sent >= 0U)
|
||||
if (auto const n_sent = send(sockfd, reinterpret_cast<char const*>(data()), n_bytes, 0); n_sent >= 0)
|
||||
{
|
||||
drain(n_sent);
|
||||
return n_sent;
|
||||
|
||||
@@ -17,6 +17,18 @@
|
||||
#define TR_CONSTEXPR20
|
||||
#endif
|
||||
|
||||
#if __cpp_lib_constexpr_vector >= 201907L
|
||||
#define TR_CONSTEXPR_VEC constexpr
|
||||
#else
|
||||
#define TR_CONSTEXPR_VEC
|
||||
#endif
|
||||
|
||||
#if __cpp_lib_constexpr_string >= 201907L
|
||||
#define TR_CONSTEXPR_STR constexpr
|
||||
#else
|
||||
#define TR_CONSTEXPR_STR
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 202302L // _MSVC_LANG value for C++23 not available yet
|
||||
#define TR_CONSTEXPR23 constexpr
|
||||
#else
|
||||
|
||||
@@ -114,33 +114,41 @@ template<typename T>
|
||||
*/
|
||||
[[nodiscard]] bool tr_wildmat(char const* text, char const* pattern);
|
||||
|
||||
// c++23 (P1679R3), GCC 11.1, clang 12
|
||||
template<typename T>
|
||||
[[nodiscard]] constexpr bool tr_strv_contains(std::string_view sv, T key) noexcept // c++23
|
||||
[[nodiscard]] constexpr bool tr_strv_contains(std::string_view sv, T key) noexcept
|
||||
{
|
||||
return sv.find(key) != std::string_view::npos;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool tr_strv_starts_with(std::string_view sv, char key) // c++20
|
||||
// c++20 (P0457R2), GCC 9.1, clang 6
|
||||
[[nodiscard]] constexpr bool tr_strv_starts_with(std::string_view sv, char key)
|
||||
{
|
||||
return !std::empty(sv) && sv.front() == key;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool tr_strv_starts_with(std::string_view sv, std::string_view key) // c++20
|
||||
// c++20 (P0457R2), GCC 9.1, clang 6
|
||||
[[nodiscard]] constexpr bool tr_strv_starts_with(std::string_view sv, std::string_view key)
|
||||
{
|
||||
return std::size(key) <= std::size(sv) && sv.substr(0, std::size(key)) == key;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool tr_strv_starts_with(std::wstring_view sv, std::wstring_view key) // c++20
|
||||
// c++20 (P0457R2), GCC 9.1, clang 6
|
||||
[[nodiscard]] constexpr bool tr_strv_starts_with(
|
||||
std::wstring_view sv,
|
||||
std::wstring_view key) // c++20 (P0457R2), GCC 9.1, clang 6
|
||||
{
|
||||
return std::size(key) <= std::size(sv) && sv.substr(0, std::size(key)) == key;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool tr_strv_ends_with(std::string_view sv, std::string_view key) // c++20
|
||||
// c++20 (P0457R2), GCC 9.1, clang 6
|
||||
[[nodiscard]] constexpr bool tr_strv_ends_with(std::string_view sv, std::string_view key)
|
||||
{
|
||||
return std::size(key) <= std::size(sv) && sv.substr(std::size(sv) - std::size(key)) == key;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool tr_strv_ends_with(std::string_view sv, char key) // c++20
|
||||
// c++20 (P0457R2), GCC 9.1, clang 6
|
||||
[[nodiscard]] constexpr bool tr_strv_ends_with(std::string_view sv, char key)
|
||||
{
|
||||
return !std::empty(sv) && sv.back() == key;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ struct Config
|
||||
struct Units
|
||||
{
|
||||
template<typename... Names> // NOLINTNEXTLINE(google-explicit-constructor, cppcoreguidelines-pro-type-member-init)
|
||||
Units(Base base, Names... names) noexcept
|
||||
Units(Base base, Names... names)
|
||||
{
|
||||
set_base(base);
|
||||
|
||||
@@ -204,7 +204,7 @@ public:
|
||||
return compare(that) >= 0;
|
||||
}
|
||||
|
||||
std::string_view to_string(char* buf, size_t buflen) const noexcept
|
||||
std::string_view to_string(char* buf, size_t buflen) const
|
||||
{
|
||||
auto idx = size_t{ 0 };
|
||||
auto val = 1.0 * base_quantity_;
|
||||
|
||||
@@ -192,6 +192,7 @@ tr_variant& tr_variant::merge(tr_variant const& that)
|
||||
that.visit(
|
||||
[this](auto const& value)
|
||||
{
|
||||
// TODO(c++20): use std::remove_cvref_t (P0550R2) when GCC >= 9.1
|
||||
using ValueType = std::decay_t<decltype(value)>;
|
||||
|
||||
if constexpr (
|
||||
|
||||
@@ -100,9 +100,9 @@ public:
|
||||
return Vector::const_iterator{ const_cast<Map*>(this)->find(key) };
|
||||
}
|
||||
|
||||
[[nodiscard]] auto contains(tr_quark const key) const noexcept
|
||||
[[nodiscard]] TR_CONSTEXPR20 auto contains(tr_quark const key) const noexcept
|
||||
{
|
||||
return find(key) != end(); // NOLINT(readability-container-contains)
|
||||
return find(key) != end();
|
||||
}
|
||||
|
||||
[[nodiscard]] TR_CONSTEXPR20 auto size() const noexcept
|
||||
@@ -131,7 +131,7 @@ public:
|
||||
return 0U;
|
||||
}
|
||||
|
||||
bool replace_key(tr_quark const old_key, tr_quark const new_key)
|
||||
TR_CONSTEXPR20 bool replace_key(tr_quark const old_key, tr_quark const new_key)
|
||||
{
|
||||
if (contains(new_key))
|
||||
{
|
||||
@@ -309,6 +309,7 @@ public:
|
||||
template<typename Val>
|
||||
[[nodiscard]] constexpr auto* get_if() noexcept
|
||||
{
|
||||
// TODO(c++20): use std::remove_cvref_t (P0550R2) when GCC >= 9.1
|
||||
static_assert(
|
||||
!std::is_same_v<std::decay_t<Val>, std::string> && !std::is_same_v<std::decay_t<Val>, std::string_view>,
|
||||
"not supported -- use value_if<std::string_view>() instead.");
|
||||
@@ -318,6 +319,7 @@ public:
|
||||
template<typename Val>
|
||||
[[nodiscard]] constexpr auto const* get_if() const noexcept
|
||||
{
|
||||
// TODO(c++20): use std::remove_cvref_t (P0550R2) when GCC >= 9.1
|
||||
static_assert(
|
||||
!std::is_same_v<std::decay_t<Val>, std::string> && !std::is_same_v<std::decay_t<Val>, std::string_view>,
|
||||
"not supported -- use value_if<std::string_view>() instead.");
|
||||
|
||||
@@ -9,8 +9,10 @@ find_program(CODESIGN_EXECUTABLE codesign REQUIRED)
|
||||
set(MAC_BUNDLE_NAME Transmission)
|
||||
|
||||
add_compile_options(
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-fmodules>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-fcxx-modules>
|
||||
$<$<COMPILE_LANGUAGE:C>:-fmodules>
|
||||
|
||||
# https://github.com/llvm/llvm-project/issues/57432
|
||||
"$<$<COMPILE_LANG_AND_ID:CXX,AppleClang,Clang>:-fno-modules;-Xclang;-fno-cxx-modules>"
|
||||
|
||||
# equivalent of XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES for this directory
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-fobjc-arc>
|
||||
@@ -415,6 +417,7 @@ target_link_libraries(${TR_NAME}-mac
|
||||
"-framework Quartz"
|
||||
"-framework Security"
|
||||
"-weak_framework Sparkle"
|
||||
"-weak_framework UniformTypeIdentifiers"
|
||||
"-weak_framework UserNotifications")
|
||||
|
||||
if(NOT CMAKE_GENERATOR STREQUAL Xcode)
|
||||
|
||||
@@ -2,10 +2,17 @@
|
||||
// It may be used under the MIT (SPDX: MIT) license.
|
||||
// License text can be found in the licenses/ folder.
|
||||
|
||||
#if __has_feature(modules)
|
||||
@import Carbon;
|
||||
@import UserNotifications;
|
||||
|
||||
@import Sparkle;
|
||||
#else
|
||||
#import <Carbon/Carbon.h>
|
||||
#import <UserNotifications/UserNotifications.h>
|
||||
|
||||
#import <Sparkle/Sparkle.h>
|
||||
#endif
|
||||
|
||||
#include <atomic> /* atomic, atomic_fetch_add_explicit, memory_order_relaxed */
|
||||
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
// It may be used under the MIT (SPDX: MIT) license.
|
||||
// License text can be found in the licenses/ folder.
|
||||
|
||||
#if __has_feature(modules)
|
||||
@import AppKit;
|
||||
#else
|
||||
#import <AppKit/AppKit.h>
|
||||
#endif
|
||||
|
||||
#import "ExpandedPathToIconTransformer.h"
|
||||
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
// It may be used under the MIT (SPDX: MIT) license.
|
||||
// License text can be found in the licenses/ folder.
|
||||
|
||||
#if __has_feature(modules)
|
||||
@import AppKit;
|
||||
#else
|
||||
#import <AppKit/AppKit.h>
|
||||
#endif
|
||||
|
||||
#import "FileListNode.h"
|
||||
|
||||
|
||||
@@ -99,9 +99,11 @@ target_link_libraries(${TR_NAME}-mac-qlappex
|
||||
PRIVATE
|
||||
${TR_NAME}
|
||||
"-framework Foundation"
|
||||
"-framework AppKit"
|
||||
"-framework CoreFoundation"
|
||||
"-framework CoreServices"
|
||||
"-framework Quartz"
|
||||
"-framework UniformTypeIdentifiers"
|
||||
"-framework QuickLook")
|
||||
|
||||
install(
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
#if __has_feature(modules)
|
||||
@import AppKit;
|
||||
@import CoreFoundation;
|
||||
@import QuickLook;
|
||||
#else
|
||||
#import <AppKit/AppKit.h>
|
||||
#import <CoreFoundation/CFPlugInCOM.h>
|
||||
#import <QuickLook/QuickLook.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
#if __has_feature(modules)
|
||||
@import CoreFoundation;
|
||||
@import QuickLook;
|
||||
#else
|
||||
#import <CoreFoundation/CoreFoundation.h>
|
||||
#import <CoreFoundation/CFPlugInCOM.h>
|
||||
#import <QuickLook/QuickLook.h>
|
||||
#endif
|
||||
|
||||
QL_EXTERN_C_BEGIN
|
||||
OSStatus GenerateThumbnailForURL(void* thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize);
|
||||
|
||||
@@ -2,8 +2,13 @@
|
||||
// It may be used under the MIT (SPDX: MIT) license.
|
||||
// License text can be found in the licenses/ folder.
|
||||
|
||||
#if __has_feature(modules)
|
||||
@import ObjectiveC;
|
||||
@import AppKit;
|
||||
#else
|
||||
#import <objc/runtime.h>
|
||||
#import <AppKit/AppKit.h>
|
||||
#endif
|
||||
#import "NSStringAdditions.h"
|
||||
|
||||
// Development-only proxy when app is not signed for running Sparkle
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
// It may be used under the MIT (SPDX: MIT) license.
|
||||
// License text can be found in the licenses/ folder.
|
||||
|
||||
#if __has_feature(modules)
|
||||
@import AppKit;
|
||||
#else
|
||||
#import <AppKit/AppKit.h>
|
||||
#endif
|
||||
|
||||
#include <libtransmission/transmission.h>
|
||||
|
||||
|
||||
@@ -3,6 +3,11 @@ HeaderFilterRegex: .*/tests/libtransmission/.*
|
||||
|
||||
# Many of these checks are disabled only because the code hasn't been
|
||||
# cleaned up yet. Pull requests welcomed.
|
||||
#
|
||||
# -modernize-loop-convert (P0896R4): GCC 10.1, clang 15
|
||||
# -readability-container-contains (P0458R2): GCC 9.1, clang 13
|
||||
# Ref: https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html
|
||||
# Ref: https://libcxx.llvm.org/Status/Cxx20.html
|
||||
Checks: >
|
||||
bugprone-*,
|
||||
-bugprone-easily-swappable-parameters,
|
||||
@@ -30,9 +35,13 @@ Checks: >
|
||||
-misc-no-recursion,
|
||||
-misc-non-private-member-variables-in-classes,
|
||||
modernize-*,
|
||||
-modernize-loop-convert,
|
||||
-modernize-use-designated-initializers,
|
||||
-modernize-use-ranges,
|
||||
-modernize-use-trailing-return-type,
|
||||
performance-*,
|
||||
readability-*,
|
||||
-readability-container-contains,
|
||||
-readability-enum-initial-value,
|
||||
-readability-function-cognitive-complexity,
|
||||
-readability-identifier-length,
|
||||
|
||||
@@ -635,35 +635,38 @@ TEST_F(AnnouncerUdpTest, canAnnounceIPv4)
|
||||
{ tr_address::from_string("192.168.1.3"sv).value_or(tr_address{}), tr_port::from_host(2022) },
|
||||
} };
|
||||
|
||||
auto request = tr_announce_request{};
|
||||
request.event = TR_ANNOUNCE_EVENT_STARTED;
|
||||
request.port = tr_port::from_host(80);
|
||||
request.key = 0xCAFE;
|
||||
request.numwant = 20;
|
||||
request.up = 1;
|
||||
request.down = 2;
|
||||
request.corrupt = 3;
|
||||
request.leftUntilComplete = 100;
|
||||
request.announce_url = "https://127.0.0.1/announce"sv;
|
||||
request.tracker_id = "fnord"s;
|
||||
request.peer_id = tr_peerIdInit();
|
||||
request.info_hash = tr_rand_obj<tr_sha1_digest_t>();
|
||||
auto const request = tr_announce_request{
|
||||
.event = TR_ANNOUNCE_EVENT_STARTED,
|
||||
.port = tr_port::from_host(80),
|
||||
.key = 0xCAFE,
|
||||
.numwant = 20,
|
||||
.up = 1,
|
||||
.down = 2,
|
||||
.corrupt = 3,
|
||||
.leftUntilComplete = 100,
|
||||
.announce_url = tr_interned_string{ "https://127.0.0.1/announce"sv },
|
||||
.tracker_id = "fnord"s,
|
||||
.peer_id = tr_peerIdInit(),
|
||||
.info_hash = tr_rand_obj<tr_sha1_digest_t>(),
|
||||
.log_name = {},
|
||||
};
|
||||
|
||||
auto expected_response = tr_announce_response{};
|
||||
expected_response.info_hash = request.info_hash;
|
||||
expected_response.did_connect = true;
|
||||
expected_response.did_timeout = false;
|
||||
expected_response.interval = Interval;
|
||||
expected_response.min_interval = 0; // not specified in UDP announce
|
||||
expected_response.seeders = Seeders;
|
||||
expected_response.leechers = Leechers;
|
||||
expected_response.downloads = std::nullopt; // not specified in UDP announce
|
||||
expected_response.pex = std::vector<tr_pex>{ tr_pex{ addresses[0] }, tr_pex{ addresses[1] }, tr_pex{ addresses[2] } };
|
||||
expected_response.pex6 = {};
|
||||
expected_response.errmsg = {};
|
||||
expected_response.warning = {};
|
||||
expected_response.tracker_id = {}; // not specified in UDP announce
|
||||
expected_response.external_ip = {};
|
||||
auto const expected_response = tr_announce_response{
|
||||
.info_hash = request.info_hash,
|
||||
.did_connect = true,
|
||||
.did_timeout = false,
|
||||
.interval = Interval,
|
||||
.min_interval = 0, // not specified in UDP announce
|
||||
.seeders = Seeders,
|
||||
.leechers = Leechers,
|
||||
.downloads = std::nullopt, // not specified in UDP announce
|
||||
.pex = std::vector{ tr_pex{ addresses[0] }, tr_pex{ addresses[1] }, tr_pex{ addresses[2] } },
|
||||
.pex6 = {},
|
||||
.errmsg = {},
|
||||
.warning = {},
|
||||
.tracker_id = {}, // not specified in UDP announce
|
||||
.external_ip = {},
|
||||
};
|
||||
|
||||
// build the announcer
|
||||
auto mediator = MockMediator{};
|
||||
@@ -718,35 +721,38 @@ TEST_F(AnnouncerUdpTest, canAnnounceIPv6)
|
||||
{ tr_address::from_string("fd12:3456:789a:1::3"sv).value_or(tr_address{}), tr_port::from_host(2022) },
|
||||
} };
|
||||
|
||||
auto request = tr_announce_request{};
|
||||
request.event = TR_ANNOUNCE_EVENT_STARTED;
|
||||
request.port = tr_port::from_host(80);
|
||||
request.key = 0xCAFE;
|
||||
request.numwant = 20;
|
||||
request.up = 1;
|
||||
request.down = 2;
|
||||
request.corrupt = 3;
|
||||
request.leftUntilComplete = 100;
|
||||
request.announce_url = "https://[::1]/announce"sv;
|
||||
request.tracker_id = "fnord"s;
|
||||
request.peer_id = tr_peerIdInit();
|
||||
request.info_hash = tr_rand_obj<tr_sha1_digest_t>();
|
||||
auto const request = tr_announce_request{
|
||||
.event = TR_ANNOUNCE_EVENT_STARTED,
|
||||
.port = tr_port::from_host(80),
|
||||
.key = 0xCAFE,
|
||||
.numwant = 20,
|
||||
.up = 1,
|
||||
.down = 2,
|
||||
.corrupt = 3,
|
||||
.leftUntilComplete = 100,
|
||||
.announce_url = tr_interned_string{ "https://[::1]/announce"sv },
|
||||
.tracker_id = "fnord"s,
|
||||
.peer_id = tr_peerIdInit(),
|
||||
.info_hash = tr_rand_obj<tr_sha1_digest_t>(),
|
||||
.log_name = {},
|
||||
};
|
||||
|
||||
auto expected_response = tr_announce_response{};
|
||||
expected_response.info_hash = request.info_hash;
|
||||
expected_response.did_connect = true;
|
||||
expected_response.did_timeout = false;
|
||||
expected_response.interval = Interval;
|
||||
expected_response.min_interval = 0; // not specified in UDP announce
|
||||
expected_response.seeders = Seeders;
|
||||
expected_response.leechers = Leechers;
|
||||
expected_response.downloads = std::nullopt; // not specified in UDP announce
|
||||
expected_response.pex = {};
|
||||
expected_response.pex6 = std::vector<tr_pex>{ tr_pex{ addresses[0] }, tr_pex{ addresses[1] }, tr_pex{ addresses[2] } };
|
||||
expected_response.errmsg = {};
|
||||
expected_response.warning = {};
|
||||
expected_response.tracker_id = {}; // not specified in UDP announce
|
||||
expected_response.external_ip = {};
|
||||
auto const expected_response = tr_announce_response{
|
||||
.info_hash = request.info_hash,
|
||||
.did_connect = true,
|
||||
.did_timeout = false,
|
||||
.interval = Interval,
|
||||
.min_interval = 0, // not specified in UDP announce
|
||||
.seeders = Seeders,
|
||||
.leechers = Leechers,
|
||||
.downloads = std::nullopt, // not specified in UDP announce
|
||||
.pex = {},
|
||||
.pex6 = std::vector{ tr_pex{ addresses[0] }, tr_pex{ addresses[1] }, tr_pex{ addresses[2] } },
|
||||
.errmsg = {},
|
||||
.warning = {},
|
||||
.tracker_id = {}, // not specified in UDP announce
|
||||
.external_ip = {},
|
||||
};
|
||||
|
||||
// build the announcer
|
||||
auto mediator = MockMediator{};
|
||||
|
||||
@@ -147,16 +147,20 @@ public:
|
||||
static auto constexpr PlaintextProtocolName = "\023BitTorrent protocol"sv;
|
||||
|
||||
tr_socket_address const DefaultPeerSockAddr{ *tr_address::from_string("127.0.0.1"sv), tr_port::from_host(8080) };
|
||||
tr_handshake::Mediator::TorrentInfo const TorrentWeAreSeeding{ tr_sha1::digest("abcde"sv),
|
||||
tr_peerIdInit(),
|
||||
tr_torrent_id_t{ 100 },
|
||||
true /*is_done*/,
|
||||
true /*is_running*/ };
|
||||
tr_handshake::Mediator::TorrentInfo const UbuntuTorrent{ *tr_sha1_from_string("2c6b6858d61da9543d4231a71db4b1c9264b0685"sv),
|
||||
tr_peerIdInit(),
|
||||
tr_torrent_id_t{ 101 },
|
||||
false /*is_done*/,
|
||||
true /*is_running*/ };
|
||||
tr_handshake::Mediator::TorrentInfo const TorrentWeAreSeeding{
|
||||
.info_hash = tr_sha1::digest("abcde"sv),
|
||||
.client_peer_id = tr_peerIdInit(),
|
||||
.id = tr_torrent_id_t{ 100 },
|
||||
.is_done = true,
|
||||
.is_running = true,
|
||||
};
|
||||
tr_handshake::Mediator::TorrentInfo const UbuntuTorrent{
|
||||
.info_hash = *tr_sha1_from_string("2c6b6858d61da9543d4231a71db4b1c9264b0685"sv),
|
||||
.client_peer_id = tr_peerIdInit(),
|
||||
.id = tr_torrent_id_t{ 101 },
|
||||
.is_done = false,
|
||||
.is_running = true,
|
||||
};
|
||||
|
||||
auto createIncomingIo(tr_session* session)
|
||||
{
|
||||
|
||||
@@ -735,6 +735,7 @@ TEST_F(VariantTest, visitsNodesDepthFirst)
|
||||
node.visit(
|
||||
[&](auto const& val)
|
||||
{
|
||||
// TODO(c++20): use std::remove_cvref_t (P0550R2) when GCC >= 9.1
|
||||
using ValueType = std::decay_t<decltype(val)>;
|
||||
|
||||
if constexpr (
|
||||
|
||||
Reference in New Issue
Block a user