1
0
forked from Rativel/BurritOS
Files
BurritOS/src/utility/bitmap.rs
2023-03-29 15:02:04 +02:00

145 lines
4.4 KiB
Rust

pub const BITS_IN_BYTE: usize = 8;
pub const BITS_IN_WORD: usize = 32;
use std::fs::File;
use std::io::{Cursor, Write, Read};
use crate::simulator::disk::SECTOR_SIZE;
pub struct BitMap {
num_bits: usize,
num_words: usize,
map: Vec<u32>,
}
impl BitMap {
/// Initialize a bitmap with "nitems" bits, so that every bit is clear.
/// it can be added somewhere on a list.
///
/// ### Parameters
/// - **nitems** is the number of bits in the bitmap.
///----------------------------------------------------------------------
pub fn init_bitmap(&self, n_items: usize) -> BitMap {
let mut tmp: Vec<u32>;
BitMap{
num_bits: n_items,
num_words: (n_items + SECTOR_SIZE as usize -1) / SECTOR_SIZE as usize,
map: tmp,
};
*self
}
/// Set the "nth" bit in a bitmap.
/// ### Parameters
/// - **which** is the number of the bit to be set.
pub fn mark(&mut self, which: usize) {
assert!(which >= 0 && which < self.num_bits);
self.map[which / BITS_IN_WORD] |= 1 << (which % BITS_IN_WORD);
}
/// return true if the "nth" bit is set.
///
/// ### Paramenters
/// - **which** is the number of the bit to be tested.
pub fn test(&self, which: usize) -> bool {
assert!(which < self.num_bits);
(self.map[which / BITS_IN_WORD] & (1 << (which % BITS_IN_WORD))) != 0
}
/// Return the number of the first bit which is clear.
/// As a side effect, set the bit (mark it as in use).
/// (In other words, find and allocate a bit.)
/// If no bits are clear, return ERROR
pub fn find(&mut self) -> i32 {
for i in 0..self.num_bits {
if !self.test(i) {
self.mark(i);
return i as i32;
}
}
-1
}
/// Clear the "nth" bit in a bitmap.
/// ### Parameters
/// - **which** is the number of the bit to be cleared.
pub fn clear(&mut self, which: usize) {
assert!(which < self.num_bits, "index out of range");
let word_idx = which / BITS_IN_WORD;
let bit_idx = which % BITS_IN_WORD;
self.map[word_idx] &= !(1 << bit_idx);
}
/// Return the number of clear bits in the bitmap.
/// (In other words, how many bits are unallocated?)
pub fn num_clear(&self) -> i32 {
let mut count = 0;
for i in 0..self.num_bits {
if !self.test(i) {
count += 1;
}
}
count
}
/// Print the contents of the bitmap, for debugging.
/// Could be done in a number of ways, but we just print the #'s of
/// all the bits that are set in the bitmap.
pub fn print(&self) {
println!("Bitmap set:");
for i in 0..self.num_bits {
if self.test(i) {
print!("{}, ", i);
}
}
println!();
}
///Initialize the contents of a bitmap from a Nachos file.
///
/// ### Parameters
/// - **file** is the place to read the bitmap from
pub fn fetch_from(&mut self, file_path: &str) -> std::io::Result<&Vec<u32>> {
// Ouvre le fichier en mode lecture seule
let mut file = File::open(file_path)?;
// Lit les octets du fichier dans un buffer
let mut buffer = vec![0; self.num_words * std::mem::size_of::<u32>()];
file.read_exact(&mut buffer)?;
// Convertit les octets en vecteur de u32
self.map = vec![0; self.num_words];
for i in 0..self.num_words {
let j = i * std::mem::size_of::<u32>();
let bytes = [
buffer[j], buffer[j+1], buffer[j+2], buffer[j+3]
];
self.map[i] = u32::from_le_bytes(bytes);
}
Ok(&self.map)
}
/// Store the contents of a bitmap to a Nachos file.
///
/// ### Paramenters
/// - **file** is the place to write the bitmap to
pub fn write_back(&mut self, file_path: &str) -> std::io::Result<()> {
// Encapsule le vecteur dans un std::io::Cursor pour l'utiliser comme un std::io::Write
let mut cursor = Cursor::new(Vec::<u8>::new());
for u32_val in self.map.as_mut_slice() {
cursor.write_all(&u32_val.to_le_bytes())?;
}
// Ouvre le fichier en mode écriture
let mut file = File::create(file_path)?;
// Écrit les données dans le fichier
file.write_all(&cursor.into_inner())?;
Ok(())
}
}