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

231 lines
5.8 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1994 - 1994.
//
// File: tblrowal.cxx
//
// Contents: The CTableRowAlloc class, used in allocation
// of table row data and checking of column bindings.
//
// Classes: CTableRowAlloc
//
// History: 27 Jun 1994 Alanw Created
//
//--------------------------------------------------------------------------
#include "pch.cxx"
#pragma hdrstop
#include <tblrowal.hxx>
#include "tabledbg.hxx"
//+-------------------------------------------------------------------------
//
// Member: CTableRowAlloc::CTableRowAlloc, public
//
// Synopsis: Constructor for a row field allocator. Initializes
// max. width and other members.
//
// Arguments: [cbRow] - maximum size of the row. Can be zero if the
// row is to grow dynamically via the AllocOffset
// method.
//
// Notes:
//
//+-------------------------------------------------------------------------
CTableRowAlloc::CTableRowAlloc(unsigned cbRow) :
_maxRow( (USHORT)cbRow ),
_cbRow( sizeof(_aRowMap) ),
_iFirstFree(0)
{
RtlZeroMemory( _aRowMap, sizeof(_aRowMap) );
_pRowMap = _aRowMap;
}
//+---------------------------------------------------------------------------
//
// Member: CTableRowAlloc::_IsLikelyFree
//
// Synopsis: Quickly checks to see if the given offset is likely to be
// free.
//
// Arguments: [iOffset] - Offset to test
// [cbData] - Length of the data needed.
//
// Returns: TRUE if that location is likely to be free.
// FALSE if it is guaranteed not to be a free candidate.
//
// History: 5-03-96 srikants Created
//
// Notes: This is a quick check to see if the location is likely to
// be free. Does not guarantee that it is free.
//
//----------------------------------------------------------------------------
inline BOOL CTableRowAlloc::_IsLikelyFree( unsigned iOffset, unsigned cbData )
{
if ( iOffset < _cbRow && _pRowMap[iOffset] != 0 )
return FALSE;
if (iOffset + cbData > _maxRow)
return FALSE;
return TRUE;
}
inline unsigned AlignedOffset( unsigned offset, unsigned cbAlign )
{
Win4Assert( ( cbAlign & (cbAlign-1) ) == 0 );
return (offset + cbAlign-1) & ~(cbAlign-1);
}
//+-------------------------------------------------------------------------
//
// Member: CTableRowAlloc::AllocOffset, public
//
// Synopsis: Allocate a row field. Return the offset in the row.
//
// Arguments: [cbData] - size of data field
// [cbAlign] - required alignment of field (may be zero
// if no alignment requirement)
// [fGrow] - TRUE if row can be grown
//
// Returns: USHORT - offset of allocted field. 0xFFFF if failed.
//
// Notes:
//
//+-------------------------------------------------------------------------
USHORT CTableRowAlloc::AllocOffset(
unsigned cbData,
unsigned cbAlign,
BOOL fGrow
) {
Win4Assert(cbAlign <= 16);
if (cbAlign == 0)
cbAlign = 1;
USHORT usSavedMax = _maxRow;
for ( unsigned i = AlignedOffset(_iFirstFree,cbAlign);
i < _cbRow;
i += cbAlign)
{
if (fGrow && (i + cbData) > _maxRow)
SetRowWidth(i + cbData);
if ( _IsLikelyFree(i, cbData) && ReserveRowSpace( i, cbData )) {
return (USHORT)i;
}
}
if (fGrow)
{
SetRowWidth(i + cbData);
if (ReserveRowSpace( i, cbData )) {
return (USHORT)i;
}
SetRowWidth(usSavedMax);
}
return 0xFFFF;
}
//+-------------------------------------------------------------------------
//
// Member: CTableRowAlloc::ReserveRowSpace, public
//
// Synopsis: Reserve a row field in the allocation map.
//
// Arguments: [iOffset] - offset of field in row
// [cbData] - size of data field
//
// Returns: BOOL - TRUE if field could be reserved, FALSE otherwise
//
// Notes:
//
//+-------------------------------------------------------------------------
BOOL CTableRowAlloc::ReserveRowSpace(
unsigned iOffset,
unsigned cbData
) {
Win4Assert(cbData > 0);
if (iOffset + cbData > _maxRow) {
return FALSE;
}
if (iOffset + cbData >= _cbRow) {
//
// Before growing the array, check to see if the reservation
// would fail anyway.
//
if (iOffset < _cbRow && _pRowMap[ iOffset ] != 0)
{
return FALSE;
}
//
// Need to allocate more space for the row map
//
unsigned cbNew = iOffset + max( cbData, CB_INIT );
BYTE* pNewMap = new BYTE [cbNew];
Win4Assert( _cbRow > 0 );
RtlCopyMemory(pNewMap, _pRowMap, _cbRow);
RtlZeroMemory((void *)&pNewMap[_cbRow], cbNew - _cbRow);
if ( _pRowMap != _aRowMap )
delete [] _pRowMap;
_pRowMap = pNewMap;
_cbRow = (USHORT)cbNew;
}
//
// Check if any byte in the field has already been reserved.
//
for (unsigned i = 0; i < cbData; i++) {
if (_pRowMap[ iOffset + i ] != 0) {
return FALSE;
}
}
//
// Reserve the requested field
//
for (i = 0; i < cbData; i++) {
_pRowMap[ iOffset + i ] = 1;
}
//
// Update the _iFirstFree if appropriate.
//
Win4Assert( _iFirstFree <= _cbRow );
if ( _iFirstFree == iOffset )
{
//
// Find the next free location
//
Win4Assert( i+iOffset == _iFirstFree+cbData );
Win4Assert( i == cbData );
for ( i += iOffset; i < _cbRow; i++ )
{
if ( !_IsInUse(i) )
break;
}
_iFirstFree = i;
}
return TRUE;
}