/* * Copyright (c) 2018-2021, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include namespace AK { class Bitmap { AK_MAKE_NONCOPYABLE(Bitmap); public: Bitmap() = default; Bitmap(size_t size, bool default_value) : m_size(size) { VERIFY(m_size != 0); m_data = static_cast(kmalloc(size_in_bytes())); fill(default_value); } Bitmap(u8* data, size_t size) : m_data(data) , m_size(size) { } BitmapView view() { return { m_data, m_size }; } const BitmapView view() const { return { m_data, m_size }; } Bitmap(Bitmap&& other) : m_data(exchange(other.m_data, nullptr)) , m_size(exchange(other.m_size, 0)) { } Bitmap& operator=(Bitmap&& other) { if (this != &other) { kfree(m_data); m_data = exchange(other.m_data, nullptr); m_size = exchange(other.m_size, 0); } return *this; } ~Bitmap() { kfree(m_data); m_data = nullptr; } size_t size() const { return m_size; } size_t size_in_bytes() const { return ceil_div(m_size, static_cast(8)); } bool get(size_t index) const { VERIFY(index < m_size); return 0 != (m_data[index / 8] & (1u << (index % 8))); } void set(size_t index, bool value) const { VERIFY(index < m_size); if (value) m_data[index / 8] |= static_cast((1u << (index % 8))); else m_data[index / 8] &= static_cast(~(1u << (index % 8))); } size_t count_slow(bool value) const { return count_in_range(0, m_size, value); } size_t count_in_range(size_t start, size_t len, bool value) const { return view().count_in_range(start, len, value); } bool is_null() const { return !m_data; } u8* data() { return m_data; } const u8* data() const { return m_data; } void grow(size_t size, bool default_value) { VERIFY(size > m_size); auto previous_size_bytes = size_in_bytes(); auto previous_size = m_size; auto previous_data = m_data; m_size = size; m_data = reinterpret_cast(kmalloc(size_in_bytes())); fill(default_value); if (previous_data != nullptr) { __builtin_memcpy(m_data, previous_data, previous_size_bytes); if (previous_size % 8) set_range(previous_size, 8 - previous_size % 8, default_value); kfree(previous_data); } } template void set_range(size_t start, size_t len) { return view().set_range(start, len); } void set_range(size_t start, size_t len, bool value) { return view().set_range(start, len, value); } void fill(bool value) { view().fill(value); } Optional find_one_anywhere_set(size_t hint = 0) const { return view().find_one_anywhere(hint); } Optional find_one_anywhere_unset(size_t hint = 0) const { return view().find_one_anywhere(hint); } Optional find_first_set() const { return view().find_first(); } Optional find_first_unset() const { return view().find_first(); } Optional find_next_range_of_unset_bits(size_t& from, size_t min_length = 1, size_t max_length = max_size) const { return view().find_next_range_of_unset_bits(from, min_length, max_length); } Optional find_longest_range_of_unset_bits(size_t max_length, size_t& found_range_size) const { return view().find_longest_range_of_unset_bits(max_length, found_range_size); } Optional find_first_fit(size_t minimum_length) const { return view().find_first_fit(minimum_length); } Optional find_best_fit(size_t minimum_length) const { return view().find_best_fit(minimum_length); } static constexpr size_t max_size = 0xffffffff; private: u8* m_data { nullptr }; size_t m_size { 0 }; }; } using AK::Bitmap;