tinystl实现(第二十五步:bitmap实现)

39 篇文章 4 订阅
28 篇文章 36 订阅

经过长时间的学习终于可以开始tinystl的仿(chao)写工作了,本文参考了这位大神的github,坦白讲我只是补充了注释,因为tinystl的代码真的非常经典而我又没什么这种大型项目的经验,所以只能这样做,不过相信能够有助于大家的学习
#强烈建议按顺序阅读本专栏
bitmap的实现方法非常有趣,对于一个byte中的每一位进行分别操作,从而达到了记录大量01bool值的效果
.h文件

#pragma once
#ifndef _BITMAP_H_
#define _BITMAP_H_

#include <cstdint>
#include <iostream>
#include <stdexcept>
//#include <string>

#include "Allocator.h"
#include "String.h"
#include "UninitializedFunctions.h"

namespace mySTL {

	//bitmap会将N上调至8的倍数
	//因此bitmap实际上会操作的bit数是大于等于N的
	template<size_t N>
	class bitmap {
	public:
		typedef allocator<uint8_t> dataAllocator;
	private:
		uint8_t *start_;
		uint8_t *finish_;
		const size_t size_;//记录多少bit
		const size_t sizeOfUINT8_;//记录多少uint8_t
		enum EAlign { ALIGN = 8 };
	public:
		bitmap();

		//Returns the number of bits in the bitset that are set (i.e., that have a value of one)
		size_t count() const;
		size_t size() const { return size_; }
		//Returns whether the bit at position pos is set (i.e., whether it is one).
		bool test(size_t pos) const;
		//Returns whether any of the bits is set (i.e., whether at least one bit in the bitset is set to one).
		bool any() const;
		//Returns whether none of the bits is set (i.e., whether all bits in the bitset have a value of zero).
		bool none() const;
		//Returns whether all of the bits in the bitset are set (to one).
		bool all() const;

		bitmap& set();
		bitmap& set(size_t pos, bool val = true);
		bitmap& reset();
		bitmap& reset(size_t pos);
		bitmap& flip();
		bitmap& flip(size_t pos);

		//std::string to_string() const;
		string to_string() const;

		template<size_t N>
		friend std::ostream& operator <<(std::ostream& os, const bitmap<N>& bm);
	private:
		size_t roundUp8(size_t bytes);
		//将i的第nth为置为newVal
		void setNthInInt8(uint8_t& i, size_t nth, bool newVal);
		//取出i的第nth位
		uint8_t getMask(uint8_t i, size_t nth)const { return (i & (1 << nth)); }
		//将第n个位置转换为其在第几个uint8_t中
		size_t getNth(size_t n)const { return (n / 8); }
		//将第n个位置转换为其在第N个uint8_t中的第几个bit上
		size_t getMth(size_t n)const { return (n % EAlign::ALIGN); }
		void allocateAndFillN(size_t n, uint8_t val);
		void THROW(size_t n)const;
	};// end of bitmap
}

#include "Detail\Bitmap.impl.h"
#endif

impl.h

#pragma once
#ifndef  _BITMAP_IMPL_H_
#define _BITMAP_IMPL_H_
namespace mySTL {
	template<size_t N>
	void bitmap<N>::allocateAndFillN(size_t n, uint8_t val) {
		start_ = dataAllocator::allocate(n);
		finish_ = uninitialized_fill_n(start_, n, val);
	}
	//判断越界
	template<size_t N>
	void bitmap<N>::THROW(size_t n)const {
		if (!(0 <= n && n < size()))
			throw std::out_of_range("Out Of Range");
	}
	//
	template<size_t N>
	void bitmap<N>::setNthInInt8(uint8_t& i, size_t nth, bool newVal) {//nth从0开始
		uint8_t temp = getMask(i, nth);//getmask获取对应位置的值
		if ((bool)temp == newVal) {
			return;
		}
		else {
			if (temp) {//nth位为1
				temp = ~temp;//反转后只有对应位置0
				i = i & temp;
			}
			else {//nth位为0
				i = i | (1 << nth);//将1移动到对应位置再填入
			}
		}
	}
	//规整至8的倍数(会随着align的变化而变化)
	template<size_t N>
	size_t bitmap<N>::roundUp8(size_t bytes) {
		return ((bytes + EAlign::ALIGN - 1) & ~(EAlign::ALIGN - 1));
	}
	//全部设1
	template<size_t N>
	bitmap<N>& bitmap<N>::set() {
		uninitialized_fill_n(start_, sizeOfUINT8_, ~0);
		return *this;
	}
	//全部设0
	template<size_t N>
	bitmap<N>& bitmap<N>::reset() {
		uninitialized_fill_n(start_, sizeOfUINT8_, 0);
		return *this;
	}
	//查找
	template<size_t N>
	bool bitmap<N>::test(size_t pos) const {
		THROW(pos);//是否越界
		const auto nth = getNth(pos);//找到在第几块
		const auto mth = getMth(pos);//找到第几块的第几位
		uint8_t *ptr = start_ + nth;//
		uint8_t temp = getMask(*ptr, mth);
		if (temp)
			return true;
		return false;
	}
	//
	template<size_t N>
	bitmap<N>::bitmap() :size_(roundUp8(N)), sizeOfUINT8_(roundUp8(N) / 8) {
		allocateAndFillN(sizeOfUINT8_, 0);
	}
	//
	template<size_t N>
	bitmap<N>& bitmap<N>::set(size_t pos, bool val) {
		THROW(pos);
		const auto nth = getNth(pos);
		const auto mth = getMth(pos);
		uint8_t *ptr = start_ + nth;//get the nth uint8_t
		setNthInInt8(*ptr, mth, val);
		return *this;
	}
	//将某点置0
	template<size_t N>
	bitmap<N>& bitmap<N>::reset(size_t pos) {
		set(pos, false);
		return *this;
	}
	//全部取反
	template<size_t N>
	bitmap<N>& bitmap<N>::flip() {
		uint8_t *ptr = start_;
		for (; ptr != finish_; ++ptr) {
			uint8_t n = *ptr;
			*ptr = ~n;
		}
		return *this;
	}
	//反转对应位
	template<size_t N>
	bitmap<N>& bitmap<N>::flip(size_t pos) {
		THROW(pos);
		const auto nth = getNth(pos);
		const auto mth = getMth(pos);
		uint8_t *ptr = start_ + nth;
		uint8_t temp = getMask(*ptr, mth);
		if (temp)
			setNthInInt8(*ptr, mth, false);
		else
			setNthInInt8(*ptr, mth, true);
		return *this;
	}
	//计数共多少为真
	template<size_t N>
	size_t bitmap<N>::count() const {
		uint8_t *ptr = start_;
		size_t sum = 0;
		for (; ptr != finish_; ++ptr) {
			for (int i = 0; i != 8; ++i) {
				uint8_t t = getMask(*ptr, i);
				if (t) {
					++sum;
				}
			}
		}
		return sum;
	}
	//查找是否有1,可以整个区块判断
	template<size_t N>
	bool bitmap<N>::any() const {
		uint8_t *ptr = start_;
		for (; ptr != finish_; ++ptr) {
			uint8_t n = *ptr;
			if (n != 0)
				return true;
		}
		return false;
	}
	//查找是否有0,于上同理
	template<size_t N>
	bool bitmap<N>::all() const {
		uint8_t *ptr = start_;
		for (; ptr != finish_; ++ptr) {
			uint8_t n = *ptr;
			if (n != (uint8_t)~0)
				return false;
		}
		return true;
	}
	
	template<size_t N>
	bool bitmap<N>::none() const {
		return !any();
	}
	//打印函数
	template<size_t N>
	string bitmap<N>::to_string() const {
		string str;
		uint8_t *ptr = start_;
		for (; ptr != finish_; ++ptr) {
			uint8_t n = *ptr;
			for (int i = 0; i != 8; ++i) {
				uint8_t t = getMask(n, i);
				if (t) str += "1";
				else str += "0";
			}
		}
		return str;
	}

	template<size_t N>
	std::ostream& operator <<(std::ostream& os, const bitmap<N>& bm) {
		os << bm.to_string();
		return os;
	}
}
#endif // ! _BITMAP_IMPL_H_

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值