bitmap presque entièrement testé
This commit is contained in:
parent
347cdd9cf3
commit
9a23b1bb37
@ -4,18 +4,28 @@ pub const BITS_IN_WORD: usize = 32;
|
||||
use std::fs::File;
|
||||
use std::io::{Cursor, Write, Read};
|
||||
|
||||
use crate::drivers::drv_disk::{self, DrvDisk};
|
||||
use crate::filesys::openfile::OpenFile;
|
||||
use crate::simulator::disk::SECTOR_SIZE;
|
||||
|
||||
pub struct BitMap {
|
||||
num_bits: usize,
|
||||
num_words: usize,
|
||||
map: Vec<u32>,
|
||||
pub num_bits: usize,
|
||||
pub num_words: usize,
|
||||
pub map: Vec<u32>,
|
||||
}
|
||||
|
||||
impl BitMap {
|
||||
|
||||
pub fn compute_map_size(n_item : usize, dst_n_item : &mut usize, dst_num_word : &mut usize){
|
||||
//on effectue un calcul sur n_item pour avoir un nombre de bits multiple de 32
|
||||
//On fait le choix d'arrondir vers le haut pour que la map puisse acceuillir la taille souhaitée
|
||||
*dst_n_item = n_item - (n_item%32);
|
||||
|
||||
if n_item%32 > 0 {
|
||||
*dst_n_item += 32;
|
||||
}
|
||||
|
||||
*dst_num_word = *dst_n_item/32;
|
||||
}
|
||||
|
||||
/// Initialize a bitmap with "nitems" bits, so that every bit is clear.
|
||||
/// it can be added somewhere on a list.
|
||||
///
|
||||
@ -23,19 +33,45 @@ impl BitMap {
|
||||
/// - **nitems** is the number of bits in the bitmap.
|
||||
///----------------------------------------------------------------------
|
||||
pub fn init_bitmap(n_items: usize) -> BitMap {
|
||||
|
||||
let mut rounded_num_bits = 0;
|
||||
let mut rounded_num_words = 0;
|
||||
|
||||
BitMap::compute_map_size(n_items, &mut rounded_num_bits, &mut rounded_num_words);
|
||||
|
||||
BitMap{
|
||||
num_bits: n_items,
|
||||
num_words: (n_items + SECTOR_SIZE as usize -1) / SECTOR_SIZE as usize,
|
||||
map: vec![0,n_items as u32],
|
||||
num_bits: rounded_num_bits,
|
||||
num_words: rounded_num_words,//(n_items + SECTOR_SIZE as usize -1) / SECTOR_SIZE as usize,
|
||||
map: vec![0u32 ; rounded_num_words],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//values is not borrowed
|
||||
pub fn init_bitmap_from(values: &mut Vec<u32>)-> BitMap {
|
||||
let mut tmp: Vec<u32> = Vec::new();
|
||||
|
||||
for value in values.iter(){
|
||||
tmp.push(*value)
|
||||
}
|
||||
|
||||
BitMap{
|
||||
num_bits: values.len()*std::mem::size_of::<u32>()*8,
|
||||
num_words: values.len(),
|
||||
map: tmp
|
||||
}
|
||||
}
|
||||
|
||||
/// 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);
|
||||
//self.map[which / BITS_IN_WORD] |= 1 << (which % BITS_IN_WORD);
|
||||
let position_modulo = which%BITS_IN_WORD;
|
||||
let left_shift = BITS_IN_WORD-position_modulo-1;
|
||||
|
||||
self.map[which / BITS_IN_WORD] |= (1u32 << left_shift);
|
||||
}
|
||||
|
||||
/// return true if the "nth" bit is set.
|
||||
@ -44,7 +80,11 @@ impl BitMap {
|
||||
/// - **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
|
||||
//(self.map[which / BITS_IN_WORD] & (1 << (which % BITS_IN_WORD))) != 0
|
||||
let position_modulo = which%BITS_IN_WORD;
|
||||
let left_shift = BITS_IN_WORD-position_modulo-1;
|
||||
|
||||
(self.map[which / BITS_IN_WORD] & (1u32 << left_shift)) != 0
|
||||
}
|
||||
|
||||
/// Return the number of the first bit which is clear.
|
||||
@ -97,15 +137,18 @@ impl BitMap {
|
||||
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: &mut OpenFile, drv_disk: &mut DrvDisk) -> std::io::Result<&Vec<u32>> {
|
||||
let mut num_bytes = self.num_words * std::mem::size_of::<u32>();
|
||||
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>()];
|
||||
OpenFile::read(drv_disk, file, &mut buffer, num_bytes as i32);
|
||||
file.read_exact(&mut buffer)?;
|
||||
|
||||
// Convertit les octets en vecteur de u32
|
||||
self.map = vec![0; self.num_words];
|
||||
@ -119,22 +162,218 @@ impl BitMap {
|
||||
|
||||
Ok(&self.map)
|
||||
}
|
||||
*/
|
||||
|
||||
///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){
|
||||
// Ouvre le fichier en mode lecture seule
|
||||
let mut file = File::open(file_path).expect("BitMap::fetch_from , unable to open file in read only");
|
||||
|
||||
let mut buf_to_convert : Vec<u8> = Vec::new();
|
||||
|
||||
file.read_to_end(&mut buf_to_convert).expect("BitMap::fetch_from , unable to read from file");
|
||||
|
||||
let borne_max_exclue;
|
||||
|
||||
//si le fichier contient plus de mots que la map ne peut en acceuillir, on lit de quoi remplir la map
|
||||
if buf_to_convert.len() > self.num_bits/8 {
|
||||
borne_max_exclue = self.num_words*4;
|
||||
}
|
||||
//sinon on lit ce que le fichier contient, en respectant l'alignement sur 4 octects !
|
||||
else {
|
||||
borne_max_exclue = buf_to_convert.len() - (buf_to_convert.len()%4);
|
||||
}
|
||||
|
||||
let mut i = 0;
|
||||
|
||||
// !! borne_max_exclue doit etre multiple de 4 !!
|
||||
while i < borne_max_exclue {
|
||||
|
||||
let a : u32 = buf_to_convert[i] as u32;
|
||||
let b : u32 = buf_to_convert[i+1] as u32;
|
||||
let c : u32 = buf_to_convert[i+2] as u32;
|
||||
let d : u32 = buf_to_convert[i+3] as u32;
|
||||
|
||||
self.map[i/4] = (a<<24) | (b<<16) | (c<<8) | (d);
|
||||
|
||||
i += 4;//on passe aux 4 octets suivants
|
||||
}
|
||||
}
|
||||
|
||||
/// 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: &mut OpenFile, drv_disk: &mut DrvDisk) -> std::io::Result<()> {
|
||||
let mut num_bytes = self.num_words * std::mem::size_of::<u32>();
|
||||
|
||||
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())?;
|
||||
}
|
||||
|
||||
OpenFile::read_at(drv_disk, file, &mut cursor.into_inner(), num_bytes as i32, 0);
|
||||
// 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(())
|
||||
}
|
||||
|
||||
|
||||
pub fn add_word(&mut self, word : u32){
|
||||
self.map.push(word);
|
||||
self.num_words += 1;
|
||||
self.num_bits += std::mem::size_of::<u32>()*8;
|
||||
}
|
||||
|
||||
pub fn add_words(&mut self, words : Vec<u32>){
|
||||
for word in words.iter(){
|
||||
self.add_word(*word);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::io::{Seek, SeekFrom};
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_fetch_from_file_smaller_than_map() {
|
||||
//println!("\n\n TEST FETCH FROM\n");
|
||||
//On ecrit la séquence 0x AB CD EF 10 20 2E 3E 4F
|
||||
let values : [u8 ; 8] = [0xAB, 0xCD, 0xEF, 0x10, 0x20, 0x2E, 0x3E, 0x4F];
|
||||
let values_for_test : [u32 ; 2] = [0xABCDEF10, 0x202E3E4F];
|
||||
|
||||
let mut f = File::options()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open("test_fetch_bitmap")
|
||||
.expect("Unable to create File");
|
||||
|
||||
f.write_all(&values[..]).expect("Unable to write data");
|
||||
|
||||
//creating and loading the bitmap
|
||||
|
||||
let mut bit_map : BitMap = BitMap::init_bitmap(100);
|
||||
|
||||
bit_map.fetch_from("test_fetch_bitmap");
|
||||
|
||||
assert!(bit_map.num_bits == 128);
|
||||
assert!(bit_map.num_words == 4);
|
||||
|
||||
for j in 0..bit_map.map.len(){
|
||||
if j<2 {
|
||||
assert!(values_for_test[j] == bit_map.map[j]);
|
||||
}
|
||||
else {
|
||||
assert!(bit_map.map[j] == 0u32);
|
||||
}
|
||||
}
|
||||
//print for debug
|
||||
/*for val in bit_map.map.iter(){
|
||||
println!("{:08X?}", *val)
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_fetch_from_map_smaller_than_file() {
|
||||
//println!("\n\n TEST FETCH FROM\n");
|
||||
//On ecrit la séquence 0x AB CD EF 10 20 2E 3E 4F
|
||||
let mut values : [u8 ; 8] = [0xFE, 0x59, 0xEF, 0x10, 0x20, 0x2E, 0x3E, 0x4F];
|
||||
|
||||
let mut f = File::options()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open("test_fetch_bitmap_2")
|
||||
.expect("Unable to create File");
|
||||
|
||||
f.write_all(&values[..]).expect("Unable to write data");
|
||||
|
||||
//creating and loading the bitmap
|
||||
//1 bit donnera lieu via init_bit_map a une map de 32 bit soit 1 mot
|
||||
let mut bit_map : BitMap = BitMap::init_bitmap(1);
|
||||
|
||||
//println!("\nnombre de bit de la map {} \nnombre de mot {}\n", bit_map.num_bits, bit_map.num_words);
|
||||
|
||||
bit_map.fetch_from("test_fetch_bitmap");
|
||||
|
||||
assert!(bit_map.num_bits == 32);
|
||||
assert!(bit_map.num_words == 1);
|
||||
assert!(bit_map.map[0] == 0xFE59EF10);
|
||||
//println!("\n\n data loaded into map \n");
|
||||
|
||||
//print for debug
|
||||
/*for val in bit_map.map.iter(){
|
||||
println!("{:08X?}", *val)
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_mark() {
|
||||
|
||||
let mut bit_map : BitMap = BitMap::init_bitmap(128);
|
||||
let index_to_set : [usize ; 16] = [0,5,10,15,18,25,28,31,45,70,74,88,99,101,102,127];
|
||||
|
||||
for val in index_to_set.iter(){
|
||||
bit_map.mark(*val);
|
||||
}
|
||||
|
||||
assert!(bit_map.num_bits == 128);
|
||||
assert!(bit_map.num_words == 4);
|
||||
|
||||
/*for i in bit_map.map.iter(){
|
||||
println!("\n{:#032b}", *i);
|
||||
}*/
|
||||
|
||||
for i in 0..bit_map.num_bits {
|
||||
|
||||
let word_index = i/32;
|
||||
let mask_to_shift : u32 = 0x80000000;//un 1 au debut puis full 0 <=> 0x100000000000000000000000000000000
|
||||
let shift_value = i%32;
|
||||
|
||||
if index_to_set.contains(&i) {
|
||||
assert!( (bit_map.map[word_index] & (mask_to_shift>>shift_value)) != 0);
|
||||
}
|
||||
else{
|
||||
assert!( (bit_map.map[word_index] & (mask_to_shift>>shift_value)) == 0) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_test() {
|
||||
|
||||
let mut bit_map : BitMap = BitMap::init_bitmap(128);
|
||||
let index_to_set : [usize ; 16] = [0,5,10,15,18,25,28,31,45,70,74,88,99,101,102,127];
|
||||
|
||||
for val in index_to_set.iter(){
|
||||
bit_map.mark(*val);
|
||||
}
|
||||
|
||||
assert!(bit_map.num_bits == 128);
|
||||
assert!(bit_map.num_words == 4);
|
||||
|
||||
for i in 0..bit_map.num_bits {
|
||||
|
||||
if index_to_set.contains(&i) {
|
||||
assert!( bit_map.test(i) == true);
|
||||
}
|
||||
else{
|
||||
assert!( bit_map.test(i) == false) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user