1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/openeuler-stratovirt

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Это зеркальный репозиторий, синхронизируется ежедневно с исходного репозитория.
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
bitmap.rs 17 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
liuxiangdong Отправлено 2 лет назад 74c9827
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
// Copyright (c) 2020 Huawei Technologies Co.,Ltd. All rights reserved.
//
// StratoVirt is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan
// PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
use std::cmp::Ord;
use std::mem::size_of;
use anyhow::{anyhow, Context, Result};
use crate::UtilError;
/// This struct is used to offer bitmap.
pub struct Bitmap<T: BitOps> {
/// The data to restore bit information.
data: Vec<T>,
}
impl<T: BitOps> Bitmap<T> {
/// Initialize a Bitmap structure with a size.
///
/// # Arguments
///
/// * `size` - The size of bitmap is the number of bit unit. If you want
/// to restore a `length` with bitmap. The `size` would be `length/bit_unit_size+1`.
pub fn new(size: usize) -> Self {
Bitmap::<T> {
data: [T::zero()].repeat(size),
}
}
/// Return the size of bitmap.
pub fn size(&self) -> usize {
self.data.len()
}
/// Return the Volume of bitmap.
pub fn vol(&self) -> usize {
self.size() * T::len()
}
/// Set the bit of bitmap.
///
/// # Arguments
///
/// * `num` - the input number.
pub fn set(&mut self, num: usize) -> Result<()> {
let index = self.bit_index(num);
if index >= self.size() {
return Err(anyhow!(UtilError::OutOfBound(
index as u64,
self.vol() as u64
)));
}
self.data[index] = T::bit_or(self.data[index], T::one().rhs(self.bit_pos(num)));
Ok(())
}
/// Set the range of bitmap.
///
/// # Arguments
///
/// * `start` - the begin bit.
/// * `len` - the end bit.
///
/// # Example
///
/// ```rust
/// use util::bitmap::Bitmap;
/// let mut bitmap = Bitmap::<u64>::new(4);
/// assert!(bitmap.set_range(65, 10).is_ok());
/// assert_eq!(bitmap.contain(64).unwrap(), false);
/// assert_eq!(bitmap.contain(65).unwrap(), true);
/// assert_eq!(bitmap.contain(70).unwrap(), true);
/// assert_eq!(bitmap.contain(74).unwrap(), true);
/// assert_eq!(bitmap.contain(75).unwrap(), false);
/// ```
pub fn set_range(&mut self, start: usize, len: usize) -> Result<()> {
if len == 0 {
return Ok(());
}
let mut index = self.bit_index(start);
let mut bits_to_set: usize = T::len() - self.bit_pos(start);
let mut mask_to_set: T = T::full().rhs(self.bit_pos(start));
let mut length: usize = len;
while length >= bits_to_set {
if index >= self.size() {
return Err(anyhow!(UtilError::OutOfBound(
index as u64,
self.vol() as u64
)));
}
length -= bits_to_set;
self.data[index] = T::bit_or(self.data[index], mask_to_set);
bits_to_set = T::len();
mask_to_set = T::full();
index += 1;
}
if length > 0 {
if index >= self.size() {
return Err(anyhow!(UtilError::OutOfBound(
index as u64,
self.vol() as u64
)));
}
bits_to_set = T::len() - self.bit_pos(start + len);
let mask_to_set_end: T = T::full().lhs(self.bit_pos(bits_to_set));
mask_to_set = T::bit_and(mask_to_set, mask_to_set_end);
self.data[index] = T::bit_or(self.data[index], mask_to_set);
}
Ok(())
}
/// Clear the bit of bitmap.
///
/// # Arguments
///
/// * `num` - the input number
pub fn clear(&mut self, num: usize) -> Result<()> {
let index = self.bit_index(num);
if index >= self.size() {
return Err(anyhow!(UtilError::OutOfBound(
index as u64,
self.vol() as u64
)));
}
self.data[index] = T::bit_and(
self.data[index],
T::bit_not(T::one().rhs(self.bit_pos(num))),
);
Ok(())
}
/// Clear the range of bitmap.
///
/// # Arguments
///
/// * `start` - the begin bit.
/// * `len` - the end bit.
///
/// # Example
///
/// ```rust
/// use util::bitmap::Bitmap;
/// let mut bitmap = Bitmap::<u64>::new(4);
/// assert!(bitmap.set_range(0, 256).is_ok());
/// assert!(bitmap.clear_range(65, 10).is_ok());
///
/// assert_eq!(bitmap.contain(64).unwrap(), true);
/// assert_eq!(bitmap.contain(65).unwrap(), false);
/// assert_eq!(bitmap.contain(70).unwrap(), false);
/// assert_eq!(bitmap.contain(74).unwrap(), false);
/// assert_eq!(bitmap.contain(75).unwrap(), true);
/// ```
pub fn clear_range(&mut self, start: usize, len: usize) -> Result<()> {
if len == 0 {
return Ok(());
}
let mut index = self.bit_index(start);
let mut bits_to_clear: usize = T::len() - self.bit_pos(start);
let mut mask_to_clear: T = T::bit_not(T::full().rhs(self.bit_pos(start)));
let mut length: usize = len;
while length >= bits_to_clear {
if index >= self.size() {
return Err(anyhow!(UtilError::OutOfBound(
index as u64,
self.vol() as u64
)));
}
length -= bits_to_clear;
self.data[index] = T::bit_and(self.data[index], mask_to_clear);
bits_to_clear = T::len();
mask_to_clear = T::zero();
index += 1;
}
if length > 0 {
if index >= self.size() {
return Err(anyhow!(UtilError::OutOfBound(
index as u64,
self.vol() as u64
)));
}
bits_to_clear = T::len() - self.bit_pos(start + len);
let mask_to_clear_end: T = T::bit_not(T::full().lhs(self.bit_pos(bits_to_clear)));
mask_to_clear = T::bit_or(mask_to_clear, mask_to_clear_end);
self.data[index] = T::bit_and(self.data[index], mask_to_clear);
}
Ok(())
}
/// Change the bit of bitmap.
///
/// # Arguments
///
/// * `num` - the input number
/// # Example
///
/// ```rust
/// use util::bitmap::Bitmap;
/// let mut bitmap = Bitmap::<u16>::new(1);
/// assert!(bitmap.change(15).is_ok());
/// assert_eq!(bitmap.contain(15).unwrap(), true);
/// assert!(bitmap.change(15).is_ok());
/// assert_eq!(bitmap.contain(15).unwrap(), false);
/// ```
pub fn change(&mut self, num: usize) -> Result<()> {
let index = self.bit_index(num);
if index >= self.size() {
return Err(anyhow!(UtilError::OutOfBound(
index as u64,
self.vol() as u64
)));
}
self.data[index] = T::bit_xor(self.data[index], T::one().rhs(self.bit_pos(num)));
Ok(())
}
/// Query bitmap if contains input number or not.
///
/// # Arguments
///
/// * `num` - the input number.
pub fn contain(&self, num: usize) -> Result<bool> {
if num > self.vol() {
return Err(anyhow!(UtilError::OutOfBound(
num as u64,
self.size() as u64 * T::len() as u64,
)));
}
Ok(T::bit_and(
self.data[self.bit_index(num)],
T::one().rhs(self.bit_pos(num)),
)
.bool())
}
/// Count the number of bits before the input offset.
///
/// # Arguments
///
/// * `offset` - the input offset as the query's start.
pub fn count_front_bits(&self, offset: usize) -> Result<usize> {
if offset > self.vol() {
return Err(anyhow!(UtilError::OutOfBound(
offset as u64,
self.size() as u64
)));
}
let mut num = 0;
for i in 0..self.bit_index(offset) + 1 {
if i == self.bit_index(offset) {
for j in i * T::len()..offset {
let ret = self.contain(j).with_context(|| "count front bits failed")?;
if ret {
num += 1;
}
}
break;
}
if self.data[i] != T::zero() {
for j in 0..T::len() {
if T::bit_and(self.data[i], T::one().rhs(j)).bool() {
num += 1;
};
}
}
}
Ok(num)
}
/// Return a new offset to get a zero bit from input offset.
///
/// # Arguments
///
/// * `offset` - the input offset as the query's start.
pub fn find_next_zero(&self, offset: usize) -> Result<usize> {
let size = self.size();
let idx = offset / T::len();
let mut offset = offset % T::len();
for i in idx..size {
if self.data[i] == T::full() {
continue;
}
for j in offset..T::len() {
if !self.contain(i * T::len() + j)? {
return Ok(i * T::len() + j);
}
}
offset = 0;
}
Ok(self.vol())
}
/// Return a new offset to get next nonzero bit from input offset.
///
/// # Arguments
///
/// * `offset` - the input offset as the query's start.
pub fn find_next_bit(&self, offset: usize) -> Result<usize> {
let size = self.size();
let idx = offset / T::len();
let mut offset = offset % T::len();
for i in idx..size {
if self.data[i] == T::zero() {
continue;
}
for j in offset..T::len() {
if self.contain(i * T::len() + j)? {
return Ok(i * T::len() + j);
}
}
offset = 0;
}
Ok(self.vol())
}
/// Get the inner data from bitmap.
///
/// # Arguments
///
/// * `buf` - the cache to receive the data.
pub fn get_data(&mut self, buf: &mut Vec<T>) {
buf.clear();
buf.append(&mut self.data);
}
/// clear all the data in bitmap
pub fn clear_all(&mut self) {
for i in 0..self.size() {
self.data[i] = T::zero();
}
}
fn bit_index(&self, num: usize) -> usize {
num / T::len()
}
fn bit_pos(&self, num: usize) -> usize {
num % T::len()
}
}
/// This trait is used to bind some basic operations of bit.
pub trait BitOps: Copy + Ord {
fn bool(self) -> bool;
fn len() -> usize;
fn zero() -> Self;
fn one() -> Self;
fn full() -> Self;
fn value(self) -> usize;
fn bit_not(bit: Self) -> Self;
fn bit_and(bit: Self, other_bit: Self) -> Self;
fn bit_or(bit: Self, other_bit: Self) -> Self;
fn bit_xor(bit: Self, other_bit: Self) -> Self;
fn rhs(&self, rhs: usize) -> Self;
fn lhs(&self, lhs: usize) -> Self;
}
macro_rules! bitops {
($type:ident) => {
impl BitOps for $type {
fn bool(self) -> bool {
!(self == 0)
}
fn len() -> usize {
size_of::<Self>() / size_of::<u8>() * 8
}
fn zero() -> Self {
0 as Self
}
fn one() -> Self {
1 as Self
}
fn full() -> Self {
!0 as Self
}
fn value(self) -> usize {
(self / Self::one()) as usize
}
fn bit_not(bit: Self) -> Self {
!bit
}
fn bit_and(bit: Self, other_bit: Self) -> Self {
bit & other_bit
}
fn bit_or(bit: Self, other_bit: Self) -> Self {
bit | other_bit
}
fn bit_xor(bit: Self, other_bit: Self) -> Self {
bit ^ other_bit
}
fn rhs(&self, rhs: usize) -> Self {
self << rhs
}
fn lhs(&self, lhs: usize) -> Self {
self >> lhs
}
}
};
}
bitops!(u8);
bitops!(u16);
bitops!(u32);
bitops!(u64);
#[cfg(test)]
mod tests {
use super::Bitmap;
#[test]
fn test_bitmap_basic() {
let mut bitmap = Bitmap::<u16>::new(1);
assert!(bitmap.set(15).is_ok());
assert!(bitmap.set(16).is_err());
assert_eq!(bitmap.contain(15).unwrap(), true);
assert_eq!(bitmap.count_front_bits(16).unwrap(), 1);
assert_eq!(bitmap.count_front_bits(15).unwrap(), 0);
assert!(bitmap.change(15).is_ok());
assert!(bitmap.change(16).is_err());
assert_eq!(bitmap.contain(15).unwrap(), false);
}
#[test]
fn test_bitmap_set_range() {
let mut bitmap = Bitmap::<u64>::new(4);
assert!(bitmap.set_range(256, 1).is_err());
assert!(bitmap.set_range(0, 257).is_err());
assert!(bitmap.set_range(0, 256).is_ok());
bitmap.clear_all();
assert!(bitmap.set_range(65, 10).is_ok());
assert_eq!(bitmap.contain(64).unwrap(), false);
assert_eq!(bitmap.contain(65).unwrap(), true);
assert_eq!(bitmap.contain(70).unwrap(), true);
assert_eq!(bitmap.contain(74).unwrap(), true);
assert_eq!(bitmap.contain(75).unwrap(), false);
bitmap.clear_all();
assert!(bitmap.set_range(63, 1).is_ok());
assert_eq!(bitmap.contain(62).unwrap(), false);
assert_eq!(bitmap.contain(63).unwrap(), true);
assert_eq!(bitmap.contain(64).unwrap(), false);
bitmap.clear_all();
assert!(bitmap.set_range(63, 66).is_ok());
assert_eq!(bitmap.contain(62).unwrap(), false);
assert_eq!(bitmap.contain(63).unwrap(), true);
assert_eq!(bitmap.contain(67).unwrap(), true);
assert_eq!(bitmap.contain(128).unwrap(), true);
assert_eq!(bitmap.contain(129).unwrap(), false);
bitmap.clear_all();
}
#[test]
fn test_bitmap_clear_range() {
let mut bitmap = Bitmap::<u64>::new(4);
assert!(bitmap.set_range(0, 256).is_ok());
assert!(bitmap.clear_range(256, 1).is_err());
assert!(bitmap.clear_range(0, 0).is_ok());
assert!(bitmap.clear_range(0, 257).is_err());
assert!(bitmap.set_range(0, 256).is_ok());
assert!(bitmap.clear_range(65, 10).is_ok());
assert_eq!(bitmap.contain(64).unwrap(), true);
assert_eq!(bitmap.contain(65).unwrap(), false);
assert_eq!(bitmap.contain(70).unwrap(), false);
assert_eq!(bitmap.contain(74).unwrap(), false);
assert_eq!(bitmap.contain(75).unwrap(), true);
assert!(bitmap.set_range(0, 256).is_ok());
assert!(bitmap.clear_range(63, 1).is_ok());
assert_eq!(bitmap.contain(62).unwrap(), true);
assert_eq!(bitmap.contain(63).unwrap(), false);
assert_eq!(bitmap.contain(64).unwrap(), true);
assert!(bitmap.set_range(0, 256).is_ok());
assert!(bitmap.clear_range(63, 66).is_ok());
assert_eq!(bitmap.contain(62).unwrap(), true);
assert_eq!(bitmap.contain(63).unwrap(), false);
assert_eq!(bitmap.contain(67).unwrap(), false);
assert_eq!(bitmap.contain(128).unwrap(), false);
assert_eq!(bitmap.contain(129).unwrap(), true);
assert!(bitmap.clear_range(0, 256).is_ok());
}
#[test]
fn test_bitmap_find_next_zero() {
let mut bitmap = Bitmap::<u64>::new(4);
assert!(bitmap.set_range(0, 256).is_ok());
assert!(bitmap.clear(0).is_ok());
assert!(bitmap.clear(32).is_ok());
assert!(bitmap.clear(64).is_ok());
assert!(bitmap.clear(128).is_ok());
let mut offset = 0;
offset = bitmap.find_next_zero(offset).unwrap();
assert_eq!(offset, 0);
offset = bitmap.find_next_zero(offset + 1).unwrap();
assert_eq!(offset, 32);
offset = bitmap.find_next_zero(offset + 1).unwrap();
assert_eq!(offset, 64);
offset = bitmap.find_next_zero(offset + 1).unwrap();
assert_eq!(offset, 128);
offset = bitmap.find_next_zero(offset + 1).unwrap();
assert_eq!(offset, 256);
}
#[test]
fn test_bitmap_find_next_bit() {
let mut bitmap = Bitmap::<u64>::new(4);
bitmap.clear_all();
assert!(bitmap.set(0).is_ok());
assert!(bitmap.set(32).is_ok());
assert!(bitmap.set(64).is_ok());
assert!(bitmap.set(128).is_ok());
let mut offset = 0;
offset = bitmap.find_next_bit(offset).unwrap();
assert_eq!(offset, 0);
offset = bitmap.find_next_bit(offset + 1).unwrap();
assert_eq!(offset, 32);
offset = bitmap.find_next_bit(offset + 1).unwrap();
assert_eq!(offset, 64);
offset = bitmap.find_next_bit(offset + 1).unwrap();
assert_eq!(offset, 128);
offset = bitmap.find_next_bit(offset + 1).unwrap();
assert_eq!(offset, 256);
}
}

Комментарий ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://gitlife.ru/oschina-mirror/openeuler-stratovirt.git
git@gitlife.ru:oschina-mirror/openeuler-stratovirt.git
oschina-mirror
openeuler-stratovirt
openeuler-stratovirt
master