blob: 9f188bcc2f5b5ecc3530514c20ed56688a6a298c [file] [log] [blame]
/*
* Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef FastBitVector_h
#define FastBitVector_h
#include <string.h>
#include <wtf/FastMalloc.h>
#include <wtf/StdLibExtras.h>
namespace WTF {
class PrintStream;
class FastBitVector {
public:
FastBitVector()
: m_array(0)
, m_numBits(0)
{
}
FastBitVector(const FastBitVector& other)
: m_array(0)
, m_numBits(0)
{
*this = other;
}
~FastBitVector()
{
if (m_array)
fastFree(m_array);
}
FastBitVector& operator=(const FastBitVector& other)
{
size_t length = other.arrayLength();
uint32_t* newArray = static_cast<uint32_t*>(fastCalloc(length, 4));
memcpy(newArray, other.m_array, length * 4);
if (m_array)
fastFree(m_array);
m_array = newArray;
m_numBits = other.m_numBits;
return *this;
}
size_t numBits() const { return m_numBits; }
void resize(size_t numBits)
{
if (numBits == m_numBits)
return;
// Use fastCalloc instead of fastRealloc because we expect the common
// use case for this method to be initializing the size of the bitvector.
size_t newLength = arrayLength(numBits);
uint32_t* newArray = static_cast<uint32_t*>(fastCalloc(newLength, 4));
memcpy(newArray, m_array, arrayLength() * 4);
if (m_array)
fastFree(m_array);
m_array = newArray;
m_numBits = numBits;
}
void setAll()
{
memset(m_array, 255, arrayLength() * 4);
}
void clearAll()
{
memset(m_array, 0, arrayLength() * 4);
}
void set(const FastBitVector& other)
{
ASSERT(m_numBits == other.m_numBits);
memcpy(m_array, other.m_array, arrayLength() * 4);
}
bool setAndCheck(const FastBitVector& other)
{
bool changed = false;
ASSERT(m_numBits == other.m_numBits);
for (unsigned i = arrayLength(); i--;) {
changed |= m_array[i] != other.m_array[i];
m_array[i] = other.m_array[i];
}
return changed;
}
bool equals(const FastBitVector& other) const
{
ASSERT(m_numBits == other.m_numBits);
// Use my own comparison loop because memcmp does more than what I want
// and bcmp is not as standard.
for (unsigned i = arrayLength(); i--;) {
if (m_array[i] != other.m_array[i])
return false;
}
return true;
}
void merge(const FastBitVector& other)
{
ASSERT(m_numBits == other.m_numBits);
for (unsigned i = arrayLength(); i--;)
m_array[i] |= other.m_array[i];
}
void filter(const FastBitVector& other)
{
ASSERT(m_numBits == other.m_numBits);
for (unsigned i = arrayLength(); i--;)
m_array[i] &= other.m_array[i];
}
void exclude(const FastBitVector& other)
{
ASSERT(m_numBits == other.m_numBits);
for (unsigned i = arrayLength(); i--;)
m_array[i] &= ~other.m_array[i];
}
void set(size_t i)
{
ASSERT_WITH_SECURITY_IMPLICATION(i < m_numBits);
m_array[i >> 5] |= (1 << (i & 31));
}
void clear(size_t i)
{
ASSERT_WITH_SECURITY_IMPLICATION(i < m_numBits);
m_array[i >> 5] &= ~(1 << (i & 31));
}
void set(size_t i, bool value)
{
if (value)
set(i);
else
clear(i);
}
bool get(size_t i) const
{
ASSERT_WITH_SECURITY_IMPLICATION(i < m_numBits);
return !!(m_array[i >> 5] & (1 << (i & 31)));
}
size_t bitCount() const
{
size_t result = 0;
for (unsigned i = arrayLength(); i--;)
result += WTF::bitCount(m_array[i]);
return result;
}
template<typename Functor>
void forEachSetBit(const Functor& functor)
{
unsigned n = arrayLength();
for (unsigned i = 0; i < n; ++i) {
uint32_t word = m_array[i];
unsigned j = i << 5;
while (word) {
if (word & 1)
functor(j);
word >>= 1;
j++;
}
}
}
WTF_EXPORT_PRIVATE void dump(PrintStream&) const;
private:
static size_t arrayLength(size_t numBits) { return (numBits + 31) >> 5; }
size_t arrayLength() const { return arrayLength(m_numBits); }
uint32_t* m_array; // No, this can't be an std::unique_ptr<uint32_t[]>.
size_t m_numBits;
};
} // namespace WTF
using WTF::FastBitVector;
#endif // FastBitVector_h