windows-nt/Source/XPSP1/NT/inetsrv/query/cindex/bitstm.cxx
2020-09-26 16:20:57 +08:00

1054 lines
28 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1991 - 2000.
//
// File: BITSTM.cxx
//
// Contents: 'Bit Stream'
//
// Classes: CBitBuffer
//
// Classes: CBitStream, CWBitStream, CRBitStream
//
// History: 03-Jul-91 KyleP Created
// 24-Aug-92 BartoszM Rewrote it
//
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#pragma optimize( "t", on )
#include "bitstm.hxx"
//+---------------------------------------------------------------------------
//
// Member: CSmartBuffer::CSmartBuffer, public
//
// Synopsis: Constructor.
//
// Arguments: [phStorage] -- Physical index -- source of pages
// [mode] -- Access mode for the index
//
// History: 02-Sep-92 BartoszM Created
//
//----------------------------------------------------------------------------
CSmartBuffer::CSmartBuffer ( CPhysStorage& phStorage, EAccessMode mode )
: _phStorage(phStorage),
_pBuffer(0),
_fWritable( mode == eWriteExisting )
{
}
//+---------------------------------------------------------------------------
//
// Member: CSmartBuffer::CSmartBuffer, public
//
// Synopsis: Constructor.
//
// Arguments: [phStorage] -- Physical index -- source of pages
// [fCreate] -- Indicates if new buffer is needed
//
// History: 02-Sep-92 BartoszM Created
//
//----------------------------------------------------------------------------
CSmartBuffer::CSmartBuffer ( CPhysStorage& phStorage, BOOL fCreate )
: _phStorage(phStorage),
_numPage(0),
_fWritable(fCreate)
{
if (fCreate)
{
_pBuffer = _phStorage.BorrowNewBuffer(0);
IncrementSig();
#if CIDBG == 1
CheckCorruption();
#endif
}
else
{
_pBuffer = _phStorage.BorrowBuffer( 0, _fWritable, _fWritable );
CheckCorruption();
}
}
//+---------------------------------------------------------------------------
//
// Member: CSmartBuffer::CSmartBuffer, public
//
// Synopsis: Constructor.
//
// Arguments: [phStorage] -- Physical index -- source of pages
// [numPage] -- Page to encapsulate
// [mode] -- Access mode for the index
// [fIncrSig] -- Indicates if page should be signed
//
// History: 02-Sep-92 BartoszM Created
//
//----------------------------------------------------------------------------
CSmartBuffer::CSmartBuffer ( CPhysStorage& phStorage,
ULONG numPage,
EAccessMode mode,
BOOL fIncrSig )
: _phStorage(phStorage),
_numPage(numPage),
_fWritable(mode == eWriteExisting)
{
_pBuffer = _phStorage.BorrowBuffer( _numPage, _fWritable, _fWritable );
if ( _fWritable && fIncrSig )
IncrementSig();
if (fIncrSig)
CheckCorruption();
}
//+---------------------------------------------------------------------------
//
// Member: CSmartBuffer::CSmartBuffer, public
//
// Synopsis: Constructor.
//
// Arguments: [buf] -- Source CSmartBuffer
// [numPage] -- Page to acquire
//
// History: 02-Sep-92 BartoszM Created
//
//----------------------------------------------------------------------------
CSmartBuffer::CSmartBuffer ( CSmartBuffer& buf, ULONG numPage )
: _phStorage(buf._phStorage),
_numPage(numPage),
_fWritable(buf._fWritable)
{
_pBuffer = _phStorage.BorrowBuffer( _numPage, _fWritable, _fWritable );
if ( _fWritable )
IncrementSig();
CheckCorruption();
}
//+---------------------------------------------------------------------------
//
// Member: CSmartBuffer::~CSmartBuffer, public
//
// Synopsis: Destructor.
//
// History: 02-Sep-92 BartoszM Created
//
//----------------------------------------------------------------------------
CSmartBuffer::~CSmartBuffer ()
{
if ( 0 != _pBuffer )
{
// If a writable buffer still exists in this destructor we're in a
// failure path that must not THROW. Anything that really needs to
// be on disk should already be there by now, so this code path
// won't throw if it can't flush.
//
// If you see this debugout and you're not unwinding an exception,
// your code is broken.
// If a merge fails and you get this debugout, it's not a problem
//
if ( _fWritable && _phStorage.RequiresFlush( _numPage ) )
{
IncrementSig();
ciDebugOut(( DEB_WARN, "deleting writable buffer in potential "
"unwind path -- it may not get flushed\n" ));
}
_phStorage.ReturnBuffer( _numPage, _fWritable, FALSE );
}
}
//+---------------------------------------------------------------------------
//
// Member: CSmartBuffer::CheckCorruption, private
//
// Synopsis: Attempts to determine if the entire page wasn't written
// to disk.
//
// History: ? KyleP Created
//
//----------------------------------------------------------------------------
void CSmartBuffer::CheckCorruption()
{
if ( 0 == _pBuffer[0] ||
_pBuffer[0] != _pBuffer[SMARTBUF_PAGE_SIZE_IN_DWORDS + 1] )
{
ciDebugOut(( DEB_ERROR, "Buffer at 0x%x corrupt (StartDword = 0x%x, EndDword = 0x%x)\n",
_pBuffer, _pBuffer[0], _pBuffer[SMARTBUF_PAGE_SIZE_IN_DWORDS + 1] ));
Win4Assert( !"Index corruption." );
_phStorage.GetStorage().ReportCorruptComponent( ( 0 == _pBuffer[0] ) ?
L"SmartBuffer1" :
L"SmartBuffer2");
THROW( CException( CI_CORRUPT_DATABASE ) );
}
}
//+---------------------------------------------------------------------------
//
// Member: CSmartBuffer::IncrementSig, private
//
// Synopsis: Increments the signature at the start and end of the page.
//
// History: ? KyleP Created
//
//----------------------------------------------------------------------------
void CSmartBuffer::IncrementSig()
{
Win4Assert( _pBuffer[0] == _pBuffer[SMARTBUF_PAGE_SIZE_IN_DWORDS + 1] );
_pBuffer[0]++;
_pBuffer[SMARTBUF_PAGE_SIZE_IN_DWORDS + 1]++;
}
//+---------------------------------------------------------------------------
//
// Member: CSmartBuffer::InitSignature, public
//
// Synopsis: Initializes the signature at the start and end of the page.
//
// History: ? KyleP Created
//
//----------------------------------------------------------------------------
void CSmartBuffer::InitSignature()
{
_pBuffer[0] = _pBuffer[SMARTBUF_PAGE_SIZE_IN_DWORDS + 1] = 1;
}
//+---------------------------------------------------------------------------
//
// Member: CSmartBuffer::Refill, public
//
// Synopsis: Makes sure the given page is borrowed and ready to go
//
// Arguments: [numPage] -- The page requested
//
// History: 11/6/98 dlee Added Header
//
//----------------------------------------------------------------------------
void CSmartBuffer::Refill( ULONG numPage )
{
if ( 0 != _pBuffer &&
_fWritable &&
_phStorage.RequiresFlush( _numPage ) )
{
IncrementSig();
}
// first borrow next, then return previous to avoid reloading
ULONG * pOld = _pBuffer;
unsigned numOldPage = _numPage;
_pBuffer = _phStorage.BorrowBuffer( numPage, _fWritable, _fWritable );
_numPage = numPage;
if ( 0 != pOld )
_phStorage.ReturnBuffer( numOldPage, _fWritable );
Win4Assert( 0 != _pBuffer );
// increment signature
if ( _fWritable )
IncrementSig();
CheckCorruption();
}
//+---------------------------------------------------------------------------
//
// Member: CSmartBuffer::Next, public
//
// Synopsis: Makes sure the next page is borrowed and ready to go
//
// History: 11/6/98 dlee Added Header
//
//----------------------------------------------------------------------------
ULONG* CSmartBuffer::Next()
{
Win4Assert( 0 != _pBuffer );
if ( 0 != _pBuffer &&
_fWritable &&
_phStorage.RequiresFlush( _numPage ) )
IncrementSig();
ULONG * pOld = _pBuffer;
// first borrow next, then return previous to avoid reloading
_pBuffer = _phStorage.BorrowBuffer( _numPage+1, _fWritable, _fWritable );
_numPage++;
if ( 0 != pOld )
_phStorage.ReturnBuffer( _numPage-1, _fWritable );
Win4Assert( 0 != _pBuffer );
if ( _fWritable )
IncrementSig();
CheckCorruption();
return _pBuffer + 1;
}
//+---------------------------------------------------------------------------
//
// Member: CSmartBuffer::NextNew, public
//
// Synopsis: Makes sure the next page is borrowed and ready to go
//
// History: 11/6/98 dlee Added Header
//
//----------------------------------------------------------------------------
ULONG* CSmartBuffer::NextNew()
{
Win4Assert( 0 != _pBuffer );
if ( _fWritable && _phStorage.RequiresFlush( _numPage ) )
IncrementSig();
// first borrow next, then return previous to avoid reloading
_pBuffer = _phStorage.BorrowNewBuffer(_numPage+1);
_numPage++;
Win4Assert ( _pBuffer != 0 );
_phStorage.ReturnBuffer( _numPage-1, _fWritable );
if ( _fWritable )
IncrementSig();
#if CIDBG == 1
CheckCorruption();
#endif
return _pBuffer + 1;
}
//+---------------------------------------------------------------------------
//
// Member: CSmartBuffer::Free, public
//
// Synopsis: Frees the current page if and only if the underlying storage
// is writable. Useful for master merges where we want to
// unmap the old master index so it can be made sparse.
//
// History: 11/6/98 dlee Added Header
//
//----------------------------------------------------------------------------
void CSmartBuffer::Free()
{
//
// Only free the buffer if the stream (not necessarily the buffer)
// is writable, so the stream can be shrunk from the front during a
// master merge.
//
Win4Assert( _phStorage.IsWritable() );
if ( 0 != _pBuffer )
{
if ( _fWritable && _phStorage.RequiresFlush( _numPage ) )
IncrementSig();
_phStorage.ReturnBuffer( _numPage, _fWritable );
_pBuffer = 0;
}
}
//+---------------------------------------------------------------------------
//
// Member: CBitStream::CBitStream, public
//
// Synopsis: Constructor. Does not load pages.
//
// Arguments: [physIndex] -- Physical index -- source of pages
//
// History: 02-Sep-92 BartoszM Created
//
//----------------------------------------------------------------------------
CBitStream::CBitStream(CPhysStorage& phStorage, CSmartBuffer::EAccessMode mode )
: _buffer(phStorage, mode),
_oBuffer( 0 )
{
}
//+---------------------------------------------------------------------------
//
// Member: CPBitStream::CPBitStream, public
//
// Synopsis: Constructor. Does not load any pages.
//
// Arguments: [physIndex] -- Physical index -- source of pages
//
// History: 02-Sep-92 BartoszM Created
//
//----------------------------------------------------------------------------
CPBitStream::CPBitStream(CPhysStorage& phStorage)
: CBitStream ( phStorage, CSmartBuffer::eWriteExisting )
{
_bitOff.SetPage(0);
_bitOff.SetOff(0);
ciDebugOut (( DEB_BITSTM, "CPBitStream::CPBitStream\n" ));
}
//+---------------------------------------------------------------------------
//
// Member: CBitStream::CBitStream, public
//
// Synopsis: Constructor. Starts at the beginning of index
//
// Arguments: [physIndex] -- Physical index -- source of pages
//
// History: 08-Jul-91 KyleP Created.
//
//----------------------------------------------------------------------------
CBitStream::CBitStream(CPhysStorage& phStorage, BOOL fCreate)
: _buffer(phStorage, fCreate),
_oBuffer( 0 )
{
ciDebugOut (( DEB_BITSTM, "CBitStream::CBitStream\n" ));
_pCurPos = _buffer.Get();
_pEndBuf = _pCurPos + SMARTBUF_PAGE_SIZE_IN_DWORDS;
_cbitLeftDW = ULONG_BITS;
}
//+---------------------------------------------------------------------------
//
// Member: CBitStream::CBitStream, public
//
// Synopsis: Constructor. Seek to a specified position.
//
// Arguments: [physIndex] -- Physical index -- source of pages
// [off] -- starting bit offset
// [mode] -- Check access mode
// [fIncrSig] -- Indicates if signature has to be incremented.
//
// History: 08-Jul-91 KyleP Created.
//
//----------------------------------------------------------------------------
CBitStream::CBitStream(CPhysStorage& phStorage,
const BitOffset& off,
CSmartBuffer::EAccessMode mode,
BOOL fIncrSig )
: _buffer(phStorage, off.Page(), mode, fIncrSig),
_oBuffer( 0 )
{
ciDebugOut(( DEB_BITSTM, "CBitStream::CBitStream %d:%d\n",
off.Page(), off.Offset() ));
SetPosition(off.Offset());
}
//+---------------------------------------------------------------------------
//
// Member: CBitStream::LoadNextPage, private
//
// Synopsis: Loads next page, positions stream at its beginning
//
// Requires: Page must already exits
//
// History: 28-Aug-92 BartoszM Created.
//
//----------------------------------------------------------------------------
void CBitStream::LoadNextPage()
{
_pCurPos = _buffer.Next();
_pEndBuf = _pCurPos + SMARTBUF_PAGE_SIZE_IN_DWORDS;
_cbitLeftDW = ULONG_BITS;
}
//+---------------------------------------------------------------------------
//
// Member: CBitStream::LoadNewPage, private
//
// Synopsis: Creates and loads new page following the current one
// Positions stream at its beginning
//
// History: 28-Aug-92 BartoszM Created.
//
// Notice: Page should be zero filled
//
//----------------------------------------------------------------------------
void CBitStream::LoadNewPage()
{
_pCurPos = _buffer.NextNew();
_pEndBuf = _pCurPos + SMARTBUF_PAGE_SIZE_IN_DWORDS;
_cbitLeftDW = ULONG_BITS;
#if CIDBG == 1
ULONG* p = _buffer.Get();
for (int i=0; i < SMARTBUF_PAGE_SIZE_IN_DWORDS; i++)
if (p[i] != 0)
break;
Win4Assert(i == SMARTBUF_PAGE_SIZE_IN_DWORDS);
#endif
}
//+---------------------------------------------------------------------------
//
// Function: Refill
//
// Synopsis: Invalidates the currently cached copy and gets a new
// copy of the buffer. This is needed during master merge
// because we unmap the buffer before flushing and it is
// possible that the re-mapped buffer may be in a physically
// different location.
//
// History: 4-20-94 srikants Created
//
// Notes:
//
//----------------------------------------------------------------------------
void CBitStream::Refill()
{
BitOffset bitOff;
GetOffset(bitOff);
_buffer.Refill(bitOff.Page());
SetPosition( bitOff.Offset() );
}
//+---------------------------------------------------------------------------
//
// Member: CBitStream::SetPosition, private
//
// Synopsis: Set bit position within a freshly loaded page
//
// Arguments: [off] -- number of bits to skip
//
// History: 28-Aug-92 BartoszM Created.
//
//----------------------------------------------------------------------------
void CBitStream::SetPosition(ULONG off)
{
Win4Assert( off < SMARTBUF_PAGE_SIZE_IN_BITS );
Win4Assert( !_buffer.isEmpty() );
//ciDebugOut (( DEB_BITSTM, "SetPosition %d\n", off ));
_pCurPos = _buffer.Get() + off / ULONG_BITS;
_pEndBuf = _buffer.Get() + SMARTBUF_PAGE_SIZE_IN_DWORDS;
_cbitLeftDW = ULONG_BITS - ( off - ULONG_BITS * ( off / ULONG_BITS ) );
Win4Assert ( Position() == off );
}
//+---------------------------------------------------------------------------
//
// Member: CBitStream::CBitStream, public
//
// Synopsis: Copy Constructor (with pb as a clone of _pBuffer).
//
// Arguments: [pb] -- Pointer to memory for buffer.
//
// [orig] -- Original CBitStream to be copied.
//
// History: 13-Jan-92 AmyA Created.
//
//----------------------------------------------------------------------------
CBitStream::CBitStream(CBitStream & orig)
: _buffer(orig._buffer, orig._buffer.PageNum()),
_cbitLeftDW(orig._cbitLeftDW),
_oBuffer( 0 )
{
_pCurPos = _buffer.Get() + ( orig._pCurPos - orig._buffer.Get() );
_pEndBuf = _buffer.Get() + SMARTBUF_PAGE_SIZE_IN_DWORDS;
}
//+---------------------------------------------------------------------------
//
// Member: CPBitStream::OverwriteBits, public
//
// Synopsis: Store bits in the buffer. This call doesn't affect
// surrounding bits.
//
// Effects: OR the [cb] low bits in [ul] beginning at the 'bit-cursor'
//
// Arguments: [ul] -- A DWord containing data to store.
//
// [cb] -- The number of bits to store.
//
// History: 18-Jul-91 KyleP Created.
// 02-Sep-92 BartoszM Rewrote for lazy paging
//
// Notes: Bits are stored 'big-endian'.
//
//----------------------------------------------------------------------------
void CPBitStream::OverwriteBits(ULONG ul, unsigned cb)
{
ciDebugOut (( DEB_BITSTM , "OverwriteBits %d\n", cb ));
Win4Assert(cb != 0 && cb <= ULONG_BITS);
// Fault in the page if necessary
if ( _buffer.isEmpty() || _buffer.PageNum() != _bitOff.Page())
{
_buffer.Refill(_bitOff.Page());
}
SetPosition(_bitOff.Offset());
//
// The easy case is the one where all the data fits in the current dword
//
if (cb <= _cbitLeftDW)
{
// this much will be left after current write
_cbitLeftDW -= cb;
// zero out a segment within current dword
// first create a mask of cb bits by (ULONG_BITS - cb) shift right
// then shift this mask left by the number of bits to be left
*_pCurPos &= ~((0xFFFFFFFF >> (ULONG_BITS - cb)) << _cbitLeftDW);
// shift ul left by the number of bits to be left
*_pCurPos |= (ul << _cbitLeftDW);
// prepare for the next write
_bitOff += cb;
Win4Assert( _bitOff.Offset() < SMARTBUF_PAGE_SIZE_IN_BITS );
}
else
{
IOverwriteBits( ul, cb );
}
}
//+---------------------------------------------------------------------------
//
// Member: CWBitStream::IPutBits, private
//
// Synopsis: Store bits in the buffer. Internal version for multi-dword
// case.
//
// Effects: Store the [cb] low bits in [ul] beginning at the 'bit-cursor'
//
// Arguments: [ul] -- A DWord containing data to store.
//
// [cb] -- The number of bits to store.
//
// History: 08-Jul-91 KyleP Created.
//
// Notes: Bits are stored 'big-endian'.
//
//----------------------------------------------------------------------------
void CWBitStream::IPutBits(ULONG ul, unsigned cb)
{
Win4Assert ( cb > _cbitLeftDW );
// ciDebugOut (( DEB_BITSTM, "IPutBits %d\n", cb ));
if ( _cbitLeftDW != 0 )
{
Win4Assert ( _pCurPos < EndBuf() );
//
// Save the high portion in the current dword and save the
// number of unwritten bits in cb
//
cb -= _cbitLeftDW;
*_pCurPos |= (ul >> cb);
}
//
// Increment to the next dword
//
NextDword();
//
// Store the remainder
//
_cbitLeftDW -= cb;
*_pCurPos = ul << _cbitLeftDW;
}
//+---------------------------------------------------------------------------
//
// Member: CWBitStream::ZeroToEndOfPage, public
//
// Synopsis: Writes zeros from the current bit offset to ther end of the
// page.
//
// History: 22-Apr-94 DwightKr Created.
//
// Notes: Bits are stored 'big-endian'.
//
//----------------------------------------------------------------------------
void CWBitStream::ZeroToEndOfPage()
{
ULONG * pCurPos = _pCurPos;
if ( (_cbitLeftDW != 0) && (_cbitLeftDW != 32) )
{
*pCurPos &= (0xFFFFFFFF << _cbitLeftDW);
pCurPos++;
}
RtlZeroMemory( pCurPos, (EndBuf() - pCurPos) * sizeof(ULONG));
}
void CWBitStream::InitSignature()
{
_buffer.InitSignature();
}
//+---------------------------------------------------------------------------
//
// Member: CPBitStream::IOverwriteBits, private
//
// Synopsis: Store bits in the buffer. This call doesn't affect
// surrounding bits.
//
// Effects: OR the [cb] low bits in [ul] beginning at the 'bit-cursor'
//
// Arguments: [ul] -- A DWord containing data to store.
//
// [cb] -- The number of bits to store.
//
// History: 18-Jul-91 KyleP Created.
//
// Notes: Bits are stored 'big-endian'.
//
//----------------------------------------------------------------------------
void CPBitStream::IOverwriteBits(ULONG ul, unsigned cb)
{
Win4Assert ( cb > _cbitLeftDW );
// prepare for next write
_bitOff += cb;
Win4Assert( _bitOff.Offset() < SMARTBUF_PAGE_SIZE_IN_BITS );
if ( _cbitLeftDW > 0 )
{
Win4Assert ( _pCurPos < EndBuf() );
// zero the remaining bits in the current dword
*_pCurPos &= 0xFFFFFFFF << _cbitLeftDW;
// this much will go to the next dword
cb -= _cbitLeftDW;
// shift away the part that goes to the next dword
// and or in the rest
*_pCurPos |= (ul >> cb);
}
//
// Increment to the next dword
//
NextDword();
//
// Store the remainder
//
Win4Assert( cb <= ULONG_BITS );
if ( cb == ULONG_BITS )
{
*_pCurPos = ul;
}
else
{
// zero the cb upper bits of the current dword
*_pCurPos &= (0xFFFFFFFF >> cb);
// fill them with cb bits from the bottom of ul
*_pCurPos |= ul << (ULONG_BITS - cb);
}
}
const ULONG g_aMasks[33] =
{
0,
0x1,
0x3,
0x7,
0xf,
0x1f,
0x3f,
0x7f,
0xff,
0x1ff,
0x3ff,
0x7ff,
0xfff,
0x1fff,
0x3fff,
0x7fff,
0xffff,
0x1ffff,
0x3ffff,
0x7ffff,
0xfffff,
0x1fffff,
0x3fffff,
0x7fffff,
0xffffff,
0x1ffffff,
0x3ffffff,
0x7ffffff,
0xfffffff,
0x1fffffff,
0x3fffffff,
0x7fffffff,
0xffffffff,
};
//+---------------------------------------------------------------------------
//
// Member: CBitStream::IGetBits, public
//
// Synopsis: Retrieve bits from the buffer. Internal version for multi-
// dword case.
//
// Arguments: [cb] -- Count of bits to retrieve.
//
// History: 12-Jul-91 KyleP Created.
//
//----------------------------------------------------------------------------
ULONG CBitStream::IGetBits(unsigned cb)
{
Win4Assert ( cb > _cbitLeftDW );
//ciDebugOut (( DEB_BITSTM, "IGetBits %d\n", cb ));
//
// Get the portion from the current DWord
//
ULONG ul;
if ( 0 != _cbitLeftDW )
{
const ULONG mask = g_aMasks[ cb ];
cb -= _cbitLeftDW;
ul = (*_pCurPos << cb) & mask;
}
else
ul = 0L;
//
// And the portion from the next.
//
NextDword();
_cbitLeftDW -= cb;
return ul | (*_pCurPos >> (ULONG_BITS - cb));
} //IGetBits
//+---------------------------------------------------------------------------
//
// Member: CWBitStream::PutBytes, public
//
// Synopsis: Store a number of bytes in the buffer.
//
// Arguments: [pb] -- Pointer to data to store.
//
// [cb] -- Number of bytes to store.
//
// History: 08-Jul-91 KyleP Created.
//
//----------------------------------------------------------------------------
void CWBitStream::PutBytes(const BYTE * pb, unsigned cb)
{
// ciDebugOut (( DEB_BITSTM, "IPutBytes %d\n", cb ));
while (cb > 0)
{
PutBits(*pb, 8);
pb += 1;
cb--;
}
}
//+---------------------------------------------------------------------------
//
// Member: CBitStream::GetBytes, public
//
// Synopsis: Retrieve bytes from the buffer.
//
// Arguments: [pb] -- Pointer to area where data is returned.
//
// [cb] -- Count of bytes to retrieve.
//
// History: 12-Jul-91 KyleP Created.
//
//----------------------------------------------------------------------------
void CBitStream::GetBytes(BYTE * pb, unsigned cb)
{
ciDebugOut (( DEB_BITSTM, "GetBytes %d\n", cb ));
while (cb > 0)
{
*pb = BYTE ( GetBits(8) );
pb++;
cb--;
}
}
//+---------------------------------------------------------------------------
//
// Member: CBitStream::Seek, public
//
// Synopsis: Seeks to the specified bit offset
//
// Arguments: [off] -- bit offset
//
// History: 28-Aug-92 BartoszM Created.
//
//----------------------------------------------------------------------------
void CBitStream::Seek ( const BitOffset& off )
{
ciDebugOut (( DEB_BITSTM , "CBitStream::Seek %d:%d\n",
off.Page(), off.Offset() ));
if (_buffer.PageNum() != off.Page())
{
_buffer.Refill(off.Page());
}
SetPosition(off.Offset());
}
#if CIDBG == 1
unsigned CBitStream::PeekBit()
{
if (_cbitLeftDW > 0)
{
ULONG ul = *_pCurPos;
return( ul >> (_cbitLeftDW - 1)) & 1;
}
else
{
ULONG* pNewPos = _pCurPos + 1;
if (pNewPos < EndBuf())
{
return(*pNewPos >> (ULONG_BITS-1));
}
else
{
Win4Assert ( 0 && "Untested" );
CSmartBuffer bufTmp( _buffer, _buffer.PageNum() + 1 );
ULONG* p = bufTmp.Get();
unsigned bit = *p >> (ULONG_BITS-1);
return(bit);
}
}
}
unsigned CPBitStream::PeekBit()
{
// Fault in the page if necessary
if (_buffer.isEmpty() || _buffer.PageNum() != _bitOff.Page())
_buffer.Refill(_bitOff.Page());
SetPosition(_bitOff.Offset());
return CBitStream::PeekBit();
}
void DumpDword ( ULONG* pul )
{
ULONG ul = *pul;
for (int i = ULONG_BITS-1; i >= 0; i--)
{
ciDebugOut (( DEB_ITRACE | DEB_NOCOMPNAME,"%0d", (ul >> i) & 1 ));
if (i %4 == 0)
ciDebugOut (( DEB_ITRACE | DEB_NOCOMPNAME," " ));
}
ciDebugOut (( DEB_ITRACE | DEB_NOCOMPNAME,"\n" ));
}
void CBitStream::Dump()
{
ciDebugOut (( DEB_ITRACE, "CBitStream:\n"
"\tpage %d\n"
"\t_pCurPos 0x%x dwords from beginning\n"
"\t_cbitLeftDW %d\n",
_buffer.PageNum(), _pCurPos - _buffer.Get(), _cbitLeftDW ));
if (_pCurPos > _buffer.Get())
DumpDword ( _pCurPos - 1 );
if (_pCurPos < EndBuf())
{
DumpDword ( _pCurPos );
for (unsigned i = 1; i <= ULONG_BITS - _cbitLeftDW; i++ )
{
ciDebugOut (( DEB_ITRACE | DEB_NOCOMPNAME," " ));
if (i %4 == 0)
ciDebugOut (( DEB_ITRACE | DEB_NOCOMPNAME," " ));
}
ciDebugOut (( DEB_ITRACE | DEB_NOCOMPNAME,"^\n" ));
}
if (_pCurPos + 1 < EndBuf())
DumpDword(_pCurPos + 1);
}
void CPBitStream::Dump()
{
// Fault in the page if necessary
if (_buffer.isEmpty() || _buffer.PageNum() != _bitOff.Page())
{
_buffer.Refill(_bitOff.Page());
}
SetPosition(_bitOff.Offset());
CBitStream::Dump();
}
#endif // CIDBG == 1