mirror of
https://github.com/transmission/transmission.git
synced 2025-12-24 20:35:36 +00:00
fix: ChangeFlag bitwise operations (#7613)
* unbreak ChangeFlag bitwise operations (Fix #7572) 8 bits is not enough to do bitwise comparisons on more than 8 independent values: use std:bitset to ensure proper bitwise operations inside ChangeFlags(). * refactor: use bitset methods and specify TR_CONSTEXPR23 --------- Co-authored-by: Yat Ho <lagoho7@gmail.com> Co-authored-by: Charles Kerr <charles@charleskerr.com>
This commit is contained in:
@@ -13,6 +13,8 @@
|
||||
#include "TorrentFilter.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#include <libtransmission/tr-macros.h>
|
||||
|
||||
#include <gdkmm/pixbuf.h>
|
||||
#include <glibmm/i18n.h>
|
||||
#include <glibmm/main.h>
|
||||
@@ -604,7 +606,7 @@ void FilterBar::Impl::update_count_label_idle()
|
||||
|
||||
void FilterBar::Impl::update_filter_models(Torrent::ChangeFlags changes)
|
||||
{
|
||||
static auto constexpr activity_flags = Torrent::ChangeFlag::ACTIVE_PEERS_DOWN | Torrent::ChangeFlag::ACTIVE_PEERS_UP |
|
||||
static auto TR_CONSTEXPR23 activity_flags = Torrent::ChangeFlag::ACTIVE_PEERS_DOWN | Torrent::ChangeFlag::ACTIVE_PEERS_UP |
|
||||
Torrent::ChangeFlag::ACTIVE | Torrent::ChangeFlag::ACTIVITY | Torrent::ChangeFlag::ERROR_CODE |
|
||||
Torrent::ChangeFlag::FINISHED;
|
||||
static auto constexpr tracker_flags = Torrent::ChangeFlag::TRACKERS;
|
||||
|
||||
51
gtk/Flags.h
51
gtk/Flags.h
@@ -5,13 +5,16 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <libtransmission/tr-macros.h>
|
||||
|
||||
#include <bitset>
|
||||
#include <initializer_list>
|
||||
#include <type_traits>
|
||||
|
||||
// NOLINTBEGIN(bugprone-macro-parentheses, cppcoreguidelines-macro-usage)
|
||||
|
||||
#define DEFINE_FLAGS_OPERATORS(FlagType) \
|
||||
constexpr inline Flags<FlagType> operator|(FlagType lhs, FlagType rhs) noexcept \
|
||||
TR_CONSTEXPR23 inline Flags<FlagType> operator|(FlagType lhs, FlagType rhs) noexcept \
|
||||
{ \
|
||||
return { lhs, rhs }; \
|
||||
}
|
||||
@@ -23,20 +26,21 @@ class Flags
|
||||
{
|
||||
public:
|
||||
using FlagType = T;
|
||||
using ValueType = std::make_unsigned_t<std::underlying_type_t<FlagType>>;
|
||||
using EnumValueType = std::make_unsigned_t<std::underlying_type_t<FlagType>>;
|
||||
using BitsetType = std::bitset<static_cast<EnumValueType>(FlagType::N_FLAGS)>;
|
||||
|
||||
static_assert(std::is_enum_v<FlagType> && !std::is_convertible_v<FlagType, ValueType>);
|
||||
static_assert(std::is_enum_v<FlagType> && !std::is_convertible_v<FlagType, BitsetType>);
|
||||
|
||||
public:
|
||||
constexpr Flags() noexcept = default;
|
||||
|
||||
// NOLINTNEXTLINE(hicpp-explicit-conversions)
|
||||
constexpr Flags(FlagType flag) noexcept
|
||||
TR_CONSTEXPR23 Flags(FlagType flag) noexcept
|
||||
{
|
||||
set(flag);
|
||||
}
|
||||
|
||||
constexpr Flags(std::initializer_list<FlagType> flags) noexcept
|
||||
TR_CONSTEXPR23 Flags(std::initializer_list<FlagType> flags) noexcept
|
||||
{
|
||||
for (auto const flag : flags)
|
||||
{
|
||||
@@ -44,58 +48,53 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool none() const noexcept
|
||||
[[nodiscard]] TR_CONSTEXPR23 bool none() const noexcept
|
||||
{
|
||||
return value_ == 0;
|
||||
return value_.none();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool any() const noexcept
|
||||
[[nodiscard]] TR_CONSTEXPR23 bool any() const noexcept
|
||||
{
|
||||
return !none();
|
||||
return value_.any();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool test(FlagType flag) const noexcept
|
||||
[[nodiscard]] TR_CONSTEXPR23 bool test(FlagType flag) const noexcept
|
||||
{
|
||||
return (value_ & get_mask(flag)) != 0;
|
||||
return value_.test(static_cast<EnumValueType>(flag));
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool test(Flags rhs) const noexcept
|
||||
[[nodiscard]] TR_CONSTEXPR23 bool test(Flags rhs) const noexcept
|
||||
{
|
||||
return (value_ & rhs.value_) != 0;
|
||||
return (value_ & rhs.value_).any();
|
||||
}
|
||||
|
||||
constexpr void set(FlagType flag) noexcept
|
||||
TR_CONSTEXPR23 void set(FlagType flag) noexcept
|
||||
{
|
||||
value_ |= get_mask(flag);
|
||||
value_.set(static_cast<EnumValueType>(flag));
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr Flags operator|(Flags rhs) const noexcept
|
||||
[[nodiscard]] TR_CONSTEXPR23 Flags operator|(Flags rhs) const noexcept
|
||||
{
|
||||
return Flags(value_ | rhs.value_);
|
||||
}
|
||||
|
||||
constexpr Flags& operator|=(Flags rhs) noexcept
|
||||
TR_CONSTEXPR23 Flags& operator|=(Flags rhs) noexcept
|
||||
{
|
||||
value_ |= rhs.value_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr Flags operator~() const noexcept
|
||||
[[nodiscard]] TR_CONSTEXPR23 Flags operator~() const noexcept
|
||||
{
|
||||
return Flags(~value_);
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr explicit Flags(ValueType value) noexcept
|
||||
: value_(value)
|
||||
constexpr explicit Flags(BitsetType value) noexcept
|
||||
: value_(std::move(value))
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr ValueType get_mask(FlagType flag) noexcept
|
||||
{
|
||||
return ValueType{ 1 } << static_cast<ValueType>(flag);
|
||||
}
|
||||
|
||||
private:
|
||||
ValueType value_ = {};
|
||||
BitsetType value_ = {};
|
||||
};
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "Utils.h"
|
||||
|
||||
#include <libtransmission/transmission.h>
|
||||
#include <libtransmission/tr-macros.h>
|
||||
#include <libtransmission/utils.h>
|
||||
#include <libtransmission/values.h>
|
||||
|
||||
@@ -362,23 +363,24 @@ void Torrent::Impl::notify_property_changes(ChangeFlags changes) const
|
||||
|
||||
#if GTKMM_CHECK_VERSION(4, 0, 0)
|
||||
|
||||
static auto constexpr properties_flags = std::array<std::pair<Property, ChangeFlags>, PropertyStore::PropertyCount - 1>({ {
|
||||
{ Property::ICON, ChangeFlag::MIME_TYPE },
|
||||
{ Property::NAME, ChangeFlag::NAME },
|
||||
{ Property::PERCENT_DONE, ChangeFlag::PERCENT_DONE },
|
||||
{ Property::SHORT_STATUS,
|
||||
ChangeFlag::ACTIVE_PEERS_DOWN | ChangeFlag::ACTIVE_PEERS_UP | ChangeFlag::ACTIVITY | ChangeFlag::FINISHED |
|
||||
ChangeFlag::RATIO | ChangeFlag::RECHECK_PROGRESS | ChangeFlag::SPEED_DOWN | ChangeFlag::SPEED_UP },
|
||||
{ Property::LONG_PROGRESS,
|
||||
ChangeFlag::ACTIVITY | ChangeFlag::ETA | ChangeFlag::LONG_PROGRESS | ChangeFlag::PERCENT_COMPLETE |
|
||||
ChangeFlag::PERCENT_DONE | ChangeFlag::RATIO | ChangeFlag::TOTAL_SIZE },
|
||||
{ Property::LONG_STATUS,
|
||||
ChangeFlag::ACTIVE_PEERS_DOWN | ChangeFlag::ACTIVE_PEERS_UP | ChangeFlag::ACTIVITY | ChangeFlag::ERROR_CODE |
|
||||
ChangeFlag::ERROR_MESSAGE | ChangeFlag::HAS_METADATA | ChangeFlag::LONG_STATUS | ChangeFlag::SPEED_DOWN |
|
||||
ChangeFlag::SPEED_UP | ChangeFlag::STALLED },
|
||||
{ Property::SENSITIVE, ChangeFlag::ACTIVITY },
|
||||
{ Property::CSS_CLASSES, ChangeFlag::ACTIVITY | ChangeFlag::ERROR_CODE },
|
||||
} });
|
||||
static auto TR_CONSTEXPR23
|
||||
properties_flags = std::array<std::pair<Property, ChangeFlags>, PropertyStore::PropertyCount - 1>({ {
|
||||
{ Property::ICON, ChangeFlag::MIME_TYPE },
|
||||
{ Property::NAME, ChangeFlag::NAME },
|
||||
{ Property::PERCENT_DONE, ChangeFlag::PERCENT_DONE },
|
||||
{ Property::SHORT_STATUS,
|
||||
ChangeFlag::ACTIVE_PEERS_DOWN | ChangeFlag::ACTIVE_PEERS_UP | ChangeFlag::ACTIVITY | ChangeFlag::FINISHED |
|
||||
ChangeFlag::RATIO | ChangeFlag::RECHECK_PROGRESS | ChangeFlag::SPEED_DOWN | ChangeFlag::SPEED_UP },
|
||||
{ Property::LONG_PROGRESS,
|
||||
ChangeFlag::ACTIVITY | ChangeFlag::ETA | ChangeFlag::LONG_PROGRESS | ChangeFlag::PERCENT_COMPLETE |
|
||||
ChangeFlag::PERCENT_DONE | ChangeFlag::RATIO | ChangeFlag::TOTAL_SIZE },
|
||||
{ Property::LONG_STATUS,
|
||||
ChangeFlag::ACTIVE_PEERS_DOWN | ChangeFlag::ACTIVE_PEERS_UP | ChangeFlag::ACTIVITY | ChangeFlag::ERROR_CODE |
|
||||
ChangeFlag::ERROR_MESSAGE | ChangeFlag::HAS_METADATA | ChangeFlag::LONG_STATUS | ChangeFlag::SPEED_DOWN |
|
||||
ChangeFlag::SPEED_UP | ChangeFlag::STALLED },
|
||||
{ Property::SENSITIVE, ChangeFlag::ACTIVITY },
|
||||
{ Property::CSS_CLASSES, ChangeFlag::ACTIVITY | ChangeFlag::ERROR_CODE },
|
||||
} });
|
||||
|
||||
auto& properties = PropertyStore::get();
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ public:
|
||||
STALLED,
|
||||
TOTAL_SIZE,
|
||||
TRACKERS,
|
||||
N_FLAGS,
|
||||
};
|
||||
|
||||
using ChangeFlags = Flags<ChangeFlag>;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "Utils.h"
|
||||
|
||||
#include <libtransmission/transmission.h>
|
||||
#include <libtransmission/tr-macros.h>
|
||||
|
||||
#include <array>
|
||||
#include <utility>
|
||||
@@ -130,7 +131,7 @@ void TorrentFilter::update(Torrent::ChangeFlags changes)
|
||||
|
||||
if (activity_type_ != Activity::ALL)
|
||||
{
|
||||
static constexpr auto ActivityFlags = std::array<std::pair<Activity, Torrent::ChangeFlags>, 7U>{ {
|
||||
static auto TR_CONSTEXPR23 ActivityFlags = std::array<std::pair<Activity, Torrent::ChangeFlags>, 7U>{ {
|
||||
{ Activity::DOWNLOADING, Flag::ACTIVITY },
|
||||
{ Activity::SEEDING, Flag::ACTIVITY },
|
||||
{ Activity::ACTIVE, Flag::ACTIVE_PEER_COUNT | Flag::ACTIVITY },
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "Utils.h"
|
||||
|
||||
#include <libtransmission/transmission.h>
|
||||
#include <libtransmission/tr-macros.h>
|
||||
#include <libtransmission/utils.h>
|
||||
|
||||
#include <algorithm>
|
||||
@@ -226,7 +227,7 @@ int TorrentSorter::compare(Torrent const& lhs, Torrent const& rhs) const
|
||||
void TorrentSorter::update(Torrent::ChangeFlags changes)
|
||||
{
|
||||
using Flag = Torrent::ChangeFlag;
|
||||
static auto constexpr CompareFlags = std::array<std::pair<CompareFunc, Torrent::ChangeFlags>, 9U>{ {
|
||||
static auto TR_CONSTEXPR23 CompareFlags = std::array<std::pair<CompareFunc, Torrent::ChangeFlags>, 9U>{ {
|
||||
{ &compare_by_activity, Flag::ACTIVE_PEER_COUNT | Flag::QUEUE_POSITION | Flag::SPEED_DOWN | Flag::SPEED_UP },
|
||||
{ &compare_by_age, Flag::ADDED_DATE | Flag::NAME },
|
||||
{ &compare_by_eta, Flag::ETA | Flag::NAME },
|
||||
|
||||
Reference in New Issue
Block a user