BitmapView.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /*
  2. * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Array.h>
  8. #include <AK/BuiltinWrappers.h>
  9. #include <AK/Optional.h>
  10. #include <AK/StdLibExtras.h>
  11. #include <AK/Types.h>
  12. namespace AK {
  13. static constexpr Array bitmask_first_byte = { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80 };
  14. static constexpr Array bitmask_last_byte = { 0x00, 0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F };
  15. class BitmapView {
  16. public:
  17. BitmapView() = default;
  18. BitmapView(u8* data, size_t size)
  19. : m_data(data)
  20. , m_size(size)
  21. {
  22. }
  23. [[nodiscard]] size_t size() const { return m_size; }
  24. [[nodiscard]] size_t size_in_bytes() const { return ceil_div(m_size, static_cast<size_t>(8)); }
  25. [[nodiscard]] bool get(size_t index) const
  26. {
  27. VERIFY(index < m_size);
  28. return 0 != (m_data[index / 8] & (1u << (index % 8)));
  29. }
  30. [[nodiscard]] size_t count_slow(bool value) const
  31. {
  32. return count_in_range(0, m_size, value);
  33. }
  34. [[nodiscard]] size_t count_in_range(size_t start, size_t len, bool value) const
  35. {
  36. VERIFY(start < m_size);
  37. VERIFY(start + len <= m_size);
  38. if (len == 0)
  39. return 0;
  40. size_t count;
  41. const u8* first = &m_data[start / 8];
  42. const u8* last = &m_data[(start + len) / 8];
  43. u8 byte = *first;
  44. byte &= bitmask_first_byte[start % 8];
  45. if (first == last) {
  46. byte &= bitmask_last_byte[(start + len) % 8];
  47. count = popcount(byte);
  48. } else {
  49. count = popcount(byte);
  50. // Don't access *last if it's out of bounds
  51. if (last < &m_data[size_in_bytes()]) {
  52. byte = *last;
  53. byte &= bitmask_last_byte[(start + len) % 8];
  54. count += popcount(byte);
  55. }
  56. if (++first < last) {
  57. const size_t* ptr_large = (const size_t*)(((FlatPtr)first + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1));
  58. if ((const u8*)ptr_large > last)
  59. ptr_large = (const size_t*)last;
  60. while (first < (const u8*)ptr_large) {
  61. count += popcount(*first);
  62. first++;
  63. }
  64. const size_t* last_large = (const size_t*)((FlatPtr)last & ~(sizeof(size_t) - 1));
  65. while (ptr_large < last_large) {
  66. count += popcount(*ptr_large);
  67. ptr_large++;
  68. }
  69. for (first = (const u8*)ptr_large; first < last; first++)
  70. count += popcount(*first);
  71. }
  72. }
  73. if (!value)
  74. count = len - count;
  75. return count;
  76. }
  77. [[nodiscard]] bool is_null() const { return m_data == nullptr; }
  78. [[nodiscard]] const u8* data() const { return m_data; }
  79. template<bool VALUE>
  80. Optional<size_t> find_one_anywhere(size_t hint = 0) const
  81. {
  82. VERIFY(hint < m_size);
  83. const u8* end = &m_data[m_size / 8];
  84. for (;;) {
  85. // We will use hint as what it is: a hint. Because we try to
  86. // scan over entire 32 bit words, we may start searching before
  87. // the hint!
  88. const size_t* ptr_large = (const size_t*)((FlatPtr)&m_data[hint / 8] & ~(sizeof(size_t) - 1));
  89. if ((const u8*)ptr_large < &m_data[0]) {
  90. ptr_large++;
  91. // m_data isn't aligned, check first bytes
  92. size_t start_ptr_large = (const u8*)ptr_large - &m_data[0];
  93. size_t i = 0;
  94. u8 byte = VALUE ? 0x00 : 0xff;
  95. while (i < start_ptr_large && m_data[i] == byte)
  96. i++;
  97. if (i < start_ptr_large) {
  98. byte = m_data[i];
  99. if constexpr (!VALUE)
  100. byte = ~byte;
  101. VERIFY(byte != 0);
  102. return i * 8 + bit_scan_forward(byte) - 1;
  103. }
  104. }
  105. size_t val_large = VALUE ? 0x0 : NumericLimits<size_t>::max();
  106. const size_t* end_large = (const size_t*)((FlatPtr)end & ~(sizeof(size_t) - 1));
  107. while (ptr_large < end_large && *ptr_large == val_large)
  108. ptr_large++;
  109. if (ptr_large == end_large) {
  110. // We didn't find anything, check the remaining few bytes (if any)
  111. u8 byte = VALUE ? 0x00 : 0xff;
  112. size_t i = (const u8*)ptr_large - &m_data[0];
  113. size_t byte_count = m_size / 8;
  114. VERIFY(i <= byte_count);
  115. while (i < byte_count && m_data[i] == byte)
  116. i++;
  117. if (i == byte_count) {
  118. if (hint <= 8)
  119. return {}; // We already checked from the beginning
  120. // Try scanning before the hint
  121. end = (const u8*)((FlatPtr)&m_data[hint / 8] & ~(sizeof(size_t) - 1));
  122. hint = 0;
  123. continue;
  124. }
  125. byte = m_data[i];
  126. if constexpr (!VALUE)
  127. byte = ~byte;
  128. VERIFY(byte != 0);
  129. return i * 8 + bit_scan_forward(byte) - 1;
  130. }
  131. // NOTE: We don't really care about byte ordering. We found *one*
  132. // free bit, just calculate the position and return it
  133. val_large = *ptr_large;
  134. if constexpr (!VALUE)
  135. val_large = ~val_large;
  136. VERIFY(val_large != 0);
  137. return ((const u8*)ptr_large - &m_data[0]) * 8 + bit_scan_forward(val_large) - 1;
  138. }
  139. }
  140. Optional<size_t> find_one_anywhere_set(size_t hint = 0) const
  141. {
  142. return find_one_anywhere<true>(hint);
  143. }
  144. Optional<size_t> find_one_anywhere_unset(size_t hint = 0) const
  145. {
  146. return find_one_anywhere<false>(hint);
  147. }
  148. template<bool VALUE>
  149. Optional<size_t> find_first() const
  150. {
  151. size_t byte_count = m_size / 8;
  152. size_t i = 0;
  153. u8 byte = VALUE ? 0x00 : 0xff;
  154. while (i < byte_count && m_data[i] == byte)
  155. i++;
  156. if (i == byte_count)
  157. return {};
  158. byte = m_data[i];
  159. if constexpr (!VALUE)
  160. byte = ~byte;
  161. VERIFY(byte != 0);
  162. return i * 8 + bit_scan_forward(byte) - 1;
  163. }
  164. Optional<size_t> find_first_set() const { return find_first<true>(); }
  165. Optional<size_t> find_first_unset() const { return find_first<false>(); }
  166. // The function will return the next range of unset bits starting from the
  167. // @from value.
  168. // @from: the position from which the search starts. The var will be
  169. // changed and new value is the offset of the found block.
  170. // @min_length: minimum size of the range which will be returned.
  171. // @max_length: maximum size of the range which will be returned.
  172. // This is used to increase performance, since the range of
  173. // unset bits can be long, and we don't need the while range,
  174. // so we can stop when we've reached @max_length.
  175. inline Optional<size_t> find_next_range_of_unset_bits(size_t& from, size_t min_length = 1, size_t max_length = max_size) const
  176. {
  177. if (min_length > max_length) {
  178. return {};
  179. }
  180. size_t bit_size = 8 * sizeof(size_t);
  181. size_t* bitmap = (size_t*)m_data;
  182. // Calculating the start offset.
  183. size_t start_bucket_index = from / bit_size;
  184. size_t start_bucket_bit = from % bit_size;
  185. size_t* start_of_free_chunks = &from;
  186. size_t free_chunks = 0;
  187. for (size_t bucket_index = start_bucket_index; bucket_index < m_size / bit_size; ++bucket_index) {
  188. if (bitmap[bucket_index] == NumericLimits<size_t>::max()) {
  189. // Skip over completely full bucket of size bit_size.
  190. if (free_chunks >= min_length) {
  191. return min(free_chunks, max_length);
  192. }
  193. free_chunks = 0;
  194. start_bucket_bit = 0;
  195. continue;
  196. }
  197. if (bitmap[bucket_index] == 0x0) {
  198. // Skip over completely empty bucket of size bit_size.
  199. if (free_chunks == 0) {
  200. *start_of_free_chunks = bucket_index * bit_size;
  201. }
  202. free_chunks += bit_size;
  203. if (free_chunks >= max_length) {
  204. return max_length;
  205. }
  206. start_bucket_bit = 0;
  207. continue;
  208. }
  209. size_t bucket = bitmap[bucket_index];
  210. u8 viewed_bits = start_bucket_bit;
  211. u32 trailing_zeroes = 0;
  212. bucket >>= viewed_bits;
  213. start_bucket_bit = 0;
  214. while (viewed_bits < bit_size) {
  215. if (bucket == 0) {
  216. if (free_chunks == 0) {
  217. *start_of_free_chunks = bucket_index * bit_size + viewed_bits;
  218. }
  219. free_chunks += bit_size - viewed_bits;
  220. viewed_bits = bit_size;
  221. } else {
  222. trailing_zeroes = count_trailing_zeroes(bucket);
  223. bucket >>= trailing_zeroes;
  224. if (free_chunks == 0) {
  225. *start_of_free_chunks = bucket_index * bit_size + viewed_bits;
  226. }
  227. free_chunks += trailing_zeroes;
  228. viewed_bits += trailing_zeroes;
  229. if (free_chunks >= min_length) {
  230. return min(free_chunks, max_length);
  231. }
  232. // Deleting trailing ones.
  233. u32 trailing_ones = count_trailing_zeroes(~bucket);
  234. bucket >>= trailing_ones;
  235. viewed_bits += trailing_ones;
  236. free_chunks = 0;
  237. }
  238. }
  239. }
  240. if (free_chunks < min_length) {
  241. size_t first_trailing_bit = (m_size / bit_size) * bit_size;
  242. size_t trailing_bits = size() % bit_size;
  243. for (size_t i = 0; i < trailing_bits; ++i) {
  244. if (!get(first_trailing_bit + i)) {
  245. if (free_chunks == 0)
  246. *start_of_free_chunks = first_trailing_bit + i;
  247. if (++free_chunks >= min_length)
  248. return min(free_chunks, max_length);
  249. } else {
  250. free_chunks = 0;
  251. }
  252. }
  253. return {};
  254. }
  255. return min(free_chunks, max_length);
  256. }
  257. Optional<size_t> find_longest_range_of_unset_bits(size_t max_length, size_t& found_range_size) const
  258. {
  259. size_t start = 0;
  260. size_t max_region_start = 0;
  261. size_t max_region_size = 0;
  262. while (true) {
  263. // Look for the next block which is bigger than currunt.
  264. auto length_of_found_range = find_next_range_of_unset_bits(start, max_region_size + 1, max_length);
  265. if (length_of_found_range.has_value()) {
  266. max_region_start = start;
  267. max_region_size = length_of_found_range.value();
  268. start += max_region_size;
  269. } else {
  270. // No ranges which are bigger than current were found.
  271. break;
  272. }
  273. }
  274. found_range_size = max_region_size;
  275. if (max_region_size != 0) {
  276. return max_region_start;
  277. }
  278. return {};
  279. }
  280. Optional<size_t> find_first_fit(size_t minimum_length) const
  281. {
  282. size_t start = 0;
  283. auto length_of_found_range = find_next_range_of_unset_bits(start, minimum_length, minimum_length);
  284. if (length_of_found_range.has_value()) {
  285. return start;
  286. }
  287. return {};
  288. }
  289. Optional<size_t> find_best_fit(size_t minimum_length) const
  290. {
  291. size_t start = 0;
  292. size_t best_region_start = 0;
  293. size_t best_region_size = max_size;
  294. bool found = false;
  295. while (true) {
  296. // Look for the next block which is bigger than requested length.
  297. auto length_of_found_range = find_next_range_of_unset_bits(start, minimum_length, best_region_size);
  298. if (length_of_found_range.has_value()) {
  299. if (best_region_size > length_of_found_range.value() || !found) {
  300. best_region_start = start;
  301. best_region_size = length_of_found_range.value();
  302. found = true;
  303. }
  304. start += length_of_found_range.value();
  305. } else {
  306. // There are no ranges which can fit requested length.
  307. break;
  308. }
  309. }
  310. if (found) {
  311. return best_region_start;
  312. }
  313. return {};
  314. }
  315. static constexpr size_t max_size = 0xffffffff;
  316. protected:
  317. u8* m_data { nullptr };
  318. size_t m_size { 0 };
  319. };
  320. }
  321. using AK::BitmapView;