deargui-vpl/ref/virtools/Includes/XBitArray.h

554 lines
10 KiB
C++

/*************************************************************************/
/* File : XBitArray.h */
/* Author : Aymeric Bard */
/* */
/* Virtools SDK */
/* Copyright (c) Virtools 2000, All Rights Reserved. */
/*************************************************************************/
#ifndef XBITARRAY_H
#define XBITARRAY_H "$Id:$"
#include "XArray.h"
#include "VxMath.h"
/************************************************
{filename:XBitArray}
Summary: Set of bit flags.
Remarks:
o This class define a set of bit flags that may be treated as a virtual array but are stored in an efficient manner.
o The class has methods to set, clear and return the i-th bit, resize the array, etc.
************************************************/
class XBitArray
{
public:
XBitArray(int initialsize = 1) {
if (initialsize<1) initialsize=1;
m_Size = (initialsize<<5);
if (m_Size > 32) { // we allocate only if > 32
m_Data = Allocate(initialsize);
Clear();
} else {
m_Flags = 0;
}
}
~XBitArray() {
if (m_Size > 32)
Free();
}
// copy Ctor
XBitArray(const XBitArray& a)
{
m_Size = a.m_Size;
if (m_Size <= 32)
m_Flags = a.m_Flags;
else {
m_Data = Allocate(m_Size>>5);
memcpy(m_Data,a.m_Data,m_Size>>3);
}
}
// operator =
XBitArray& operator = (const XBitArray& a)
{
if (this != &a) {
if (m_Size != a.m_Size) {
if (m_Size > 32)
Free();
m_Size = a.m_Size;
if (m_Size > 32) { // we allocate only if > 32
m_Data = Allocate(m_Size>>5);
memcpy(m_Data,a.m_Data,m_Size>>3);
} else {
m_Flags = a.m_Flags;
}
} else {
if (m_Size>32)
memcpy(m_Data,a.m_Data,m_Size>>3);
else
m_Flags = a.m_Flags;
}
}
return *this;
}
// Reallocation if necessary
void CheckSize(int n)
{
while (n >= m_Size) { // m_Size >= 32, always
int size = (m_Size>>5);
XDWORD* temp = Allocate(size+size);
// Copy the old bits
if (m_Size > 32)
memcpy(temp,m_Data,size*sizeof(XDWORD));
else
*temp = m_Flags;
// Clear the new bits
memset(temp+size,0,size*sizeof(XDWORD));
if (m_Size > 32) // we free only if we were allocated
Free();
m_Data = temp;
m_Size += m_Size;
}
}
void CheckSameSize(XBitArray& a)
{
if (m_Size < a.m_Size) {
if (a.m_Size > 32) {
int size = a.m_Size>>5;
int oldsize = m_Size>>5;
XDWORD* temp = Allocate(size);
// Copy the old bits
if (m_Size > 32)
memcpy(temp,m_Data,oldsize*sizeof(XDWORD));
else
*temp = m_Flags;
// Clear the new bits
memset(temp+oldsize,0,(size-oldsize)*sizeof(XDWORD));
if (m_Size > 32) // we free only if we were allocated
Free();
m_Data = temp;
m_Size = a.m_Size;
}
}
}
// Summary: Returns if the n-th bit is set to 1
int IsSet(int n) {
if (n >= m_Size)
return 0; // Out of range
if (m_Size <= 32)
return (m_Flags & (1<<n)); // Not allocated
return (m_Data[n>>5] & (1<<(n&31))); // Allocated after the first DWORD
}
// Summary: Returns if the n-th bit is set to 1
int operator [] (int n) {
return IsSet(n);
}
// Summary: Appends the bitcount first bits of integer v to the array
void AppendBits(int n,int v,int bitcount)
{
int mask = 1;
bitcount += n;
for(int i=n;i<bitcount; ++i,mask<<=1) {
if (mask&v)
Set(i);
else
Unset(i);
}
}
// Summary: Sets the n-th bit to 1
void Set(int n) {
if (n < m_Size) {
if (m_Size <= 32) { // Only one dword long
m_Flags |= (1<<n);
} else { // more than one dword
m_Data[n>>5] |= 1<<(n&31);
}
} else { // we have to reallocate
CheckSize(n);
m_Data[n>>5] |= 1<<(n&31);
}
}
// Summary: Sets the n-th bit to 1 and return 0 if it was set, 1 otherwise
int TestSet(int n) {
if(n < m_Size) {
if (m_Size <= 32) { // Only one dword long
int mask = 1<<n;
if (m_Flags&mask) return 0;
m_Flags |= mask;
return 1;
} else { // more than one dword
int pos = n>>5;
int mask = 1<<(n&31);
if (m_Data[pos]&mask) return 0;
m_Data[pos] |= mask;
return 1;
}
} else { // we have to reallocate
CheckSize(n);
m_Data[n>>5] |= 1<<(n&31);
return 1;
}
}
// Summary: Sets the n-th bit to 0
void Unset(int n) {
if(n < m_Size) {
if (m_Size <= 32) {
m_Flags &= ~(1<<n);
} else {
m_Data[n>>5] &= ~(1<<(n&31));
}
}
}
// Summary: Sets the n-th bit to 0 and return 1 if it was set, 0 otherwise
int TestUnset(int n) {
if(n < m_Size) {
if (m_Size <= 32) {
int mask = 1<<n;
if (m_Flags & mask) {
m_Flags &= ~mask;
return 1;
}
return 0;
} else {
int pos = n>>5;
int mask = 1<<(n&31);
if (m_Data[pos] & mask) {
m_Data[pos] &= ~mask;
return 1;
}
return 0;
}
} else return 0;
}
// Summary: Returns the number of bits
int Size() const {
return m_Size;
}
// Summary: Resets the array
void Clear() {
if (m_Size<=32)
m_Flags = 0;
else
memset(m_Data,0,(m_Size>>3));
}
// Summary: Sets all bits of the array to 1
// Warning : this functions sets all the allocated bits, not only the
// used bits
void Fill() {
if (m_Size<=32)
m_Flags = 0xffffffff;
else
memset(m_Data,0xff,(m_Size>>3));
}
// Summary: Performs a binary AND with another array
void And(XBitArray& a)
{
if (a.m_Size <= 32) {
if (m_Size <= 32)
m_Flags &= a.m_Flags;
else {
m_Data[0] &= a.m_Flags;
// clear the remaining bytes
int rsize = m_Size>>5;
for (int i=1;i<rsize;++i) {
m_Data[i] = 0;
}
}
} else {
if (m_Size <= 32)
m_Flags &= a.m_Data[0];
else {
int size = a.m_Size>>5;
int i = 0;
for (;i<size;++i) {
m_Data[i] &= a.m_Data[i];
}
// clear the remaining bytes
int rsize = m_Size>>5;
for (;i<rsize;++i) {
m_Data[i] = 0;
}
}
}
}
// Summary: subtract bits from another bitarray
XBitArray& operator -= (XBitArray& a)
{
if (a.m_Size <= 32) {
if (m_Size <= 32)
m_Flags &= ~a.m_Flags;
else {
m_Data[0] &= ~a.m_Flags;
}
} else {
if (m_Size <= 32)
m_Flags &= ~a.m_Data[0];
else {
int size = a.m_Size>>5;
int i = 0;
for (;i<size;++i) {
m_Data[i] &= ~a.m_Data[i];
}
}
}
return *this;
}
// Summary: Returns TRUE if at least one common bit is set in two arrays
BOOL CheckCommon(XBitArray& a)
{
if (a.m_Size <= 32) {
if (m_Size <= 32)
return (m_Flags & a.m_Flags);
else
return (m_Data[0] & a.m_Flags);
} else {
if (m_Size <= 32)
return (m_Flags & a.m_Data[0]);
else {
int size = a.m_Size>>5;
for (int i=0;i<size;++i) {
if (m_Data[i] & a.m_Data[i])
return TRUE;
}
}
}
return FALSE;
}
// Summary: Performs a binary OR with another array
void Or(XBitArray& a)
{
CheckSameSize(a);
if (a.m_Size <= 32) {
if (m_Size <= 32)
m_Flags |= a.m_Flags;
else
m_Data[0] |= a.m_Flags;
} else {
if (m_Size <= 32)
m_Flags |= a.m_Data[0];
else {
int size = a.m_Size>>5;
for (int i=0;i<size;++i) {
m_Data[i] |= a.m_Data[i];
}
}
}
}
// Summary: Performs a binary XOR with another array
void XOr(XBitArray& a)
{
CheckSameSize(a);
if (a.m_Size <= 32) {
if (m_Size <= 32)
m_Flags ^= a.m_Flags;
else
m_Data[0] ^= a.m_Flags;
} else {
if (m_Size <= 32)
m_Flags ^= a.m_Data[0];
else {
int size = a.m_Size>>5;
for (int i=0;i<size;++i) {
m_Data[i] ^= a.m_Data[i];
}
}
}
}
// Summary: Inverts all bits value in the array
void Invert()
{
if (m_Size <= 32) {
m_Flags = ~m_Flags;
} else {
int size = m_Size>>5;
for(int i=0;i<size;++i) {
m_Data[i] = ~m_Data[i];
}
}
}
// Summary: Returns the number of bits set
int BitSet()
{
int set = 0;
if (m_Size <= 32) {
int mask = 1;
for (int j=0;j<32;++j) {
if (m_Flags & mask)
++set;
mask<<=1;
}
} else {
int size = m_Size>>5;
for (int i=0;i<size;++i) {
int mask = 1;
for(int j=0;j<32;++j) {
if(m_Data[i]&mask) ++set;
mask<<=1;
}
}
}
return set;
}
// Summary: Returns the position of the n-th set(1) bit
int GetSetBitPosition(int n)
{
int set = 0;
int pos = 0;
if (m_Size <= 32) {
int mask = 1;
for (int j=0; j<32; ++j, ++pos) {
if (m_Flags & mask) {
if (set == n)
return pos;
++set;
}
mask<<=1;
}
} else {
int size = m_Size>>5;
for (int i=0;i<size;++i) {
int mask = 1;
for (int j=0; j<32; ++j, ++pos) {
if (m_Data[i] & mask) {
if (set == n)
return pos;
++set;
}
mask<<=1;
}
}
}
return -1;
}
// Summary: Returns the position of the n-th unset(0) bit
int GetUnsetBitPosition(int n)
{
int unset = 0;
int pos = 0;
if (m_Size <= 32) {
int mask = 1;
for (int j=0; j<32; ++j, ++pos) {
if (!(m_Flags & mask)) {
if (unset == n)
return pos;
++unset;
}
mask<<=1;
}
} else {
int size = m_Size>>5;
for (int i=0;i<size;++i) {
int mask = 1;
for (int j=0;j<32;++j,++pos) {
if (!(m_Data[i]&mask)) {
if (unset == n)
return pos;
++unset;
}
mask<<=1;
}
}
}
// We haven't found an unsetted bit yet : we reallocate
CheckSize(pos);
return pos;
}
char * ConvertToString(char * buffer)
{
if (buffer)
{
int count=0;
if (m_Size <= 32) {
for (int j=0;j<32;j++)
{
if (m_Flags & (1<<j))
buffer[count]='1';
else
buffer[count]='0';
count++;
}
} else {
for (int i=0;i<(m_Size>>5);i++)
{
for (int j=0;j<32;j++)
{
if (m_Data[i] & (1<<j))
buffer[count]='1';
else
buffer[count]='0';
count++;
}
}
}
buffer[m_Size]=0;
}
return buffer;
}
// Summary: Returns the occupied size in memory in bytes
int GetMemoryOccupation(BOOL addstatic=FALSE) const {
if (m_Size<=32)
return addstatic?sizeof(*this):0;
else
return (m_Size>>5)*sizeof(XDWORD)+(addstatic?sizeof(*this):0);
}
private:
XDWORD* Allocate(int size)
{
return new XDWORD[size];
}
void Free()
{
delete [] m_Data;
}
// the array itself {secret}
// If the size is inferior strict to 32
// the data array is not allocated, we
// just use the sapce of the pointer to store the
// first bits
union {
XDWORD* m_Data;
XDWORD m_Flags;
};
// real size already allocated {secret}
int m_Size;
};
#endif // BITARRAY_H