380 lines
9.8 KiB
C++
380 lines
9.8 KiB
C++
// -*- c-basic-offset: 4; related-file-name: "../../lib/bitvector.cc" -*-
|
|
#ifndef CLICK_BITVECTOR_HH
|
|
#define CLICK_BITVECTOR_HH
|
|
#include <click/glue.hh>
|
|
CLICK_DECLS
|
|
|
|
/** @file <click/bitvector.hh>
|
|
* @brief Click's bitvector class. */
|
|
|
|
/** @class Bitvector
|
|
@brief Vector of bits.
|
|
|
|
The Bitvector class implements a vector of individually addressable bits.
|
|
It supports bitwise operations such as |= and &= as well as the usual
|
|
assignment and indexing operations.
|
|
|
|
Bitvectors are stored as arrays of data words with type word_type, each
|
|
containing wbits bits. For some purposes it may be faster or easier to
|
|
manipulate data words directly. */
|
|
class Bitvector {
|
|
public:
|
|
|
|
class Bit;
|
|
typedef bool (Bitvector::*unspecified_bool_type)() const;
|
|
|
|
typedef uint32_t word_type;
|
|
enum { wbits = 32, wshift = 5, wmask = 31 };
|
|
|
|
inline Bitvector();
|
|
explicit inline Bitvector(int n);
|
|
explicit inline Bitvector(bool bit);
|
|
inline Bitvector(int n, bool bit);
|
|
inline Bitvector(const Bitvector &x);
|
|
inline ~Bitvector();
|
|
|
|
inline int size() const;
|
|
inline Bit operator[](int i);
|
|
inline bool operator[](int i) const;
|
|
inline Bit force_bit(int i);
|
|
|
|
inline int word_size() const;
|
|
inline int max_word() const;
|
|
inline word_type *words();
|
|
inline const word_type *words() const;
|
|
|
|
bool zero() const;
|
|
inline operator unspecified_bool_type() const;
|
|
inline bool operator!() const;
|
|
|
|
Bitvector &assign(int n, bool bit);
|
|
Bitvector &operator=(const Bitvector &x);
|
|
void clear();
|
|
void resize(int n);
|
|
|
|
friend inline bool operator==(const Bitvector &a, const Bitvector &b);
|
|
friend inline bool operator!=(const Bitvector &a, const Bitvector &b);
|
|
bool nonzero_intersection(const Bitvector &x) const;
|
|
|
|
inline Bitvector operator~() const;
|
|
friend inline Bitvector operator&(Bitvector a, const Bitvector &b);
|
|
friend inline Bitvector operator|(Bitvector a, const Bitvector &b);
|
|
friend inline Bitvector operator^(Bitvector a, const Bitvector &b);
|
|
friend inline Bitvector operator-(Bitvector a, const Bitvector &b);
|
|
|
|
void flip();
|
|
inline void negate();
|
|
Bitvector &operator&=(const Bitvector &x);
|
|
Bitvector &operator|=(const Bitvector &x);
|
|
Bitvector &operator^=(const Bitvector &x);
|
|
inline Bitvector &operator-=(const Bitvector &x);
|
|
void offset_or(const Bitvector &x, int offset);
|
|
void or_with_difference(const Bitvector &x, Bitvector &difference);
|
|
|
|
void swap(Bitvector &x);
|
|
|
|
/** @cond never */
|
|
typedef word_type data_word_type CLICK_DEPRECATED;
|
|
enum { data_word_bits = wbits };
|
|
inline word_type *data_words() CLICK_DEPRECATED;
|
|
inline const word_type *data_words() const CLICK_DEPRECATED;
|
|
/** @endcond never */
|
|
|
|
private:
|
|
|
|
enum { ninline = 2, inlinebits = ninline * wbits };
|
|
|
|
int _max;
|
|
word_type *_data;
|
|
word_type _f[ninline];
|
|
|
|
void finish_copy_constructor(const Bitvector &);
|
|
inline void clear_last();
|
|
void hard_resize(int, bool);
|
|
|
|
};
|
|
|
|
|
|
/** @class Bitvector::Bit
|
|
@brief A wrapper class that acts like a single bit.
|
|
|
|
Bits are returned by modifiable Bitvectors' operator[]. They act like bools,
|
|
but Bit operations actually index into individual bits in some shared word. */
|
|
class Bitvector::Bit { public:
|
|
|
|
inline Bit(Bitvector::word_type &w, int bit_offset);
|
|
|
|
inline operator bool() const;
|
|
|
|
inline Bit &operator=(bool x);
|
|
inline Bit &operator=(const Bit &x);
|
|
inline void flip();
|
|
|
|
inline Bit &operator&=(bool x);
|
|
inline Bit &operator|=(bool x);
|
|
inline Bit &operator^=(bool x);
|
|
inline Bit &operator-=(bool x);
|
|
|
|
private:
|
|
|
|
Bitvector::word_type &_p;
|
|
Bitvector::word_type _mask;
|
|
|
|
};
|
|
|
|
|
|
/** @brief Construct an empty bitvector. */
|
|
inline Bitvector::Bitvector()
|
|
: _max(-1), _data(_f) {
|
|
_f[0] = 0;
|
|
}
|
|
|
|
/** @brief Construct an all-false bitvector with @a n elements.
|
|
@pre @a n >= 0 */
|
|
inline Bitvector::Bitvector(int n)
|
|
: _data(_f) {
|
|
assert(n >= 0);
|
|
if (n <= inlinebits) {
|
|
_max = n - 1;
|
|
memset(_f, 0, sizeof(_f));
|
|
} else {
|
|
_max = -1;
|
|
resize(n);
|
|
}
|
|
}
|
|
|
|
/** @brief Construct a @a bit-valued length-1 bitvector. */
|
|
inline Bitvector::Bitvector(bool bit)
|
|
: _max(0), _data(_f) {
|
|
_f[0] = bit;
|
|
}
|
|
|
|
/** @brief Construct a @a bit-valued length-@a n bitvector.
|
|
@pre @a n >= 0 */
|
|
inline Bitvector::Bitvector(int n, bool b)
|
|
: _max(-1), _data(_f) {
|
|
assign(n, b);
|
|
}
|
|
|
|
/** @brief Construct a bitvector as a copy of @a x. */
|
|
inline Bitvector::Bitvector(const Bitvector &x)
|
|
: _max(x._max), _data(_f) {
|
|
if (_max < inlinebits)
|
|
memcpy(_data, x._data, ninline * sizeof(word_type));
|
|
else
|
|
finish_copy_constructor(x);
|
|
}
|
|
|
|
/** @brief Destroy a bitvector.
|
|
|
|
All outstanding Bit objects become invalid. */
|
|
inline Bitvector::~Bitvector() {
|
|
if (_data != _f)
|
|
delete[] _data;
|
|
}
|
|
|
|
/** @brief Return the number of bits in the bitvector. */
|
|
inline int Bitvector::size() const {
|
|
return _max + 1;
|
|
}
|
|
|
|
/** @brief Test if the bitvector contains at least one true bit.
|
|
@sa zero() */
|
|
inline Bitvector::operator unspecified_bool_type() const {
|
|
return !zero() ? &Bitvector::zero : 0;
|
|
}
|
|
|
|
/** @brief Test if the bitvector contains no true bits.
|
|
@sa zero() */
|
|
inline bool Bitvector::operator!() const {
|
|
return zero();
|
|
}
|
|
|
|
/** @brief Return the bit at position @a i.
|
|
@pre 0 <= @a i < size() */
|
|
inline Bitvector::Bit Bitvector::operator[](int i) {
|
|
assert(i >= 0 && i <= _max);
|
|
return Bit(_data[i>>wshift], i & wmask);
|
|
}
|
|
|
|
/** @overload */
|
|
inline bool Bitvector::operator[](int i) const {
|
|
assert(i >= 0 && i <= _max);
|
|
return (_data[i>>wshift] & (word_type(1) << (i & wmask))) != 0;
|
|
}
|
|
|
|
/** @brief Return the bit at position @a i, extending if necessary.
|
|
|
|
If @a i >= size(), then the bitvector is resize()d to length @a i+1,
|
|
which adds false bits to fill out the vector.
|
|
|
|
@pre 0 <= @a i
|
|
@post @a i < size() */
|
|
inline Bitvector::Bit Bitvector::force_bit(int i) {
|
|
assert(i >= 0);
|
|
if (i > _max)
|
|
resize(i + 1);
|
|
return Bit(_data[i>>wshift], i & wmask);
|
|
}
|
|
|
|
/** @brief Return the number of valid data words. */
|
|
inline int Bitvector::word_size() const {
|
|
return (_max + wbits) >> wshift;
|
|
}
|
|
|
|
/** @brief Return the index of the maximum valid data word. */
|
|
inline int Bitvector::max_word() const {
|
|
return (_max < 0 ? -1 : _max >> wshift);
|
|
}
|
|
|
|
/** @brief Return a pointer to this bitvector's data words. */
|
|
inline Bitvector::word_type *Bitvector::words() {
|
|
return _data;
|
|
}
|
|
|
|
/** @overload */
|
|
inline const Bitvector::word_type *Bitvector::words() const {
|
|
return _data;
|
|
}
|
|
|
|
/** @cond never */
|
|
inline Bitvector::word_type *Bitvector::data_words() {
|
|
return _data;
|
|
}
|
|
inline const Bitvector::word_type *Bitvector::data_words() const {
|
|
return _data;
|
|
}
|
|
/** @endcond never */
|
|
|
|
/** @brief Test bitvectors for equality. */
|
|
inline bool operator==(const Bitvector &a, const Bitvector &b) {
|
|
return a.size() == b.size()
|
|
&& memcmp(a.words(), b.words(), a.word_size() * sizeof(Bitvector::word_type)) == 0;
|
|
}
|
|
|
|
/** @brief Test bitvectors for inequality. */
|
|
inline bool operator!=(const Bitvector &a, const Bitvector &b) {
|
|
return !(a == b);
|
|
}
|
|
|
|
/** @brief Modify this bitvector by bitwise subtraction with @a x.
|
|
@pre @a x.size() == size()
|
|
@return *this
|
|
|
|
Equivalent to <code>*this &= ~@a x</code>. */
|
|
inline Bitvector &Bitvector::operator-=(const Bitvector &x) {
|
|
return *this &= ~x;
|
|
}
|
|
|
|
/** @brief Flip all bits in this bitvector.
|
|
@sa negate() */
|
|
inline void Bitvector::negate() {
|
|
flip();
|
|
}
|
|
|
|
/** @brief Return the bitwise negation of this bitvector. */
|
|
inline Bitvector Bitvector::operator~() const {
|
|
Bitvector m = *this;
|
|
m.flip();
|
|
return m;
|
|
}
|
|
|
|
/** @brief Return the bitwise and of two bitvectors.
|
|
@pre @a a.size() == @a b.size() */
|
|
inline Bitvector operator&(Bitvector a, const Bitvector &b) {
|
|
return a &= b;
|
|
}
|
|
|
|
/** @brief Return the bitwise or of two bitvectors.
|
|
@pre @a a.size() == @a b.size() */
|
|
inline Bitvector operator|(Bitvector a, const Bitvector &b) {
|
|
return a |= b;
|
|
}
|
|
|
|
/** @brief Return the bitwise exclusive or of two bitvectors.
|
|
@pre @a a.size() == @a b.size() */
|
|
inline Bitvector operator^(Bitvector a, const Bitvector &b) {
|
|
return a ^= b;
|
|
}
|
|
|
|
/** @brief Return the bitwise subtraction of two bitvectors.
|
|
@pre @a a.size() == @a b.size()
|
|
|
|
<code>a - b</code> is equivalent to <code>a & ~b</code>. */
|
|
inline Bitvector operator-(Bitvector a, const Bitvector &b) {
|
|
return a & ~b;
|
|
}
|
|
|
|
inline void click_swap(Bitvector &a, Bitvector &b) {
|
|
a.swap(b);
|
|
}
|
|
|
|
inline void assign_consume(Bitvector &a, Bitvector &b) {
|
|
a.swap(b);
|
|
}
|
|
|
|
|
|
/** @brief Construct a bit at offset @a bit_offset in data word @a w. */
|
|
inline Bitvector::Bit::Bit(Bitvector::word_type &w, int bit_offset)
|
|
: _p(w), _mask(Bitvector::word_type(1) << bit_offset) {
|
|
}
|
|
|
|
/** @brief Test if this bit is true. */
|
|
inline Bitvector::Bit::operator bool() const {
|
|
return (_p & _mask) != 0;
|
|
}
|
|
|
|
/** @brief Set this bit to @a x. */
|
|
inline Bitvector::Bit &Bitvector::Bit::operator=(bool x) {
|
|
if (x)
|
|
_p |= _mask;
|
|
else
|
|
_p &= ~_mask;
|
|
return *this;
|
|
}
|
|
|
|
/** @overload */
|
|
inline Bitvector::Bit &Bitvector::Bit::operator=(const Bit &x) {
|
|
if (x._p & x._mask)
|
|
_p |= _mask;
|
|
else
|
|
_p &= ~_mask;
|
|
return *this;
|
|
}
|
|
|
|
/** @brief Flip this bit. */
|
|
inline void Bitvector::Bit::flip() {
|
|
_p ^= _mask;
|
|
}
|
|
|
|
/** @brief Modify this bit by bitwise and with @a x. */
|
|
inline Bitvector::Bit &Bitvector::Bit::operator&=(bool x) {
|
|
if (!x)
|
|
_p &= ~_mask;
|
|
return *this;
|
|
}
|
|
|
|
/** @brief Modify this bit by bitwise or with @a x. */
|
|
inline Bitvector::Bit &Bitvector::Bit::operator|=(bool x) {
|
|
if (x)
|
|
_p |= _mask;
|
|
return *this;
|
|
}
|
|
|
|
/** @brief Modify this bit by bitwise exclusive or with @a x. */
|
|
inline Bitvector::Bit &Bitvector::Bit::operator^=(bool x) {
|
|
if (x)
|
|
_p ^= _mask;
|
|
return *this;
|
|
}
|
|
|
|
/** @brief Modify this bit by bitwise subtraction with @a x. */
|
|
inline Bitvector::Bit &Bitvector::Bit::operator-=(bool x) {
|
|
if (x)
|
|
_p &= ~_mask;
|
|
return *this;
|
|
}
|
|
|
|
CLICK_ENDDECLS
|
|
#endif
|