duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

bitfield.h (3499B)


      1 // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
      2 // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
      3 
      4 #pragma once
      5 #include "types.h"
      6 #include <type_traits>
      7 
      8 // Disable MSVC warnings that we actually handle
      9 #ifdef _MSC_VER
     10 #pragma warning(push)
     11 #pragma warning(disable : 4800) // warning C4800: 'int': forcing value to bool 'true' or 'false' (performance warning)
     12 #endif
     13 
     14 template<typename BackingDataType, typename DataType, unsigned BitIndex, unsigned BitCount>
     15 struct BitField
     16 {
     17   static_assert(!std::is_same_v<DataType, bool> || BitCount == 1, "Boolean bitfields should only be 1 bit");
     18 
     19   // We have to delete the copy assignment operator otherwise we can't use this class in anonymous structs/unions.
     20   BitField& operator=(const BitField& rhs) = delete;
     21 
     22   ALWAYS_INLINE constexpr BackingDataType GetMask() const
     23   {
     24     return ((static_cast<BackingDataType>(~0)) >> (8 * sizeof(BackingDataType) - BitCount)) << BitIndex;
     25   }
     26 
     27   ALWAYS_INLINE constexpr operator DataType() const { return GetValue(); }
     28 
     29   ALWAYS_INLINE constexpr BitField& operator=(DataType value)
     30   {
     31     SetValue(value);
     32     return *this;
     33   }
     34 
     35   ALWAYS_INLINE constexpr DataType operator++()
     36   {
     37     DataType value = GetValue() + 1;
     38     SetValue(value);
     39     return GetValue();
     40   }
     41 
     42   ALWAYS_INLINE constexpr DataType operator++(int)
     43   {
     44     DataType value = GetValue();
     45     SetValue(value + 1);
     46     return value;
     47   }
     48 
     49   ALWAYS_INLINE constexpr DataType operator--()
     50   {
     51     DataType value = GetValue() - 1;
     52     SetValue(value);
     53     return GetValue();
     54   }
     55 
     56   ALWAYS_INLINE constexpr DataType operator--(int)
     57   {
     58     DataType value = GetValue();
     59     SetValue(value - 1);
     60     return value;
     61   }
     62 
     63   ALWAYS_INLINE constexpr BitField& operator+=(DataType rhs)
     64   {
     65     SetValue(GetValue() + rhs);
     66     return *this;
     67   }
     68 
     69   ALWAYS_INLINE constexpr BitField& operator-=(DataType rhs)
     70   {
     71     SetValue(GetValue() - rhs);
     72     return *this;
     73   }
     74 
     75   ALWAYS_INLINE constexpr BitField& operator*=(DataType rhs)
     76   {
     77     SetValue(GetValue() * rhs);
     78     return *this;
     79   }
     80 
     81   ALWAYS_INLINE constexpr BitField& operator/=(DataType rhs)
     82   {
     83     SetValue(GetValue() / rhs);
     84     return *this;
     85   }
     86 
     87   ALWAYS_INLINE constexpr BitField& operator&=(DataType rhs)
     88   {
     89     SetValue(GetValue() & rhs);
     90     return *this;
     91   }
     92 
     93   ALWAYS_INLINE constexpr BitField& operator|=(DataType rhs)
     94   {
     95     SetValue(GetValue() | rhs);
     96     return *this;
     97   }
     98 
     99   ALWAYS_INLINE constexpr BitField& operator^=(DataType rhs)
    100   {
    101     SetValue(GetValue() ^ rhs);
    102     return *this;
    103   }
    104 
    105   ALWAYS_INLINE constexpr BitField& operator<<=(DataType rhs)
    106   {
    107     SetValue(GetValue() << rhs);
    108     return *this;
    109   }
    110 
    111   ALWAYS_INLINE constexpr BitField& operator>>=(DataType rhs)
    112   {
    113     SetValue(GetValue() >> rhs);
    114     return *this;
    115   }
    116 
    117   ALWAYS_INLINE constexpr DataType GetValue() const
    118   {
    119     if constexpr (std::is_same_v<DataType, bool>)
    120     {
    121       return static_cast<DataType>(!!((data & GetMask()) >> BitIndex));
    122     }
    123     else if constexpr (std::is_signed_v<DataType>)
    124     {
    125       constexpr int shift = 8 * sizeof(DataType) - BitCount;
    126       return (static_cast<DataType>(data >> BitIndex) << shift) >> shift;
    127     }
    128     else
    129     {
    130       return static_cast<DataType>((data & GetMask()) >> BitIndex);
    131     }
    132   }
    133 
    134   ALWAYS_INLINE constexpr void SetValue(DataType value)
    135   {
    136     data = (data & ~GetMask()) | ((static_cast<BackingDataType>(value) << BitIndex) & GetMask());
    137   }
    138 
    139   BackingDataType data;
    140 };
    141 
    142 #ifdef _MSC_VER
    143 #pragma warning(pop)
    144 #endif