2023-08-23 11:50:45 +00:00
|
|
|
/**
|
|
|
|
* @file Bitmap.h
|
|
|
|
* @author apio (cloudapio.eu)
|
|
|
|
* @brief An interface to an array of bits.
|
|
|
|
*
|
|
|
|
* @copyright Copyright (c) 2022-2023, the Luna authors.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2022-12-04 14:14:07 +00:00
|
|
|
#pragma once
|
2023-01-09 17:08:50 +00:00
|
|
|
#include <luna/Result.h>
|
2022-12-04 14:14:07 +00:00
|
|
|
#include <luna/Types.h>
|
|
|
|
|
2023-08-23 11:50:45 +00:00
|
|
|
/**
|
|
|
|
* @brief A class providing an interface to an array of bits.
|
|
|
|
*/
|
2022-12-04 14:14:07 +00:00
|
|
|
class Bitmap
|
|
|
|
{
|
|
|
|
public:
|
2023-08-23 11:50:45 +00:00
|
|
|
/**
|
|
|
|
* @brief Construct a new empty Bitmap object.
|
|
|
|
*
|
|
|
|
* This object is invalid until initialize() is called on it.
|
|
|
|
*/
|
2022-12-04 14:14:07 +00:00
|
|
|
Bitmap();
|
2023-08-23 11:50:45 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Construct a new Bitmap object.
|
|
|
|
*
|
|
|
|
* @param location The memory to use. This memory is not managed by Bitmap; if it is dynamically allocated, you must
|
|
|
|
* free it after it is no longer used by the bitmap.
|
|
|
|
* @param size_in_bytes The size (in bytes, the number of bits available will be 8 times more) of the memory used.
|
|
|
|
*/
|
2022-12-04 14:14:07 +00:00
|
|
|
Bitmap(void* location, usize size_in_bytes);
|
|
|
|
|
2023-08-23 11:50:45 +00:00
|
|
|
/**
|
|
|
|
* @brief Initialize a Bitmap object.
|
|
|
|
*
|
|
|
|
* If the object was previously initialized, you should call move() instead.
|
|
|
|
*
|
|
|
|
* @param location The memory to use. This memory is not managed by Bitmap; if it is dynamically allocated, you must
|
|
|
|
* free it after it is no longer used by the bitmap.
|
|
|
|
* @param size_in_bytes The size (in bytes, the number of bits available will be 8 times more) of the memory used.
|
|
|
|
*/
|
2022-12-04 14:14:07 +00:00
|
|
|
void initialize(void* location, usize size_in_bytes);
|
|
|
|
|
2023-08-23 11:50:45 +00:00
|
|
|
/**
|
|
|
|
* @brief Initialize a previously initialized Bitmap object and return the memory location it was previously using.
|
|
|
|
*
|
|
|
|
* If the object was not previously initialized, you should call initialize() instead.
|
|
|
|
*
|
|
|
|
* @param new_location The memory to use. This memory is not managed by Bitmap; if it is dynamically allocated, you
|
|
|
|
* must free it after it is no longer used by the bitmap.
|
|
|
|
* @param new_location_size_in_bytes The size (in bytes, the number of bits available will be 8 times more) of the
|
|
|
|
* memory used.
|
|
|
|
* @return void* The old memory location previously used by the bitmap.
|
|
|
|
*/
|
|
|
|
void* move(void* new_location, usize new_location_size_in_bytes);
|
2023-01-21 22:16:50 +00:00
|
|
|
|
2023-08-23 11:50:45 +00:00
|
|
|
/**
|
|
|
|
* @brief Change the value of the bit at a specific index.
|
|
|
|
*
|
|
|
|
* @param index The index of the bit to change.
|
|
|
|
* @param value The value to set.
|
|
|
|
*/
|
2022-12-04 14:14:07 +00:00
|
|
|
void set(usize index, bool value);
|
2023-08-23 11:50:45 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Read the value of the bit at a specific index.
|
|
|
|
*
|
|
|
|
* @param index The index of the bit to read.
|
|
|
|
* @return bool The value of the specified bit.
|
|
|
|
*/
|
2022-12-05 11:50:30 +00:00
|
|
|
bool get(usize index) const;
|
2022-12-04 14:14:07 +00:00
|
|
|
|
2023-08-23 11:50:45 +00:00
|
|
|
/**
|
|
|
|
* @brief Return the size in bits of the bitmap.
|
|
|
|
*
|
|
|
|
* @return usize The size in bits.
|
|
|
|
*/
|
2022-12-05 11:50:30 +00:00
|
|
|
usize size() const
|
2022-12-04 14:14:07 +00:00
|
|
|
{
|
|
|
|
return m_size_in_bytes * 8;
|
|
|
|
}
|
|
|
|
|
2023-08-23 11:50:45 +00:00
|
|
|
/**
|
|
|
|
* @brief Return the size in bytes of the bitmap.
|
|
|
|
*
|
|
|
|
* @return usize The size in bytes.
|
|
|
|
*/
|
2022-12-05 11:50:30 +00:00
|
|
|
usize size_in_bytes() const
|
2022-12-04 14:14:07 +00:00
|
|
|
{
|
|
|
|
return m_size_in_bytes;
|
|
|
|
}
|
|
|
|
|
2023-08-23 11:50:45 +00:00
|
|
|
/**
|
|
|
|
* @brief Return the memory location used by the bitmap.
|
|
|
|
*
|
|
|
|
* @return void* The memory location used. If it is NULL, the bitmap was not initialized.
|
|
|
|
*/
|
2022-12-05 11:50:30 +00:00
|
|
|
void* location() const
|
2022-12-04 14:14:07 +00:00
|
|
|
{
|
|
|
|
return (void*)m_location;
|
|
|
|
}
|
|
|
|
|
2023-08-23 11:50:45 +00:00
|
|
|
/**
|
|
|
|
* @brief Check whether the bitmap has been initialized.
|
|
|
|
*
|
|
|
|
* @return true The bitmap was initialized by a constructor or initialize().
|
|
|
|
* @return false The bitmap was not initialized and you should not call other methods on it until initialize() is
|
|
|
|
* called.
|
|
|
|
*/
|
2022-12-05 11:50:30 +00:00
|
|
|
bool initialized() const
|
2022-12-04 14:14:07 +00:00
|
|
|
{
|
|
|
|
return m_location;
|
|
|
|
}
|
|
|
|
|
2023-08-23 11:50:45 +00:00
|
|
|
/**
|
|
|
|
* @brief Find the first bit with a specific value.
|
|
|
|
*
|
|
|
|
* @param value The value to look for.
|
|
|
|
* @param begin If different from 0, the bit index to start looking at.
|
|
|
|
* @return Option<usize> If a matching bit was found, the index of said bit, otherwise an empty Option.
|
|
|
|
*/
|
2023-01-09 16:59:52 +00:00
|
|
|
Option<usize> find(bool value, usize begin = 0) const;
|
|
|
|
|
2023-08-23 11:50:45 +00:00
|
|
|
/**
|
|
|
|
* @brief Find the first bit with a specific value and toggle it.
|
|
|
|
*
|
|
|
|
* @param value The value to look for.
|
|
|
|
* @param begin If different from 0, the bit index to start looking at.
|
|
|
|
* @return Option<usize> If a matching bit was found, the index of said bit, otherwise an empty Option.
|
|
|
|
*/
|
2023-01-09 17:08:50 +00:00
|
|
|
Option<usize> find_and_toggle(bool value, usize begin = 0);
|
|
|
|
|
2023-08-23 11:50:45 +00:00
|
|
|
/**
|
|
|
|
* @brief Find the first region of bits all with a specific value.
|
|
|
|
*
|
|
|
|
* @param value The value to look for.
|
|
|
|
* @param count The number of consecutive bits that should all match the value.
|
|
|
|
* @param begin If different from 0, the bit index to start looking at.
|
|
|
|
* @return Option<usize> If a matching region was found, the index of the first bit in said region, otherwise an
|
|
|
|
* empty Option.
|
|
|
|
*/
|
2023-01-13 17:55:31 +00:00
|
|
|
Option<usize> find_region(bool value, usize count, usize begin = 0) const;
|
|
|
|
|
2023-08-23 11:50:45 +00:00
|
|
|
/**
|
|
|
|
* @brief Find the first region of bits all with a specific value, and toggle them all.
|
|
|
|
*
|
|
|
|
* @param value The value to look for.
|
|
|
|
* @param count The number of consecutive bits that should all match the value.
|
|
|
|
* @param begin If different from 0, the bit index to start looking at.
|
|
|
|
* @return Option<usize> If a matching region was found, the index of the first bit in said region, otherwise an
|
|
|
|
* empty Option.
|
|
|
|
*/
|
2023-01-13 17:55:31 +00:00
|
|
|
Option<usize> find_and_toggle_region(bool value, usize count, usize begin = 0);
|
|
|
|
|
2023-08-23 11:50:45 +00:00
|
|
|
/**
|
|
|
|
* @brief Check whether a region of bits all match a value.
|
|
|
|
*
|
|
|
|
* @param start The bit index of the first bit in the region.
|
|
|
|
* @param bits The number of bits in the region.
|
|
|
|
* @param value The value to check against.
|
|
|
|
* @return bool Whether the region matches.
|
|
|
|
*/
|
2023-01-16 20:16:38 +00:00
|
|
|
bool match_region(usize start, usize bits, bool value);
|
2023-08-23 11:50:45 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Check whether a region of bits all match a value, returning an error if the region is outside of the
|
|
|
|
* Bitmap's bounds (instead of crashing).
|
|
|
|
*
|
|
|
|
* @param start The bit index of the first bit in the region.
|
|
|
|
* @param bits The number of bits in the region.
|
|
|
|
* @param value The value to check against.
|
|
|
|
* @return Result<bool> An error if the region is out of bounds, or whether the region matches.
|
|
|
|
*/
|
2023-01-22 13:25:51 +00:00
|
|
|
Result<bool> try_match_region(usize start, usize bits, bool value);
|
2023-01-16 20:16:38 +00:00
|
|
|
|
2023-08-23 11:50:45 +00:00
|
|
|
/**
|
|
|
|
* @brief Set the entire bitmap to a value.
|
|
|
|
*
|
|
|
|
* @param value The value to use.
|
|
|
|
*/
|
2022-12-04 14:14:07 +00:00
|
|
|
void clear(bool value);
|
2023-08-23 11:50:45 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Set a region of bits to a value.
|
|
|
|
*
|
|
|
|
* @param start The bit index of the first bit in the region.
|
|
|
|
* @param bits The number of bits in the region.
|
|
|
|
* @param value The value to set.
|
|
|
|
*/
|
2022-12-04 14:14:07 +00:00
|
|
|
void clear_region(usize start, usize bits, bool value);
|
|
|
|
|
|
|
|
private:
|
2023-01-09 16:59:52 +00:00
|
|
|
u8 value_byte(bool b) const
|
2022-12-05 11:53:16 +00:00
|
|
|
{
|
|
|
|
return b ? 0xff : 0;
|
|
|
|
}
|
|
|
|
|
2023-01-22 13:25:51 +00:00
|
|
|
bool match_region_impl(usize start, usize bits, bool value);
|
|
|
|
|
2022-12-07 10:47:46 +00:00
|
|
|
u8* m_location = nullptr;
|
2022-12-04 14:14:07 +00:00
|
|
|
usize m_size_in_bytes = 0;
|
2023-01-02 12:07:29 +00:00
|
|
|
};
|