bit-field.hpp 2.6 KB

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