229 lines
5.5 KiB
C++
229 lines
5.5 KiB
C++
|
|
// bitvector.hpp
|
||
|
|
// Copyright (c) 2012 Ben Hanson (http://www.benhanson.net/)
|
||
|
|
//
|
||
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||
|
|
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||
|
|
|
||
|
|
#ifndef LEXERTL_BITVECTOR_HPP
|
||
|
|
#define LEXERTL_BITVECTOR_HPP
|
||
|
|
|
||
|
|
#include <vector>
|
||
|
|
|
||
|
|
namespace lexertl
|
||
|
|
{
|
||
|
|
template<typename T>
|
||
|
|
class basic_bitvector
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
template<typename Ty>
|
||
|
|
class reference
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
reference (Ty &block_, const std::size_t mask_) :
|
||
|
|
_block (block_),
|
||
|
|
_mask (mask_)
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
operator bool () const
|
||
|
|
{
|
||
|
|
return (_block & _mask) != 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
reference<Ty> &operator = (const bool bit_)
|
||
|
|
{
|
||
|
|
if (bit_)
|
||
|
|
{
|
||
|
|
_block |= _mask;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_block &= ~_mask;
|
||
|
|
}
|
||
|
|
|
||
|
|
return *this;
|
||
|
|
}
|
||
|
|
|
||
|
|
reference<Ty> &operator = (reference<Ty> &rhs_)
|
||
|
|
{
|
||
|
|
if (rhs_)
|
||
|
|
{
|
||
|
|
_block |= _mask;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_block &= ~_mask;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private:
|
||
|
|
Ty &_block;
|
||
|
|
const std::size_t _mask;
|
||
|
|
};
|
||
|
|
|
||
|
|
basic_bitvector (const std::size_t size_) :
|
||
|
|
_vec (block (size_) + (bit (size_) ? 1 : 0), 0)
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
basic_bitvector (const basic_bitvector &rhs_) :
|
||
|
|
_vec (rhs_._vec)
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
basic_bitvector &operator = (const basic_bitvector &rhs_)
|
||
|
|
{
|
||
|
|
if (&rhs_ != this)
|
||
|
|
{
|
||
|
|
_vec = rhs_._vec;
|
||
|
|
}
|
||
|
|
|
||
|
|
return *this;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool operator [] (const std::size_t index_) const
|
||
|
|
{
|
||
|
|
return (_vec[block (index_)] & (1 << bit (index_))) != 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
reference<T> operator [] (const std::size_t index_)
|
||
|
|
{
|
||
|
|
return reference<T> (_vec[block (index_)], (1 << bit (index_)));
|
||
|
|
}
|
||
|
|
|
||
|
|
basic_bitvector<T> &operator |= (const basic_bitvector<T> &rhs_)
|
||
|
|
{
|
||
|
|
typename t_vector::iterator lhs_iter_ = _vec.begin ();
|
||
|
|
typename t_vector::iterator lhs_end_ = _vec.end ();
|
||
|
|
typename t_vector::const_iterator rhs_iter_ = rhs_._vec.begin ();
|
||
|
|
typename t_vector::const_iterator rhs_end_ = rhs_._vec.end ();
|
||
|
|
|
||
|
|
for (; lhs_iter_ != lhs_end_ && rhs_iter_ != rhs_end_;
|
||
|
|
++lhs_iter_, ++rhs_iter_)
|
||
|
|
{
|
||
|
|
*lhs_iter_ |= *rhs_iter_;
|
||
|
|
}
|
||
|
|
|
||
|
|
return *this;
|
||
|
|
}
|
||
|
|
|
||
|
|
basic_bitvector<T> &operator &= (const basic_bitvector<T> &rhs_)
|
||
|
|
{
|
||
|
|
typename t_vector::iterator lhs_iter_ = _vec.begin ();
|
||
|
|
typename t_vector::iterator lhs_end_ = _vec.end ();
|
||
|
|
typename t_vector::const_iterator rhs_iter_ = rhs_._vec.begin ();
|
||
|
|
typename t_vector::const_iterator rhs_end_ = rhs_._vec.end ();
|
||
|
|
|
||
|
|
for (; lhs_iter_ != lhs_end_ && rhs_iter_ != rhs_end_;
|
||
|
|
++lhs_iter_, ++rhs_iter_)
|
||
|
|
{
|
||
|
|
*lhs_iter_ &= *rhs_iter_;
|
||
|
|
}
|
||
|
|
|
||
|
|
return *this;
|
||
|
|
}
|
||
|
|
|
||
|
|
void clear ()
|
||
|
|
{
|
||
|
|
typename t_vector::iterator iter_ = _vec.begin ();
|
||
|
|
typename t_vector::iterator end_ = _vec.end ();
|
||
|
|
|
||
|
|
for (; iter_ != end_; ++iter_)
|
||
|
|
{
|
||
|
|
*iter_ = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
bool any () const
|
||
|
|
{
|
||
|
|
typename t_vector::const_iterator iter_ = _vec.begin ();
|
||
|
|
typename t_vector::const_iterator end_ = _vec.end ();
|
||
|
|
|
||
|
|
for (; iter_ != end_; ++iter_)
|
||
|
|
{
|
||
|
|
if (*iter_) break;
|
||
|
|
}
|
||
|
|
|
||
|
|
return iter_ != end_;
|
||
|
|
}
|
||
|
|
|
||
|
|
void negate ()
|
||
|
|
{
|
||
|
|
typename t_vector::iterator iter_ = _vec.begin ();
|
||
|
|
typename t_vector::iterator end_ = _vec.end ();
|
||
|
|
|
||
|
|
for (; iter_ != end_; ++iter_)
|
||
|
|
{
|
||
|
|
*iter_ = ~*iter_;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
std::size_t find_first () const
|
||
|
|
{
|
||
|
|
return find_next (npos ());
|
||
|
|
}
|
||
|
|
|
||
|
|
std::size_t find_next (const std::size_t index_) const
|
||
|
|
{
|
||
|
|
std::size_t ret_ = npos ();
|
||
|
|
const std::size_t block_ = index_ == npos () ? 0 : block (index_ + 1);
|
||
|
|
std::size_t bit_ = index_ == npos () ? 0 : bit (index_ + 1);
|
||
|
|
typename t_vector::const_iterator iter_ = _vec.begin () + block_;
|
||
|
|
typename t_vector::const_iterator end_ = _vec.end ();
|
||
|
|
|
||
|
|
for (std::size_t i_ = block_; iter_ != end_; ++iter_, ++i_)
|
||
|
|
{
|
||
|
|
const bool bits_ = (*iter_ & (static_cast<T>(~0) << bit_)) != 0;
|
||
|
|
|
||
|
|
if (bits_)
|
||
|
|
{
|
||
|
|
std::size_t j_ = bit_;
|
||
|
|
std::size_t b_ = 1 << bit_;
|
||
|
|
bool found_ = false;
|
||
|
|
|
||
|
|
for (; j_ < sizeof(T) * 8; ++j_, b_ <<= 1)
|
||
|
|
{
|
||
|
|
if (*iter_ & b_)
|
||
|
|
{
|
||
|
|
found_ = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (found_)
|
||
|
|
{
|
||
|
|
ret_ = i_ * sizeof(T) * 8 + j_;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
bit_ = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
return ret_;
|
||
|
|
}
|
||
|
|
|
||
|
|
std::size_t npos () const
|
||
|
|
{
|
||
|
|
return static_cast<std::size_t>(~0);
|
||
|
|
}
|
||
|
|
|
||
|
|
private:
|
||
|
|
typedef std::vector<T> t_vector;
|
||
|
|
|
||
|
|
t_vector _vec;
|
||
|
|
|
||
|
|
std::size_t block (const std::size_t index_) const
|
||
|
|
{
|
||
|
|
return index_ / (sizeof(T) * 8);
|
||
|
|
}
|
||
|
|
|
||
|
|
std::size_t bit (const std::size_t index_) const
|
||
|
|
{
|
||
|
|
return index_ % (sizeof(T) * 8);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif
|