NORM-mirror/common/normBitmask.h

213 lines
6.8 KiB
C++

#ifndef _NORM_BITMASK_
#define _NORM_BITMASK_
#include "protokit.h" // for PROTO_DEBUG stuff
#include <string.h> // for memset()
#include <stdio.h> // for fprintf()
/***************************************************************
* This class also provides space-efficient binary storage.
* It's pretty much just a flat-indexed array of bits, but
* keeps some state to be relatively efficient for various
* operations.
*/
class NormBitmask
{
// Methods
public:
NormBitmask();
~NormBitmask();
bool Init(unsigned long numBits);
void Destroy();
unsigned long Size() {return num_bits;}
void Clear() // set to all zero's
{
memset(mask, 0, mask_len);
first_set = num_bits;
};
void Reset() // set to all one's
{
memset(mask, 0xff, (mask_len-1));
mask[mask_len-1] = 0x00ff << ((8 - (num_bits & 0x07)) & 0x07);
first_set = 0;
}
bool IsSet() const {return (first_set < num_bits);}
bool GetFirstSet(unsigned long& index) const
{
index = first_set;
return IsSet();
}
bool GetLastSet(unsigned long& index) const
{
index = num_bits - 1;
return GetPrevSet(index);
}
bool Test(unsigned long index) const
{
return ((index < num_bits) ?
(0 != (mask[(index >> 3)] & (0x80 >> (index & 0x07)))) :
false);
}
bool CanSet(unsigned long index) const
{return (index < num_bits);}
bool Set(unsigned long index)
{
if (index < num_bits)
{
mask[(index >> 3)] |= (0x80 >> (index & 0x07));
(index < first_set) ? (first_set = index) : 0;
return true;
}
else
{
return false;
}
}
bool Unset(unsigned long index)
{
if (index < num_bits)
{
mask[(index >> 3)] &= ~(0x80 >> (index & 0x07));
(index == first_set) ? first_set = GetNextSet(first_set) ? first_set : num_bits : 0;
}
return true;
}
bool Invert(unsigned long index)
{return (Test(index) ? Unset(index) : Set(index));}
bool SetBits(unsigned long baseIndex, unsigned long count);
bool UnsetBits(unsigned long baseIndex, unsigned long count);
bool GetNextSet(unsigned long& index) const;
bool GetPrevSet(unsigned long& index) const;
bool GetNextUnset(unsigned long& index) const;
bool Copy(const NormBitmask &b); // this = b
bool Add(const NormBitmask & b); // this = this | b
bool Subtract(const NormBitmask & b); // this = this & ~b
bool XCopy(const NormBitmask & b); // this = ~this & b
bool Multiply(const NormBitmask & b); // this = this & b
bool Xor(const NormBitmask & b); // this = this ^ b
void Display(FILE* stream);
// Members
private:
unsigned char* mask;
unsigned long mask_len;
unsigned long num_bits;
unsigned long first_set; // index of lowest _set_ bit
}; // end class NormBitmask
/***************************************************************
* This class also provides space-efficient binary storage.
* More than just a flat-indexed array of bits, this
* class can also automatically act as a sliding
* window buffer as long as the range of set bit
* indexes fall within the number of storage bits
* for which the class initialized.
*/
class NormSlidingMask
{
public:
NormSlidingMask();
~NormSlidingMask();
const char* GetMask() const {return (const char*)mask;}
bool Init(long numBits, UINT32 rangeMax);
void Destroy();
long Size() const {return num_bits;}
void Clear()
{
memset(mask, 0, mask_len);
start = end = num_bits;
offset = 0;
}
void Reset(unsigned long index = 0)
{
ASSERT(num_bits);
memset(mask, 0xff, mask_len);
mask[mask_len-1] = 0x00ff << ((8 - (num_bits & 0x07)) & 0x07);
start = 0;
end = num_bits - 1;
offset = index;
}
bool IsSet() const {return (start < num_bits);}
bool GetFirstSet(unsigned long& index) const
{
index = offset;
return IsSet();
}
bool GetLastSet(unsigned long& index) const
{
long n = end - start;
n = (n < 0) ? (n + num_bits) : n;
index = offset + n;
return IsSet();
}
bool Test(unsigned long index) const;
bool CanSet(unsigned long index) const;
bool Set(unsigned long index);
bool Unset(unsigned long index);
bool Invert(unsigned long index)
{return (Test(index) ? Unset(index): Set(index));}
bool SetBits(unsigned long index, long count);
bool UnsetBits(unsigned long index, long count);
// These return "false" when finding nothing
bool GetNextSet(unsigned long& index) const;
bool GetPrevSet(unsigned long& index) const;
//static unsigned long RawNextSet(const char* mask, long index, long start);
//static unsigned long RawPrevSet(const char* mask, long index, long end);
bool Copy(const NormSlidingMask& b); // this = b
bool Add(const NormSlidingMask & b); // this = this | b
bool Subtract(const NormSlidingMask & b); // this = this & ~b
bool XCopy(const NormSlidingMask & b); // this = ~this & b
bool Multiply(const NormSlidingMask & b); // this = this & b
bool Xor(const NormSlidingMask & b); // this = this ^ b
void Display(FILE* stream);
void Debug(long theCount);
private:
// Calculate "circular" delta between two indices
long Delta(unsigned long a, unsigned long b) const
{
long result = a - b;
return ((0 == (result & range_sign)) ?
(result & range_mask) :
(((result != range_sign) || (a < b)) ?
(result | ~range_mask) : result));
}
unsigned char* mask;
unsigned long mask_len;
unsigned long range_mask;
long range_sign;
long num_bits;
long start;
long end;
unsigned long offset;
}; // end class NormSlidingMask
#endif // _NORM_BITMASK_