Blame IbAccess/Common/Public/ibitvector.c

Packit 857059
/* BEGIN_ICS_COPYRIGHT6 ****************************************
Packit 857059
Packit 857059
Copyright (c) 2015, Intel Corporation
Packit 857059
Packit 857059
Redistribution and use in source and binary forms, with or without
Packit 857059
modification, are permitted provided that the following conditions are met:
Packit 857059
Packit 857059
    * Redistributions of source code must retain the above copyright notice,
Packit 857059
      this list of conditions and the following disclaimer.
Packit 857059
    * Redistributions in binary form must reproduce the above copyright
Packit 857059
      notice, this list of conditions and the following disclaimer in the
Packit 857059
     documentation and/or other materials provided with the distribution.
Packit 857059
    * Neither the name of Intel Corporation nor the names of its contributors
Packit 857059
      may be used to endorse or promote products derived from this software
Packit 857059
      without specific prior written permission.
Packit 857059
Packit 857059
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Packit 857059
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit 857059
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Packit 857059
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
Packit 857059
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit 857059
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
Packit 857059
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
Packit 857059
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
Packit 857059
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 857059
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 857059
Packit 857059
** END_ICS_COPYRIGHT6   ****************************************/
Packit 857059
Packit 857059
Packit 857059
#include "ibitvector.h"
Packit 857059
#include "imemory.h"
Packit 857059
#include "imath.h"
Packit 857059
Packit 857059
// Make a memory tag of 'ivec' for ivector.
Packit 857059
#define VEC_MEM_TAG		MAKE_MEM_TAG( i, v, e, c )
Packit 857059
Packit 857059
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
// bit vector access methods
Packit 857059
// These methods are an attempt to follow the functionality of the C++ STL.
Packit 857059
// The names and behavior are obviously not exact matches, but hopefully,
Packit 857059
// close enough to make those familiar with the ANSI standard comfortable.
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
Packit 857059
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
// BitVectorInitState
Packit 857059
// 
Packit 857059
// Description:
Packit 857059
//	This function performs basic bit vector initialization.  This function cannot 
Packit 857059
//	fail.
Packit 857059
// 
Packit 857059
// Inputs:
Packit 857059
//	pBitVector - Pointer to bit vector
Packit 857059
// 
Packit 857059
// Outputs:
Packit 857059
//	None.
Packit 857059
// 
Packit 857059
// Returns:
Packit 857059
//	None.
Packit 857059
// 
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
void 
Packit 857059
BitVectorInitState(
Packit 857059
	IN	BIT_VECTOR* const	pBitVector )
Packit 857059
{
Packit 857059
	ASSERT( pBitVector );
Packit 857059
Packit 857059
	MemoryClear( pBitVector, sizeof( BIT_VECTOR ) );
Packit 857059
}
Packit 857059
Packit 857059
Packit 857059
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
// BitVectorInit
Packit 857059
// 
Packit 857059
// Description:
Packit 857059
//	This function initializes the bit vector.  New bits in the bit vector are
Packit 857059
//	initialized to 0.
Packit 857059
// 
Packit 857059
// Inputs:
Packit 857059
//	pBitVector		- Pointer to bit vector
Packit 857059
//	InitialSize	- prefered initial number of bits
Packit 857059
//	GrowSize	- number of bits to allocate when incrementally growing
Packit 857059
//				the bit vector (will round up to multiple of processor
Packit 857059
//				word size)
Packit 857059
//	MaxSize		- maximum number of bits in bit vector, 0 -> no limit
Packit 857059
//	Context		- Context value passed to the callbacks.
Packit 857059
//	IsPageable	- TRUE indicates the bit vector should use pageable memory
Packit 857059
//				FALSE indicates the bit vector should used non-paged memory
Packit 857059
// 
Packit 857059
// Outputs:
Packit 857059
//	None.
Packit 857059
// 
Packit 857059
// Returns:
Packit 857059
//	FSUCCESS
Packit 857059
//	FINSUFFICIENT_MEMORY - bit vector is initialized to zero size
Packit 857059
// 
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
FSTATUS
Packit 857059
BitVectorInit(
Packit 857059
	IN	BIT_VECTOR* const	pBitVector,
Packit 857059
	IN	const uint32	InitialSize,
Packit 857059
	IN	const uint32	GrowSize,
Packit 857059
	IN	const uint32	MaxSize,
Packit 857059
	IN	boolean			IsPageable )
Packit 857059
{
Packit 857059
	FSTATUS	Status;
Packit 857059
Packit 857059
	ASSERT( pBitVector );
Packit 857059
	ASSERT( GrowSize );
Packit 857059
Packit 857059
	BitVectorInitState( pBitVector );
Packit 857059
Packit 857059
	pBitVector->m_GrowSize = ROUNDUPP2(GrowSize, _BIT_VECTOR_ENTRY_SIZE);
Packit 857059
	pBitVector->m_MaxSize = (MaxSize == 0)? IB_UINT32_MAX : MaxSize;
Packit 857059
	pBitVector->m_Pageable = IsPageable;
Packit 857059
Packit 857059
	// get the storage needed by the user
Packit 857059
	Status = BitVectorSetSize( pBitVector, MIN(InitialSize, pBitVector->m_MaxSize) );
Packit 857059
Packit 857059
	return( Status );
Packit 857059
}
Packit 857059
Packit 857059
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
// BitVectorDestroy
Packit 857059
// 
Packit 857059
// Description:
Packit 857059
//	This function deallocates all allocated memory associated with the bit vector.
Packit 857059
//	The bit vector is left initialized to zero size.  This function does not fail.
Packit 857059
// 
Packit 857059
// Inputs:
Packit 857059
//	pBitVector - Pointer to bit vector
Packit 857059
// 
Packit 857059
// Outputs:
Packit 857059
//	None.
Packit 857059
// 
Packit 857059
// Returns:
Packit 857059
//	None.
Packit 857059
// 
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
void
Packit 857059
BitVectorDestroy(
Packit 857059
	IN	BIT_VECTOR* const	pBitVector )
Packit 857059
{
Packit 857059
	ASSERT( pBitVector );
Packit 857059
Packit 857059
	// Destroy the page bit vector.
Packit 857059
	if( pBitVector->m_pBitArray )
Packit 857059
	{
Packit 857059
		MemoryDeallocate( pBitVector->m_pBitArray );
Packit 857059
	}
Packit 857059
Packit 857059
	// reset internal state
Packit 857059
	pBitVector->m_Capacity = 0;
Packit 857059
	pBitVector->m_GrowSize = 0;
Packit 857059
	pBitVector->m_Size = 0;
Packit 857059
	pBitVector->m_pBitArray = NULL;
Packit 857059
Packit 857059
	return;
Packit 857059
}
Packit 857059
Packit 857059
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
// BitVectorAt
Packit 857059
// 
Packit 857059
// Description:
Packit 857059
//	This function returns the bit at the specified index.
Packit 857059
//	Range checking is performed.  Provides constant time access.
Packit 857059
// 
Packit 857059
// Inputs:
Packit 857059
//	pBitVector		- Pointer to bit vector.
Packit 857059
//	Index		- Index of bit to get.
Packit 857059
//	pValue	- Pointer to storage for the bit to be returned.
Packit 857059
// 
Packit 857059
// Outputs:
Packit 857059
//	pValue	- Copy of the desired bit.
Packit 857059
// 
Packit 857059
// Returns:
Packit 857059
//	FSUCCESS
Packit 857059
//	FINVALID_SETTING	Index out of range.
Packit 857059
// 
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
FSTATUS
Packit 857059
BitVectorAt(
Packit 857059
	IN	const BIT_VECTOR* const	pBitVector, 
Packit 857059
	IN	const uint32		Index,
Packit 857059
	OUT	uint8*				pValue )
Packit 857059
{
Packit 857059
	ASSERT( pBitVector );	// Other asserts are in BitVectorGet
Packit 857059
Packit 857059
	// Range check
Packit 857059
	if( Index >= pBitVector->m_Size )
Packit 857059
		return( FINVALID_PARAMETER );
Packit 857059
Packit 857059
	*pValue = BitVectorGet( pBitVector, Index );
Packit 857059
	return( FSUCCESS );
Packit 857059
}
Packit 857059
Packit 857059
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
// BitVectorSet
Packit 857059
// 
Packit 857059
// Description:
Packit 857059
//	This function sets the bit at the specified index.  The array grows as
Packit 857059
//	necessary.
Packit 857059
// 
Packit 857059
// Inputs:
Packit 857059
//	pBitVector		- Pointer to bit vector.
Packit 857059
//	Index		- Index of bit to get.
Packit 857059
//	Value		- value to set the bit to
Packit 857059
// 
Packit 857059
// Outputs:
Packit 857059
//	None.
Packit 857059
// 
Packit 857059
// Returns:
Packit 857059
//	FSUCCESS
Packit 857059
//	FINSUFFICIENT_MEMORY	The array could not be resized to accomodate the
Packit 857059
//							specified bit.
Packit 857059
//	FINSUFFICIENT_RESOURCES	- would grow vector beyond max size
Packit 857059
// 
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
FSTATUS 
Packit 857059
BitVectorSet(
Packit 857059
	IN	BIT_VECTOR* const	pBitVector, 
Packit 857059
	IN	const uint32	Index,
Packit 857059
	IN	const uint8		Value )
Packit 857059
{
Packit 857059
	FSTATUS	Status;
Packit 857059
Packit 857059
	ASSERT( pBitVector );
Packit 857059
Packit 857059
	// Determine if the bit vector has room for this bit.
Packit 857059
	if( Index >= pBitVector->m_Size )
Packit 857059
	{
Packit 857059
		// Resize to accomodate the given index.
Packit 857059
		Status = BitVectorSetSize( pBitVector, Index + 1 );
Packit 857059
Packit 857059
		// Check for failure on or before the given index.
Packit 857059
		if( (Status != FSUCCESS) && (pBitVector->m_Size <= Index) )
Packit 857059
			return( Status );
Packit 857059
		if (pBitVector->m_Size <= Index) {
Packit 857059
			return( FINSUFFICIENT_MEMORY );
Packit 857059
		}
Packit 857059
	}
Packit 857059
Packit 857059
	// At this point, the array is guaranteed to be big enough
Packit 857059
	if (Value)
Packit 857059
	{
Packit 857059
		pBitVector->m_pBitArray[_BitVectorSubscript(Index)] |= _BitVectorMask(Index);
Packit 857059
	} else {
Packit 857059
		pBitVector->m_pBitArray[_BitVectorSubscript(Index)] &= ~_BitVectorMask(Index);
Packit 857059
	}
Packit 857059
Packit 857059
	return( FSUCCESS );
Packit 857059
}
Packit 857059
Packit 857059
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
// BitVectorSetCapacity
Packit 857059
// 
Packit 857059
// Description:
Packit 857059
//	This function reserves capacity in the bit vector to the specified number of
Packit 857059
//	bits.  This function can only fail if the new capacity is larger than
Packit 857059
//	the old capacity.  If the new capacity is less than the old, no action
Packit 857059
//	is taken.  When growing the capacity, new bits will have value 0.
Packit 857059
// 
Packit 857059
// Inputs:
Packit 857059
//	pBitVector		- Pointer to bit vector
Packit 857059
//	NewCapacity	- Number of bits reserved in the array
Packit 857059
// 
Packit 857059
// Outputs:
Packit 857059
//	None.
Packit 857059
// 
Packit 857059
// Returns:
Packit 857059
//	FSUCCESS
Packit 857059
//	FINSUFFICIENT_MEMORY - bit vector is left unaltered
Packit 857059
// 
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
FSTATUS 
Packit 857059
BitVectorSetCapacity(
Packit 857059
	IN	BIT_VECTOR* const	pBitVector, 
Packit 857059
	IN	uint32				NewCapacity )
Packit 857059
{
Packit 857059
	unsigned	*pNewBitArray;
Packit 857059
Packit 857059
	ASSERT( pBitVector );
Packit 857059
Packit 857059
	if (NewCapacity > pBitVector->m_MaxSize)
Packit 857059
	{
Packit 857059
		NewCapacity = pBitVector->m_MaxSize;
Packit 857059
	}
Packit 857059
Packit 857059
	// Do we have to do anything here?
Packit 857059
	if( NewCapacity <= pBitVector->m_Capacity )
Packit 857059
	{
Packit 857059
		// Nope
Packit 857059
		return( FSUCCESS );
Packit 857059
	}
Packit 857059
Packit 857059
	// Allocate our bit array.
Packit 857059
	pNewBitArray = (unsigned*)MemoryAllocateAndClear( ((NewCapacity+_BIT_VECTOR_ENTRY_SIZE)/_BIT_VECTOR_ENTRY_SIZE) * sizeof( unsigned ), 
Packit 857059
		pBitVector->m_Pageable, VEC_MEM_TAG );
Packit 857059
	if( !pNewBitArray )
Packit 857059
		return( FINSUFFICIENT_MEMORY );
Packit 857059
Packit 857059
	if( pBitVector->m_pBitArray )
Packit 857059
	{
Packit 857059
		// Copy the old bit array into the new.
Packit 857059
		MemoryCopy( pNewBitArray, pBitVector->m_pBitArray, 
Packit 857059
			((pBitVector->m_Capacity+_BIT_VECTOR_ENTRY_SIZE)/_BIT_VECTOR_ENTRY_SIZE) * sizeof( unsigned ) );
Packit 857059
Packit 857059
		// Free the old bit array.
Packit 857059
		MemoryDeallocate( pBitVector->m_pBitArray );
Packit 857059
	}
Packit 857059
	
Packit 857059
	// Set the new array.
Packit 857059
	pBitVector->m_pBitArray = pNewBitArray;
Packit 857059
Packit 857059
	// Update the bit vector with the new capacity.
Packit 857059
	pBitVector->m_Capacity = NewCapacity;
Packit 857059
Packit 857059
	return( FSUCCESS );
Packit 857059
}
Packit 857059
Packit 857059
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
// BitVectorSetSize
Packit 857059
// 
Packit 857059
// Description:
Packit 857059
//	This function resizes the bit vector to the specified number of
Packit 857059
//	bits.  This function can only fail if the new size is larger than
Packit 857059
//	the old capacity.
Packit 857059
// 
Packit 857059
// Inputs:
Packit 857059
//	pBitVector	- Pointer to bit vector
Packit 857059
//	Size	- new number of bits in the the array
Packit 857059
// 
Packit 857059
// Outputs:
Packit 857059
//	None.
Packit 857059
// 
Packit 857059
// Returns:
Packit 857059
//	FSUCCESS
Packit 857059
//	FINSUFFICIENT_MEMORY	- bit vector will have at least as many bits
Packit 857059
//							as prior to the call.  Use BitVectorGetSize()
Packit 857059
//							to determine the number of bits
Packit 857059
//	FINSUFFICIENT_RESOURCES	- would grow vector beyond max size
Packit 857059
// 
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
FSTATUS 
Packit 857059
BitVectorSetSize(
Packit 857059
	IN	BIT_VECTOR* const	pBitVector, 
Packit 857059
	IN	const uint32	Size )
Packit 857059
{
Packit 857059
	FSTATUS	Status;
Packit 857059
	uint32	NewCapacity;
Packit 857059
Packit 857059
	ASSERT( pBitVector );
Packit 857059
Packit 857059
	if( Size == pBitVector->m_Size )
Packit 857059
		return( FSUCCESS );	// no change
Packit 857059
	if (Size > pBitVector->m_MaxSize)
Packit 857059
		return( FINSUFFICIENT_RESOURCES );
Packit 857059
Packit 857059
	// Determine if the bit vector has room.
Packit 857059
	if( Size >= pBitVector->m_Capacity )
Packit 857059
	{
Packit 857059
		// keep capacity as a multiple of GrowSize
Packit 857059
		NewCapacity = ROUNDUP(Size, pBitVector->m_GrowSize);
Packit 857059
		Status = BitVectorSetCapacity( pBitVector, NewCapacity );
Packit 857059
		if( Status != FSUCCESS )
Packit 857059
			return( Status );
Packit 857059
	}
Packit 857059
Packit 857059
	pBitVector->m_Size = Size;
Packit 857059
	return( FSUCCESS );
Packit 857059
}
Packit 857059
Packit 857059
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
// BitVectorSetMinSize
Packit 857059
// 
Packit 857059
// Description:
Packit 857059
//	This function resizes the bit vector to the specified number of
Packit 857059
//	bits only if the current number of bits in the array is fewer
Packit 857059
//	than the specified size.
Packit 857059
// 
Packit 857059
// Inputs:
Packit 857059
//	pBitVector	- Pointer to bit vector
Packit 857059
//	MinSize	- at least the number of bitbits needed in the array
Packit 857059
// 
Packit 857059
// Outputs:
Packit 857059
//	None.
Packit 857059
// 
Packit 857059
// Returns:
Packit 857059
//	FSUCCESS
Packit 857059
//	FINSUFFICIENT_MEMORY - bit vector is left unaltered
Packit 857059
// 
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
FSTATUS BitVectorSetMinSize(
Packit 857059
	IN	BIT_VECTOR* const	pBitVector, 
Packit 857059
	IN	const uint32	MinSize )
Packit 857059
{
Packit 857059
	ASSERT( pBitVector );
Packit 857059
Packit 857059
	if( MinSize > pBitVector->m_Size )
Packit 857059
	{
Packit 857059
		// We have to resize the array
Packit 857059
		return( BitVectorSetSize( pBitVector, MinSize ) );
Packit 857059
	}
Packit 857059
Packit 857059
	// We didn't have to do anything
Packit 857059
	return( FSUCCESS );
Packit 857059
}
Packit 857059
Packit 857059
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
// BitVectorApplyFunc
Packit 857059
// 
Packit 857059
// Description:
Packit 857059
//	This function calls the user supplied function for each item in the bit vector.
Packit 857059
// 
Packit 857059
//	The called function has the form:
Packit 857059
//		void ApplyFunc( uint32 Index, uint8 Value, void *Context );
Packit 857059
//	where:
Packit 857059
//		Index = index of this bit
Packit 857059
//		Value = value of bit at this Index in the array
Packit 857059
//		Context = user supplied context
Packit 857059
// 
Packit 857059
// Inputs:
Packit 857059
//	pBitVector		- pointer to bit vector to iterate through
Packit 857059
//	pfnCallback	- callback called for each non-NULL bit
Packit 857059
//	Context		- context to pass to callback function
Packit 857059
// 
Packit 857059
// Outputs:
Packit 857059
//	None.
Packit 857059
// 
Packit 857059
// Returns:
Packit 857059
//	None.
Packit 857059
// 
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
void 
Packit 857059
BitVectorApplyFunc(
Packit 857059
	IN	const BIT_VECTOR* const	pBitVector, 
Packit 857059
	IN	BITVEC_APPLY_FUNC	pfnCallback,
Packit 857059
	IN	void* const			Context )
Packit 857059
{
Packit 857059
	return BitVectorApplyFuncRange(pBitVector, pfnCallback, Context,
Packit 857059
									0, pBitVector->m_Size);
Packit 857059
}
Packit 857059
Packit 857059
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
// BitVectorApplyFuncRange
Packit 857059
// 
Packit 857059
// Description:
Packit 857059
//	This function calls the user supplied function for each item in the bit vector
Packit 857059
//	across the given range of indexes of the bit vector.
Packit 857059
// 
Packit 857059
//	The called function has the form:
Packit 857059
//		void ApplyFunc( uint32 Index, uint8 Value, void *Context );
Packit 857059
//	where:
Packit 857059
//		Index = index of this bit
Packit 857059
//		Value = value of bit at this Index in the array
Packit 857059
//		Context = user supplied context
Packit 857059
// 
Packit 857059
// Inputs:
Packit 857059
//	pBitVector		- pointer to bit vector to iterate through
Packit 857059
//	pfnCallback	- callback called for each non-NULL bit
Packit 857059
//	Context		- context to pass to callback function
Packit 857059
//	StartIndex		- Index to start at
Packit 857059
//	EndIndexP1		- Index to stop at (exclusive)
Packit 857059
// 
Packit 857059
// Outputs:
Packit 857059
//	None.
Packit 857059
// 
Packit 857059
// Returns:
Packit 857059
//	None.
Packit 857059
// 
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
void 
Packit 857059
BitVectorApplyFuncRange(
Packit 857059
	IN	const BIT_VECTOR* const	pBitVector, 
Packit 857059
	IN	BITVEC_APPLY_FUNC	pfnCallback,
Packit 857059
	IN	void* const			Context,
Packit 857059
	IN	uint32				StartIndex,
Packit 857059
	IN	uint32				EndIndexP1 )
Packit 857059
{
Packit 857059
	uint32	i;
Packit 857059
	uint8 Value;
Packit 857059
Packit 857059
	ASSERT( pBitVector );
Packit 857059
	ASSERT( pfnCallback );
Packit 857059
Packit 857059
	i  = StartIndex;
Packit 857059
	if (EndIndexP1 > pBitVector->m_Size)
Packit 857059
		EndIndexP1 = pBitVector->m_Size;
Packit 857059
	for( ; i < EndIndexP1; ++i )
Packit 857059
	{
Packit 857059
		Value = BitVectorGet( pBitVector, i );
Packit 857059
		pfnCallback( i, Value, Context );
Packit 857059
	}
Packit 857059
}
Packit 857059
Packit 857059
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
// BitVectorApplyFuncSelected
Packit 857059
// 
Packit 857059
// Description:
Packit 857059
//	This function calls the user supplied function for each bit in the bit vector,
Packit 857059
//	which matches Value, starting from the beginning of the array.
Packit 857059
// 
Packit 857059
//	The called function has the form:
Packit 857059
//		void ApplyFunc( uint32 Index, uint8 Value, void *Context );
Packit 857059
//	where:
Packit 857059
//		Index = index of this bit
Packit 857059
//		Value = value of bit at this Index in the array
Packit 857059
//		Context = user supplied context
Packit 857059
// 
Packit 857059
// Inputs:
Packit 857059
//	pBitVector		- pointer to bit vector to iterate through
Packit 857059
//	pfnCallback	- callback called for each non-NULL bit
Packit 857059
//	Context		- context to pass to callback function
Packit 857059
//	Value		- Bit values to execute pfnCallback for
Packit 857059
// 
Packit 857059
// Outputs:
Packit 857059
//	None.
Packit 857059
// 
Packit 857059
// Returns:
Packit 857059
//	None.
Packit 857059
// 
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
void 
Packit 857059
BitVectorApplyFuncSelected(
Packit 857059
	IN	const BIT_VECTOR* const	pBitVector, 
Packit 857059
	IN	BITVEC_APPLY_FUNC	pfnCallback,
Packit 857059
	IN	void* const			Context,
Packit 857059
	IN	uint8				Value )
Packit 857059
{
Packit 857059
	return BitVectorApplyFuncSelectedRange(pBitVector, pfnCallback, Context,
Packit 857059
						Value, 0, pBitVector->m_Size);
Packit 857059
}
Packit 857059
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
// BitVectorApplyFuncSelectedRange
Packit 857059
// 
Packit 857059
// Description:
Packit 857059
//	This function calls the user supplied function for each bit in the bit vector,
Packit 857059
//	across the given range of indexes of the bit vector,
Packit 857059
//	which matches Value, starting from the beginning of the array.
Packit 857059
// 
Packit 857059
//	The called function has the form:
Packit 857059
//		void ApplyFunc( uint32 Index, uint8 Value, void *Context );
Packit 857059
//	where:
Packit 857059
//		Index = index of this bit
Packit 857059
//		Value = value of bit at this Index in the array
Packit 857059
//		Context = user supplied context
Packit 857059
// 
Packit 857059
// Inputs:
Packit 857059
//	pBitVector		- pointer to bit vector to iterate through
Packit 857059
//	pfnCallback	- callback called for each non-NULL bit
Packit 857059
//	Context		- context to pass to callback function
Packit 857059
//	Value		- Bit values to execute pfnCallback for
Packit 857059
//	StartIndex		- Index to start at
Packit 857059
//	EndIndexP1		- Index to stop at (exclusive)
Packit 857059
// 
Packit 857059
// Outputs:
Packit 857059
//	None.
Packit 857059
// 
Packit 857059
// Returns:
Packit 857059
//	None.
Packit 857059
// 
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
void 
Packit 857059
BitVectorApplyFuncSelectedRange(
Packit 857059
	IN	const BIT_VECTOR* const	pBitVector, 
Packit 857059
	IN	BITVEC_APPLY_FUNC	pfnCallback,
Packit 857059
	IN	void* const			Context,
Packit 857059
	IN	uint8				Value,
Packit 857059
	IN	uint32				StartIndex,
Packit 857059
	IN	uint32				EndIndexP1 )
Packit 857059
{
Packit 857059
	uint32	i;
Packit 857059
	uint8 Val;
Packit 857059
Packit 857059
	ASSERT( pBitVector );
Packit 857059
	ASSERT( pfnCallback );
Packit 857059
Packit 857059
	i  = StartIndex;
Packit 857059
	if (EndIndexP1 > pBitVector->m_Size)
Packit 857059
		EndIndexP1 = pBitVector->m_Size;
Packit 857059
	for( ; i < EndIndexP1; ++i )
Packit 857059
	{
Packit 857059
		Val = BitVectorGet( pBitVector, i );
Packit 857059
		if (Value == Val)
Packit 857059
			pfnCallback( i, Value, Context );
Packit 857059
	}
Packit 857059
}
Packit 857059
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
// BitVectorFindFromStart
Packit 857059
// 
Packit 857059
// Description:
Packit 857059
//	This function searches the Bit Vector for the given value
Packit 857059
//	starting from the beginning of the bit vector, until a bit matching
Packit 857059
//	Value is found
Packit 857059
// 
Packit 857059
// Inputs:
Packit 857059
//	pBitVector		- pointer to bit vector to iterate through
Packit 857059
//	Value			- bit value to find
Packit 857059
// 
Packit 857059
// Outputs:
Packit 857059
//	None.
Packit 857059
// 
Packit 857059
// Returns:
Packit 857059
//	Index value where the first bit with the given value was found.
Packit 857059
//	If the callback given value was never found,
Packit 857059
//	then the return value = the size of the bit vector.
Packit 857059
// 
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
uint32 
Packit 857059
BitVectorFindFromStart(
Packit 857059
	IN	const BIT_VECTOR* const	pBitVector, 
Packit 857059
	IN	uint8				Value )
Packit 857059
{
Packit 857059
	return BitVectorFindRange(pBitVector, Value, 0, pBitVector->m_Size);
Packit 857059
}
Packit 857059
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
// BitVectorFindFromIndex
Packit 857059
// 
Packit 857059
// Description:
Packit 857059
//	This function searches the Bit Vector for the given value
Packit 857059
//	starting from the given index of the bit vector, until a bit matching
Packit 857059
//	Value is found.  Search proceeds forward (increasing indexes).
Packit 857059
// 
Packit 857059
// Inputs:
Packit 857059
//	pBitVector		- pointer to bit vector to iterate through
Packit 857059
//	Value			- bit value to find
Packit 857059
//	Index			- Index to start at
Packit 857059
// 
Packit 857059
// Outputs:
Packit 857059
//	None.
Packit 857059
// 
Packit 857059
// Returns:
Packit 857059
//	Index value where the first bit with the given value was found.
Packit 857059
//	If the given value was never found,
Packit 857059
//	then the return value = the size of the bit vector.
Packit 857059
// 
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
uint32 
Packit 857059
BitVectorFindFromIndex(
Packit 857059
	IN	const BIT_VECTOR* const	pBitVector, 
Packit 857059
	IN	uint8				Value,
Packit 857059
	IN	uint32				Index )
Packit 857059
{
Packit 857059
	return BitVectorFindRange(pBitVector, Value, Index, pBitVector->m_Size);
Packit 857059
}
Packit 857059
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
// BitVectorFindRange
Packit 857059
// 
Packit 857059
// Description:
Packit 857059
//	This function searches the Bit Vector for the given value
Packit 857059
//	across the given range of indexes of the bit vector, until a bit matching
Packit 857059
//	Value is found.  Search proceeds forward (increasing indexes).
Packit 857059
// 
Packit 857059
// Inputs:
Packit 857059
//	pBitVector		- pointer to bit vector to iterate through
Packit 857059
//	Value			- bit value to find
Packit 857059
//	StartIndex		- Index to start at
Packit 857059
//	EndIndexP1		- Index to stop at (exclusive)
Packit 857059
// 
Packit 857059
// Outputs:
Packit 857059
//	None.
Packit 857059
// 
Packit 857059
// Returns:
Packit 857059
//	Index value where the first bit with the given value was found.
Packit 857059
//	If the given value was never found,
Packit 857059
//	then the return value = EndIndexP1
Packit 857059
// 
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
uint32 
Packit 857059
BitVectorFindRange(
Packit 857059
	IN	const BIT_VECTOR* const	pBitVector, 
Packit 857059
	IN	uint8				Value,
Packit 857059
	IN	uint32				StartIndex,
Packit 857059
	IN	uint32				EndIndexP1 )
Packit 857059
{
Packit 857059
	uint32	i;
Packit 857059
	uint32 *pEntry;
Packit 857059
	uint32 mask;
Packit 857059
	uint32 inc;
Packit 857059
Packit 857059
	ASSERT( pBitVector );
Packit 857059
Packit 857059
	// for speed we unroll the Value test and do 32 bits at a time
Packit 857059
	i  = StartIndex;
Packit 857059
	if (EndIndexP1 > pBitVector->m_Size)
Packit 857059
		EndIndexP1 = pBitVector->m_Size;
Packit 857059
	pEntry = &pBitVector->m_pBitArray[_BitVectorSubscript(i)];
Packit 857059
	// First word is special case with smaller mask and increment
Packit 857059
	inc = _BIT_VECTOR_ENTRY_SIZE-_BitVectorMaskShift(i);
Packit 857059
	mask = ~0<<_BitVectorMaskShift(i);
Packit 857059
	if (Value)
Packit 857059
	{
Packit 857059
		while(i < EndIndexP1)
Packit 857059
		{
Packit 857059
			// expect optimizes the looping case
Packit 857059
			if (IB_EXPECT_FALSE((*pEntry & mask) != 0))
Packit 857059
			{
Packit 857059
				// this is the entry with our bit
Packit 857059
				while(i < EndIndexP1)
Packit 857059
				{
Packit 857059
					if (*pEntry & _BitVectorMask(i))
Packit 857059
						goto done;
Packit 857059
					i++;
Packit 857059
				}
Packit 857059
				goto done;
Packit 857059
			}
Packit 857059
			++pEntry;
Packit 857059
			i+=inc;
Packit 857059
			inc = _BIT_VECTOR_ENTRY_SIZE;
Packit 857059
			mask = ~0;
Packit 857059
		}
Packit 857059
	} else {
Packit 857059
		while(i < EndIndexP1)
Packit 857059
		{
Packit 857059
			// expect optimizes the looping case
Packit 857059
			if (IB_EXPECT_FALSE((*pEntry & mask) != mask))
Packit 857059
			{
Packit 857059
				// this is the entry with our bit
Packit 857059
				while(i < EndIndexP1)
Packit 857059
				{
Packit 857059
					if (0 == (*pEntry & _BitVectorMask(i)))
Packit 857059
						goto done;
Packit 857059
					i++;
Packit 857059
				}
Packit 857059
				goto done;
Packit 857059
			}
Packit 857059
			++pEntry;
Packit 857059
			i+=inc;
Packit 857059
			inc = _BIT_VECTOR_ENTRY_SIZE;
Packit 857059
			mask = ~0;
Packit 857059
		}
Packit 857059
	}
Packit 857059
done:
Packit 857059
	// In case EndIndexP1 is not a multiple of 32, and we over incremented in the outer loop
Packit 857059
	if (i > EndIndexP1) i = EndIndexP1;
Packit 857059
Packit 857059
	DEBUG_ASSERT((EndIndexP1 == i) || (Value && BitVectorGet(pBitVector, i)) || (!Value && !BitVectorGet(pBitVector, i)));
Packit 857059
	return( i );
Packit 857059
}
Packit 857059
Packit 857059
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
// BitVectorFindFromEnd
Packit 857059
// 
Packit 857059
// Description:
Packit 857059
//	This function searches the Bit Vector for the given value
Packit 857059
//	starting from the end of the bit vector, until a bit matching
Packit 857059
//	Value is found
Packit 857059
// 
Packit 857059
// Inputs:
Packit 857059
//	pBitVector		- pointer to bit vector to iterate through
Packit 857059
//	Value			- bit value to find
Packit 857059
// 
Packit 857059
// Outputs:
Packit 857059
//	None.
Packit 857059
// 
Packit 857059
// Returns:
Packit 857059
//	Index value where the first bit with the given value was found.
Packit 857059
//	If the callback given value was never found,
Packit 857059
//	then the return value = the size of the bit vector.
Packit 857059
// 
Packit 857059
///////////////////////////////////////////////////////////////////////////////
Packit 857059
uint32 
Packit 857059
BitVectorFindFromEnd(
Packit 857059
	IN	const BIT_VECTOR* const	pBitVector, 
Packit 857059
	IN	uint8				Value )
Packit 857059
{
Packit 857059
	uint32	i;
Packit 857059
	uint32 *pEntry;
Packit 857059
Packit 857059
	ASSERT( pBitVector );
Packit 857059
Packit 857059
	// for speed we unroll the Value test and do 32 bits at a time
Packit 857059
	i  = pBitVector->m_Size;
Packit 857059
	pEntry = &pBitVector->m_pBitArray[_BitVectorSubscript(i)];
Packit 857059
	if (Value)
Packit 857059
	{
Packit 857059
		for( ; i; i-=32, --pEntry)
Packit 857059
		{
Packit 857059
			// expect optimizes the looping case
Packit 857059
			if (IB_EXPECT_FALSE(*pEntry))
Packit 857059
			{
Packit 857059
				// this is the entry with our bit
Packit 857059
				for (; i; --i)
Packit 857059
				{
Packit 857059
					if (*pEntry & _BitVectorMask(i))
Packit 857059
						goto found;
Packit 857059
				}
Packit 857059
				goto notfound;
Packit 857059
			}
Packit 857059
		}
Packit 857059
	} else {
Packit 857059
		for( ; i; i-=32, --pEntry)
Packit 857059
		{
Packit 857059
			// expect optimizes the looping case
Packit 857059
			if (IB_EXPECT_FALSE(*pEntry != 0xffffffff))
Packit 857059
			{
Packit 857059
				// this is the entry with our bit
Packit 857059
				for (; i; --i)
Packit 857059
				{
Packit 857059
					if (0 == (*pEntry & _BitVectorMask(i)))
Packit 857059
						goto found;
Packit 857059
				}
Packit 857059
				goto notfound;
Packit 857059
			}
Packit 857059
		}
Packit 857059
	}
Packit 857059
notfound:
Packit 857059
	return (pBitVector->m_Size);
Packit 857059
Packit 857059
found:
Packit 857059
	return( i );
Packit 857059
}