BitSet.h 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <anki/util/StdTypes.h>
  7. #include <initializer_list>
  8. #include <cstring>
  9. namespace anki
  10. {
  11. /// @addtogroup util_containers
  12. /// @{
  13. /// Easy bit manipulation.
  14. /// @tparam N The number of bits.
  15. /// @tparam TChunkType The type of the chunks that the bitset consists. By
  16. /// default it's U8.
  17. template<U N, typename TChunkType = U8>
  18. class BitSet
  19. {
  20. public:
  21. /// Constructor. It will set all the bits or unset them.
  22. BitSet(Bool set)
  23. {
  24. memset(m_chunks, (set) ? 0xFF : 0, sizeof(m_chunks));
  25. }
  26. /// Set or unset a bit at the given position.
  27. template<typename TInt>
  28. void set(TInt pos, Bool setBits = true)
  29. {
  30. U high, low;
  31. position(static_cast<U>(pos), high, low);
  32. ChunkType mask = MASK >> low;
  33. m_chunks[high] =
  34. (setBits) ? (m_chunks[high] | mask) : (m_chunks[high] & ~mask);
  35. }
  36. /// Set multiple bits.
  37. template<typename TInt>
  38. void set(std::initializer_list<TInt> list, Bool setBits = true)
  39. {
  40. for(auto it : list)
  41. {
  42. set(it, setBits);
  43. }
  44. }
  45. /// Set all bits.
  46. void setAll()
  47. {
  48. memset(m_chunks, 0xFF, sizeof(m_chunks));
  49. }
  50. /// Unset a bit (set to zero) at the given position.
  51. template<typename TInt>
  52. void unset(TInt pos)
  53. {
  54. set(pos, false);
  55. }
  56. /// Unset multiple bits.
  57. template<typename TInt>
  58. void unset(std::initializer_list<TInt> list)
  59. {
  60. set(list, false);
  61. }
  62. /// Unset all bits.
  63. void unsetAll()
  64. {
  65. memset(m_chunks, 0, sizeof(m_chunks));
  66. }
  67. /// Flip the bits at the given position. It will go from 1 to 0 or from 0 to
  68. /// 1.
  69. template<typename TInt>
  70. void flip(TInt pos)
  71. {
  72. U high, low;
  73. position(static_cast<U>(pos), high, low);
  74. ChunkType mask = MASK >> low;
  75. m_chunks[high] ^= mask;
  76. }
  77. /// Return true if the bit is set or false if it's not.
  78. template<typename TInt>
  79. Bool get(TInt pos) const
  80. {
  81. U high, low;
  82. position(static_cast<U>(pos), high, low);
  83. ChunkType mask = MASK >> low;
  84. return (m_chunks[high] & mask) != 0;
  85. }
  86. /// Any are enabled.
  87. Bool getAny() const
  88. {
  89. for(U i = 0; i < CHUNK_COUNT; ++i)
  90. {
  91. if(m_chunks[i] != 0)
  92. {
  93. return true;
  94. }
  95. }
  96. return false;
  97. }
  98. protected:
  99. using ChunkType = TChunkType;
  100. /// Number of bits a chunk holds.
  101. static const U CHUNK_BIT_COUNT = sizeof(ChunkType) * 8;
  102. /// Number of chunks.
  103. static const U CHUNK_COUNT = (N + (CHUNK_BIT_COUNT - 1)) / CHUNK_BIT_COUNT;
  104. /// A mask for some stuff.
  105. static const U MASK = 1 << (CHUNK_BIT_COUNT - 1);
  106. ChunkType m_chunks[CHUNK_COUNT];
  107. static void position(U bit, U& high, U& low)
  108. {
  109. ANKI_ASSERT(bit < N);
  110. high = bit / CHUNK_BIT_COUNT;
  111. low = bit % CHUNK_BIT_COUNT;
  112. ANKI_ASSERT(high < CHUNK_COUNT);
  113. ANKI_ASSERT(low < CHUNK_BIT_COUNT);
  114. }
  115. };
  116. /// @}
  117. } // end namespace anki