mirror of https://github.com/OpenTTD/OpenTTD
Codechange: introduce BaseBitSet as base for EnumBitSet
parent
b9777269ce
commit
e972033e11
|
@ -3,6 +3,7 @@ add_files(
|
||||||
alloc_func.hpp
|
alloc_func.hpp
|
||||||
alloc_type.hpp
|
alloc_type.hpp
|
||||||
backup_type.hpp
|
backup_type.hpp
|
||||||
|
base_bitset_type.hpp
|
||||||
bitmath_func.hpp
|
bitmath_func.hpp
|
||||||
convertible_through_base.hpp
|
convertible_through_base.hpp
|
||||||
endian_func.hpp
|
endian_func.hpp
|
||||||
|
|
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file base_bitset_type.hpp Base for bitset types that accept strong types,
|
||||||
|
* i.e. types that need some casting like StrongType and enum class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BASE_BITSET_TYPE_HPP
|
||||||
|
#define BASE_BITSET_TYPE_HPP
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base for bit set wrapper.
|
||||||
|
* Allows wrapping strong type values as a bit set. Methods are loosely modelled on std::bitset.
|
||||||
|
* @tparam Tvalue_type Type of values to wrap.
|
||||||
|
* @tparam Tstorage Storage type required to hold values.
|
||||||
|
*/
|
||||||
|
template <typename Timpl, typename Tvalue_type, typename Tstorage>
|
||||||
|
class BaseBitSet {
|
||||||
|
public:
|
||||||
|
using ValueType = Tvalue_type; ///< Value type of this BaseBitSet.
|
||||||
|
using BaseType = Tstorage; ///< Storage type of this BaseBitSet, be ConvertibleThroughBase
|
||||||
|
|
||||||
|
constexpr BaseBitSet() : data(0) {}
|
||||||
|
explicit constexpr BaseBitSet(Tstorage data) : data(data) {}
|
||||||
|
|
||||||
|
constexpr auto operator <=>(const BaseBitSet &) const noexcept = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value-th bit.
|
||||||
|
* @param value Bit to set.
|
||||||
|
* @returns The bit set
|
||||||
|
*/
|
||||||
|
inline constexpr Timpl &Set(Tvalue_type value)
|
||||||
|
{
|
||||||
|
this->data |= (1ULL << Timpl::DecayValueType(value));
|
||||||
|
return static_cast<Timpl&>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the value-th bit.
|
||||||
|
* @param value Bit to reset.
|
||||||
|
* @returns The bit set
|
||||||
|
*/
|
||||||
|
inline constexpr Timpl &Reset(Tvalue_type value)
|
||||||
|
{
|
||||||
|
this->data &= ~(1ULL << Timpl::DecayValueType(value));
|
||||||
|
return static_cast<Timpl&>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flip the value-th bit.
|
||||||
|
* @param value Bit to flip.
|
||||||
|
* @returns The bit set
|
||||||
|
*/
|
||||||
|
inline constexpr Timpl &Flip(Tvalue_type value)
|
||||||
|
{
|
||||||
|
if (this->Test(value)) {
|
||||||
|
return this->Reset(value);
|
||||||
|
} else {
|
||||||
|
return this->Set(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if the value-th bit is set.
|
||||||
|
* @param value Bit to check.
|
||||||
|
* @returns true iff the requested bit is set.
|
||||||
|
*/
|
||||||
|
inline constexpr bool Test(Tvalue_type value) const
|
||||||
|
{
|
||||||
|
return (this->data & (1ULL << Timpl::DecayValueType(value))) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if all of the values are set.
|
||||||
|
* @param other BitSet of values to test.
|
||||||
|
* @returns true iff all of the values are set.
|
||||||
|
*/
|
||||||
|
inline constexpr bool All(const Timpl &other) const
|
||||||
|
{
|
||||||
|
return (this->data & other.data) == other.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if any of the given values are set.
|
||||||
|
* @param other BitSet of values to test.
|
||||||
|
* @returns true iff any of the given values are set.
|
||||||
|
*/
|
||||||
|
inline constexpr bool Any(const Timpl &other) const
|
||||||
|
{
|
||||||
|
return (this->data & other.data) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if any of the values are set.
|
||||||
|
* @returns true iff any of the values are set.
|
||||||
|
*/
|
||||||
|
inline constexpr bool Any() const
|
||||||
|
{
|
||||||
|
return this->data != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if none of the values are set.
|
||||||
|
* @returns true iff none of the values are set.
|
||||||
|
*/
|
||||||
|
inline constexpr bool None() const
|
||||||
|
{
|
||||||
|
return this->data == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr Timpl operator |(const Timpl &other) const
|
||||||
|
{
|
||||||
|
return Timpl{static_cast<Tstorage>(this->data | other.data)};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr Timpl operator &(const Timpl &other) const
|
||||||
|
{
|
||||||
|
return Timpl{static_cast<Tstorage>(this->data & other.data)};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the raw value behind this bit set.
|
||||||
|
* @returns the raw value.
|
||||||
|
*/
|
||||||
|
inline constexpr Tstorage base() const noexcept
|
||||||
|
{
|
||||||
|
return this->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Tstorage data; ///< Bitmask of values.
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* BASE_BITSET_TYPE_HPP */
|
|
@ -10,6 +10,8 @@
|
||||||
#ifndef ENUM_TYPE_HPP
|
#ifndef ENUM_TYPE_HPP
|
||||||
#define ENUM_TYPE_HPP
|
#define ENUM_TYPE_HPP
|
||||||
|
|
||||||
|
#include "base_bitset_type.hpp"
|
||||||
|
|
||||||
/** Implementation of std::to_underlying (from C++23) */
|
/** Implementation of std::to_underlying (from C++23) */
|
||||||
template <typename enum_type>
|
template <typename enum_type>
|
||||||
constexpr std::underlying_type_t<enum_type> to_underlying(enum_type e) { return static_cast<std::underlying_type_t<enum_type>>(e); }
|
constexpr std::underlying_type_t<enum_type> to_underlying(enum_type e) { return static_cast<std::underlying_type_t<enum_type>>(e); }
|
||||||
|
@ -117,21 +119,21 @@ debug_inline constexpr void ToggleFlag(T &x, const T y)
|
||||||
* @tparam Tend_value Last valid value + 1.
|
* @tparam Tend_value Last valid value + 1.
|
||||||
*/
|
*/
|
||||||
template <typename Tenum, typename Tstorage, Tenum Tend_value = Tenum{std::numeric_limits<Tstorage>::digits}>
|
template <typename Tenum, typename Tstorage, Tenum Tend_value = Tenum{std::numeric_limits<Tstorage>::digits}>
|
||||||
class EnumBitSet {
|
class EnumBitSet : public BaseBitSet<EnumBitSet<Tenum, Tstorage, Tend_value>, Tenum, Tstorage> {
|
||||||
|
using BaseClass = BaseBitSet<EnumBitSet<Tenum, Tstorage, Tend_value>, Tenum, Tstorage>;
|
||||||
public:
|
public:
|
||||||
using EnumType = Tenum; ///< Enum type of this EnumBitSet.
|
using EnumType = BaseClass::ValueType;
|
||||||
using BaseType = Tstorage; ///< Storage type of this EnumBitSet, be ConvertibleThroughBase
|
|
||||||
static constexpr Tstorage MASK = std::numeric_limits<Tstorage>::max() >> (std::numeric_limits<Tstorage>::digits - to_underlying(Tend_value)); ///< Mask of valid values.
|
static constexpr Tstorage MASK = std::numeric_limits<Tstorage>::max() >> (std::numeric_limits<Tstorage>::digits - to_underlying(Tend_value)); ///< Mask of valid values.
|
||||||
|
|
||||||
constexpr EnumBitSet() : data(0) {}
|
constexpr EnumBitSet() : BaseClass() {}
|
||||||
constexpr EnumBitSet(Tenum value) : data(0) { this->Set(value); }
|
constexpr EnumBitSet(Tenum value) : BaseClass() { this->Set(value); }
|
||||||
explicit constexpr EnumBitSet(Tstorage data) : data(data & MASK) {}
|
explicit constexpr EnumBitSet(Tstorage data) : BaseClass(data & MASK) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an EnumBitSet from a list of enum values.
|
* Construct an EnumBitSet from a list of enum values.
|
||||||
* @param values List of enum values.
|
* @param values List of enum values.
|
||||||
*/
|
*/
|
||||||
constexpr EnumBitSet(std::initializer_list<const Tenum> values) : data(0)
|
constexpr EnumBitSet(std::initializer_list<const Tenum> values) : BaseClass()
|
||||||
{
|
{
|
||||||
for (const Tenum &value : values) {
|
for (const Tenum &value : values) {
|
||||||
this->Set(value);
|
this->Set(value);
|
||||||
|
@ -140,102 +142,16 @@ public:
|
||||||
|
|
||||||
constexpr auto operator <=>(const EnumBitSet &) const noexcept = default;
|
constexpr auto operator <=>(const EnumBitSet &) const noexcept = default;
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the enum value.
|
|
||||||
* @param value Enum value to set.
|
|
||||||
* @returns The EnumBitset
|
|
||||||
*/
|
|
||||||
inline constexpr EnumBitSet &Set(Tenum value)
|
|
||||||
{
|
|
||||||
this->data |= (1ULL << to_underlying(value));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the enum value to not set.
|
|
||||||
* @param value Enum value to reset.
|
|
||||||
* @returns The EnumBitset
|
|
||||||
*/
|
|
||||||
inline constexpr EnumBitSet &Reset(Tenum value)
|
|
||||||
{
|
|
||||||
this->data &= ~(1ULL << to_underlying(value));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flip the enum value.
|
|
||||||
* @param value Enum value to flip.
|
|
||||||
* @returns The EnumBitset
|
|
||||||
*/
|
|
||||||
inline constexpr EnumBitSet &Flip(Tenum value)
|
|
||||||
{
|
|
||||||
if (this->Test(value)) {
|
|
||||||
return this->Reset(value);
|
|
||||||
} else {
|
|
||||||
return this->Set(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test if the enum value is set.
|
|
||||||
* @param value Enum value to check.
|
|
||||||
* @returns true iff the requested value is set.
|
|
||||||
*/
|
|
||||||
inline constexpr bool Test(Tenum value) const
|
|
||||||
{
|
|
||||||
return (this->data & (1ULL << to_underlying(value))) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test if all of the enum values are set.
|
|
||||||
* @param other BitSet of enum values to test.
|
|
||||||
* @returns true iff all of the enum values are set.
|
|
||||||
*/
|
|
||||||
inline constexpr bool All(const EnumBitSet &other) const
|
|
||||||
{
|
|
||||||
return (this->data & other.data) == other.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test if any of the enum values are set.
|
|
||||||
* @param other BitSet of enum values to test.
|
|
||||||
* @returns true iff any of the enum values are set.
|
|
||||||
*/
|
|
||||||
inline constexpr bool Any(const EnumBitSet &other) const
|
|
||||||
{
|
|
||||||
return (this->data & other.data) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline constexpr EnumBitSet operator |(const EnumBitSet &other) const
|
|
||||||
{
|
|
||||||
return EnumBitSet{static_cast<Tstorage>(this->data | other.data)};
|
|
||||||
}
|
|
||||||
|
|
||||||
inline constexpr EnumBitSet operator &(const EnumBitSet &other) const
|
|
||||||
{
|
|
||||||
return EnumBitSet{static_cast<Tstorage>(this->data & other.data)};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that the raw value of this EnumBitSet is valid.
|
* Test that the raw value of this EnumBitSet is valid.
|
||||||
* @returns true iff the no bits outside the masked value are set.
|
* @returns true iff the no bits outside the masked value are set.
|
||||||
*/
|
*/
|
||||||
inline constexpr bool IsValid() const
|
inline constexpr bool IsValid() const
|
||||||
{
|
{
|
||||||
return (this->data & MASK) == this->data;
|
return (this->base() & MASK) == this->base();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static constexpr size_t DecayValueType(const BaseClass::ValueType &value) { return to_underlying(value); }
|
||||||
* Retrieve the raw value behind this EnumBitSet.
|
|
||||||
* @returns the raw value.
|
|
||||||
*/
|
|
||||||
inline constexpr Tstorage base() const noexcept
|
|
||||||
{
|
|
||||||
return this->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Tstorage data; ///< Bitmask of enum values.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* ENUM_TYPE_HPP */
|
#endif /* ENUM_TYPE_HPP */
|
||||||
|
|
Loading…
Reference in New Issue