353 lines
9.9 KiB
C++
353 lines
9.9 KiB
C++
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1994 - 1999.
|
||
|
//
|
||
|
// File: rowcomp.hxx
|
||
|
//
|
||
|
// Contents: Declaration of the row comparison classes
|
||
|
//
|
||
|
// Classes: CRowCompareVariant
|
||
|
//
|
||
|
// Templates: TRowCompare
|
||
|
//
|
||
|
// History: 31 Aug 1994 dlee Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#include <compare.hxx>
|
||
|
#include <xbuffer.hxx>
|
||
|
#include <shardbuf.hxx>
|
||
|
#include <tblvarnt.hxx>
|
||
|
|
||
|
#include "varntcmp.hxx"
|
||
|
#include "pathstor.hxx"
|
||
|
|
||
|
class CTableWindow;
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Class: CRowCompare
|
||
|
//
|
||
|
// Purpose: Abstract class for row comparisons
|
||
|
//
|
||
|
// Notes: The comparison function should return (for ascending order)
|
||
|
//
|
||
|
// 1..cSortItems if Row1 > Row2,
|
||
|
// 0 if same
|
||
|
// -1..-cSortItems if Row1 < Row2
|
||
|
//
|
||
|
// Return the opposite for descending order.
|
||
|
//
|
||
|
// History: 8/24/94 dlee created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
class CRowCompare
|
||
|
{
|
||
|
public:
|
||
|
CRowCompare() {}
|
||
|
virtual ~CRowCompare() {}
|
||
|
|
||
|
virtual int Compare(TBL_OFF oRow1, TBL_OFF oRow2) = 0;
|
||
|
};
|
||
|
|
||
|
class CPathStore;
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Class: CRowCompareVariant
|
||
|
//
|
||
|
// Purpose: Default case of row comparisons if a more optimal
|
||
|
// special case is not used. Converts values to variants
|
||
|
// and compares the variants. Also used if more than one
|
||
|
// (not including WORKID) sort spec specified.
|
||
|
//
|
||
|
// Notes: This must be declared unwindable because it has embedded
|
||
|
// unwindable objects.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
class CRowCompareVariant : public CRowCompare
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
CRowCompareVariant(CTableWindow & TableWindow);
|
||
|
virtual ~CRowCompareVariant();
|
||
|
|
||
|
int Compare(TBL_OFF oRow1,
|
||
|
TBL_OFF oRow2);
|
||
|
int CompareObject(CRetriever & obj,
|
||
|
TBL_OFF oRow2);
|
||
|
|
||
|
enum EVariantSource { eNone, eCompressor, eBuffer, eNewx };
|
||
|
|
||
|
private:
|
||
|
|
||
|
void _FreeVariant(CTableColumn * pColumn,
|
||
|
CTableVariant * pVar,
|
||
|
EVariantSource eSource);
|
||
|
|
||
|
void _MakeVariant(CTableColumn * pColumn,
|
||
|
BYTE * pbRow,
|
||
|
CTableVariant * pVar,
|
||
|
EVariantSource & evSource);
|
||
|
|
||
|
void _MakeVariant(CTableColumn * pColumn,
|
||
|
CRetriever & obj,
|
||
|
unsigned iProp);
|
||
|
|
||
|
PROPVARIANT * _MakeVariant( unsigned iCol,
|
||
|
XUseSharedBuffer & sharedBuf,
|
||
|
CRetriever & obj );
|
||
|
|
||
|
void _Cleanup1();
|
||
|
void _Cleanup2();
|
||
|
int _DoCompare(TBL_OFF oRow2);
|
||
|
|
||
|
void _InitComparators( CSortSet const & sortSet );
|
||
|
PATHID _GetPathId( const CTableColumn & col, BYTE * pbRow );
|
||
|
|
||
|
BOOL _FastCompare( unsigned iCol, BYTE *pbRow1, BYTE * pbRow2,
|
||
|
int & iComp );
|
||
|
|
||
|
BOOL _FastCompare( unsigned iCol, CRetriever & obj,
|
||
|
XUseSharedBuffer & sharedBuf,
|
||
|
BYTE * pbRow2, int & iComp );
|
||
|
|
||
|
unsigned _cProps;
|
||
|
CTableWindow &_TableWindow;
|
||
|
|
||
|
// Comparators for the columns
|
||
|
XArray<CCompareVariants> _aComparator;
|
||
|
|
||
|
// State data for the comparison.
|
||
|
|
||
|
XArray<CTableVariant> _aVar1;
|
||
|
XArray<CTableVariant> _aVar2;
|
||
|
XArray<CTableVariant *> _apVar1;
|
||
|
XArray<CTableVariant *> _apVar2;
|
||
|
XArray<CTableColumn *> _apColumn;
|
||
|
XArray<EVariantSource> _aVarFlags1;
|
||
|
XArray<EVariantSource> _aVarFlags2;
|
||
|
|
||
|
//
|
||
|
// Used for quick path comparison.
|
||
|
//
|
||
|
CPathStore * _pPathStore;
|
||
|
|
||
|
//
|
||
|
// Temporary shared memory for the whole table.
|
||
|
//
|
||
|
CSharedBuffer & _sharedBuf;
|
||
|
|
||
|
// Buffer used for CRetriever temporary data
|
||
|
|
||
|
enum { maxcbBuffer = MAX_PATH * sizeof WCHAR };
|
||
|
XBuffer<BYTE> _xBuffer;
|
||
|
|
||
|
// Most recent row 1 identified by this member is cached
|
||
|
|
||
|
WORKID _widCached;
|
||
|
};
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Template: TRowCompare
|
||
|
//
|
||
|
// Purpose: Special row comparator for inline values: values that are
|
||
|
// stored in the row as opposed to variable-length or easily
|
||
|
// compressed data that is stored out-of-line.
|
||
|
//
|
||
|
// Use of this template is just an optimization over using
|
||
|
// CRowCompareVariant, in which data must be converted to a
|
||
|
// variant before the comparison (which is slow).
|
||
|
//
|
||
|
// You can use this template if:
|
||
|
// -- only one property is in the sort spec
|
||
|
// -- the property value is stored inline
|
||
|
// -- the property value datatype supports relational ops
|
||
|
// -- length of the value is fixed and is not an array
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
template <class T> class TRowCompare : public CRowCompare
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
TRowCompare( CFixedVarTableWindowAllocator &Alloc,
|
||
|
ULONG oData,
|
||
|
ULONG dwOrder) :
|
||
|
_Alloc( Alloc ),
|
||
|
_oData( oData )
|
||
|
{
|
||
|
if (0 == (dwOrder & QUERY_SORTDESCEND /*DBSORTORDER_DESCEND*/ ))
|
||
|
_iGT = 1; // ascending
|
||
|
else
|
||
|
_iGT = -1; // descending
|
||
|
}
|
||
|
|
||
|
~TRowCompare() {}
|
||
|
|
||
|
int Compare( TBL_OFF oRow1,
|
||
|
TBL_OFF oRow2 )
|
||
|
{
|
||
|
T t1 = * (T *) ((BYTE *) _Alloc.FixedPointer( oRow1 ) + _oData);
|
||
|
T t2 = * (T *) ((BYTE *) _Alloc.FixedPointer( oRow2 ) + _oData);
|
||
|
|
||
|
if (t1 > t2)
|
||
|
return _iGT;
|
||
|
|
||
|
if (t1 < t2)
|
||
|
return -_iGT;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
int _iGT; // return value if 1 > 2
|
||
|
CFixedVarTableWindowAllocator &_Alloc; // allocator where rows are
|
||
|
ULONG _oData; // offset in row where value resides
|
||
|
};
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Template: TRowCompareTwo
|
||
|
//
|
||
|
// Purpose: Same as TRowCompare, except that it also does a second
|
||
|
// compare. A is compared first, then B.
|
||
|
//
|
||
|
// Rules for use of this template are the same as for
|
||
|
// TRowCompare
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
template <class TA, class TB> class TRowCompareTwo : public CRowCompare
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
TRowCompareTwo( CFixedVarTableWindowAllocator &Alloc,
|
||
|
ULONG oDataA,
|
||
|
ULONG dwOrderA,
|
||
|
ULONG oDataB,
|
||
|
ULONG dwOrderB ) :
|
||
|
_CompareA( Alloc, oDataA, dwOrderA ),
|
||
|
_CompareB( Alloc, oDataB, dwOrderB ) {}
|
||
|
|
||
|
~TRowCompareTwo() {}
|
||
|
|
||
|
int Compare( TBL_OFF oRow1,
|
||
|
TBL_OFF oRow2 )
|
||
|
{
|
||
|
int result = _CompareA.Compare( oRow1, oRow2 );
|
||
|
|
||
|
if (0 == result)
|
||
|
{
|
||
|
// same first key -- now check the second key.
|
||
|
// the * 2 means that it was the second column.
|
||
|
|
||
|
result = 2 * _CompareB.Compare( oRow1, oRow2 );
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
TRowCompare<TA> _CompareA;
|
||
|
TRowCompare<TB> _CompareB;
|
||
|
};
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Template: TRowCompareStringPlus
|
||
|
//
|
||
|
// Purpose: Same as TRowCompareTwo, except that the first key compared
|
||
|
// is a wide string, then the parameterized type is compared.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
template <class TB> class TRowCompareStringPlus : public CRowCompare
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
TRowCompareStringPlus( CFixedVarTableWindowAllocator &Alloc,
|
||
|
ULONG oDataString,
|
||
|
ULONG dwOrderString,
|
||
|
ULONG oDataB,
|
||
|
ULONG dwOrderB ) :
|
||
|
_Alloc( Alloc ),
|
||
|
_oDataString( oDataString ),
|
||
|
_CompareB( Alloc, oDataB, dwOrderB )
|
||
|
{
|
||
|
if (0 == (dwOrderString & QUERY_SORTDESCEND /*DBSORTORDER_DESCEND*/ ))
|
||
|
_iGTString = 1; // ascending
|
||
|
else
|
||
|
_iGTString = -1; // descending
|
||
|
}
|
||
|
|
||
|
|
||
|
~TRowCompareStringPlus() {}
|
||
|
|
||
|
int Compare( TBL_OFF oRow1,
|
||
|
TBL_OFF oRow2 )
|
||
|
{
|
||
|
WCHAR * p1 = * (WCHAR **) ((BYTE *) _Alloc.FixedPointer( oRow1 ) + _oDataString );
|
||
|
WCHAR * p2 = * (WCHAR **) ((BYTE *) _Alloc.FixedPointer( oRow2 ) + _oDataString );
|
||
|
|
||
|
// No string is every guaranteed to exist -- even path,
|
||
|
// since a summary catalog may have VT_EMPTY, and a VPATH
|
||
|
// is VT_EMPTY for non-web downlevel queries.
|
||
|
|
||
|
if ( 0 == p1 )
|
||
|
{
|
||
|
if ( 0 == p2 )
|
||
|
return 2 * _CompareB.Compare( oRow1, oRow2 );
|
||
|
else
|
||
|
return _iGTString;
|
||
|
}
|
||
|
else if ( 0 == p2 )
|
||
|
{
|
||
|
return -_iGTString;
|
||
|
}
|
||
|
|
||
|
int rc = CompareStringW( LOCALE_SYSTEM_DEFAULT,
|
||
|
NORM_IGNORECASE,
|
||
|
p1,
|
||
|
-1,
|
||
|
p2,
|
||
|
-1 );
|
||
|
|
||
|
// rc == 1, means less than
|
||
|
// rc == 2, means equal
|
||
|
// rc == 3, means greater than
|
||
|
|
||
|
int result = rc - 2;
|
||
|
|
||
|
if ( result > 0 )
|
||
|
return _iGTString;
|
||
|
|
||
|
if ( result < 0 )
|
||
|
return -_iGTString;
|
||
|
|
||
|
Win4Assert( 0 == result );
|
||
|
|
||
|
// same first key -- now check the second key.
|
||
|
// the * 2 means that it was the second column.
|
||
|
|
||
|
return 2 * _CompareB.Compare( oRow1, oRow2 );
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
int _iGTString; // return value if 1 > 2
|
||
|
CFixedVarTableWindowAllocator &_Alloc; // allocator where rows are
|
||
|
ULONG _oDataString; // offset in row where value resides
|
||
|
|
||
|
TRowCompare<TB> _CompareB;
|
||
|
};
|
||
|
|