bit-field.hpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #pragma once
  2. namespace nall {
  3. template<int...> struct BitField;
  4. /* static BitField */
  5. template<int Precision, int Index> struct BitField<Precision, Index> {
  6. static_assert(Precision >= 1 && Precision <= 64);
  7. enum : uint { bits = Precision };
  8. using type =
  9. conditional_t<bits <= 8, uint8_t,
  10. conditional_t<bits <= 16, uint16_t,
  11. conditional_t<bits <= 32, uint32_t,
  12. conditional_t<bits <= 64, uint64_t,
  13. void>>>>;
  14. enum : uint { shift = Index < 0 ? Precision + Index : Index };
  15. enum : type { mask = 1ull << shift };
  16. BitField(const BitField&) = delete;
  17. inline auto& operator=(const BitField& source) {
  18. target = target & ~mask | (bool)source << shift;
  19. return *this;
  20. }
  21. template<typename T> inline BitField(T* source) : target((type&)*source) {
  22. static_assert(sizeof(T) == sizeof(type));
  23. }
  24. inline auto bit() const {
  25. return shift;
  26. }
  27. inline operator bool() const {
  28. return target & mask;
  29. }
  30. inline auto& operator=(bool source) {
  31. target = target & ~mask | source << shift;
  32. return *this;
  33. }
  34. inline auto& operator&=(bool source) {
  35. target = target & (~mask | source << shift);
  36. return *this;
  37. }
  38. inline auto& operator^=(bool source) {
  39. target = target ^ source << shift;
  40. return *this;
  41. }
  42. inline auto& operator|=(bool source) {
  43. target = target | source << shift;
  44. return *this;
  45. }
  46. private:
  47. type& target;
  48. };
  49. /* dynamic BitField */
  50. template<int Precision> struct BitField<Precision> {
  51. static_assert(Precision >= 1 && Precision <= 64);
  52. enum : uint { bits = Precision };
  53. using type =
  54. conditional_t<bits <= 8, uint8_t,
  55. conditional_t<bits <= 16, uint16_t,
  56. conditional_t<bits <= 32, uint32_t,
  57. conditional_t<bits <= 64, uint64_t,
  58. void>>>>;
  59. BitField(const BitField&) = delete;
  60. inline auto& operator=(const BitField& source) {
  61. target = target & ~mask | (bool)source << shift;
  62. return *this;
  63. }
  64. template<typename T> inline BitField(T* source, int index) : target((type&)*source) {
  65. static_assert(sizeof(T) == sizeof(type));
  66. if(index < 0) index = Precision + index;
  67. mask = 1ull << index;
  68. shift = index;
  69. }
  70. inline auto bit() const {
  71. return shift;
  72. }
  73. inline operator bool() const {
  74. return target & mask;
  75. }
  76. inline auto& operator=(bool source) {
  77. target = target & ~mask | source << shift;
  78. return *this;
  79. }
  80. inline auto& operator&=(bool source) {
  81. target = target & (~mask | source << shift);
  82. return *this;
  83. }
  84. inline auto& operator^=(bool source) {
  85. target = target ^ source << shift;
  86. return *this;
  87. }
  88. inline auto& operator|=(bool source) {
  89. target = target | source << shift;
  90. return *this;
  91. }
  92. private:
  93. type& target;
  94. type mask;
  95. uint shift;
  96. };
  97. }