//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1995. // // File: StrHash.hxx // // Contents: String column compressor definitions // // Classes: CCompressedColHashString // CStringBuffer // // History: 03 Mar 1995 Alanw Created // //-------------------------------------------------------------------------- #pragma once #include #include "colcompr.hxx" const DWORD stridInvalid = 0xffffffff; //+------------------------------------------------------------------------- // // Class: CStringBuffer // // Purpose: A smart string buffer used for the GetData methods // of CCompressedColHashString and CCompressedColPath. // // Interface: // // Notes: // // History: 03 Mar 1995 Alanw Created // //-------------------------------------------------------------------------- class CStringBuffer { public: CStringBuffer() : _cchPathBuffer(0), _pwchPathBuffer(0), _fPathBufferInUse(FALSE) { } ~CStringBuffer() { delete [] _pwchPathBuffer; } BOOL InUse() { return _fPathBufferInUse; } PWSTR Alloc( unsigned cchString ); BOOL FreeConditionally( PWSTR pwszBuf ) { if (_fPathBufferInUse && pwszBuf == _pwchPathBuffer) { _fPathBufferInUse = FALSE; return TRUE; } return FALSE; } private: // // Full path buffer used by GetData. At most one GetData can be // outstanding at any one time. // unsigned _cchPathBuffer; // size of _pwchPathBuffer PWSTR _pwchPathBuffer; // temp. buffer for path BOOL _fPathBufferInUse; // TRUE if _pwchPathBuffer in use }; //+------------------------------------------------------------------------- // // Method: CStringBuffer::Alloc, public inline // // Synopsis: Return a pointer to a buffer large enough to // accomodate an the requested number of characters. // // Arguments: [cchPath] - number of characters needed, including // null terminator // // Returns: PWSTR - pointer to buffer // // Notes: At most one active GetData can ask for the path // at a time. GetData can be a performance hot spot, // so we don't want to do an allocation every time. // //-------------------------------------------------------------------------- inline PWSTR CStringBuffer::Alloc( unsigned cchPath ) { Win4Assert( _fPathBufferInUse == FALSE ); if (cchPath > _cchPathBuffer) { delete [] _pwchPathBuffer; _pwchPathBuffer = new WCHAR[ cchPath ]; _cchPathBuffer = cchPath; } _fPathBufferInUse = TRUE; return _pwchPathBuffer; } //+------------------------------------------------------------------------- // // Class: CCompressedColHashString // // Purpose: A compressed column which uses a hash table for // redundant value elimination. Specific to storing // string (VT_LPWSTR and VT_LPSTR) values. // // Interface: CCompressedCol // // Notes: To save storage space, strings are compressed to // ANSI strings whenever possible (only the ASCII // subset is tested for compression). Also, at most // MAX_HASHKEY distinct strings will be stored. // // Entries are only added to the table, never removed. // This reduces storage requirements since reference // counts do not need to be stored. // // History: 03 May 1994 Alanw Created // //-------------------------------------------------------------------------- class CCompressedColHashString: public CCompressedCol { friend class CCompressedColPath; // needs access to _pAlloc, _AddData // and _GetStringBuffer. friend class CStringStore; struct HashEntry { HASHKEY ulHashChain; // hash chain (must be first!) TBL_OFF ulStringKey; // key to string value in variable data USHORT usSizeFmt; // size and format(ascii/wchar) of the string }; public: CCompressedColHashString( BOOL fOptimizeAscii = TRUE ): CCompressedCol( VT_LPWSTR, // vtData, sizeof (HASHKEY), // cbKey, VarHash // ComprType ), _cHashEntries( 0 ), _cDataItems( 0 ), _pAlloc( NULL ), _fOptimizeAscii( fOptimizeAscii ), _cbDataWidth( sizeof (HashEntry) ), _Buf1(), _Buf2() { } ~CCompressedColHashString() { delete _pAlloc; } ULONG HashString( BYTE *pbData, USHORT cbData, VARTYPE vtType, BOOL fNullTerminated ); ULONG HashWSTR( WCHAR const * pwszStr, USHORT nChar ); ULONG HashSTR ( CHAR const * pszStr, USHORT nChar ); void AddData(PROPVARIANT const * const pvarnt, ULONG * pKey, GetValueResult& reIndicator); void AddData( const WCHAR * pwszStr, ULONG & key, GetValueResult& reIndicator ); void AddCountedWStr( const WCHAR * pwszStr, ULONG cwcStr, ULONG & key, GetValueResult& reIndicator ); ULONG FindCountedWStr( const WCHAR * pwszStr, ULONG cwcStr ); GetValueResult GetData( ULONG key, WCHAR * pwszStr, ULONG & cwcStr); GetValueResult GetData( PROPVARIANT * pvarnt, VARTYPE PreferredType, ULONG key = 0, PROPID prop = 0); const WCHAR * GetCountedWStr( ULONG key , ULONG & cwcStr ); void FreeVariant(PROPVARIANT * pvarnt); ULONG MemUsed(void) { return _pAlloc ? _pAlloc->MemUsed() : 0; } USHORT DataLength(ULONG key); private: PWSTR _GetStringBuffer( unsigned cchPath ); VOID _AddData( BYTE *pbData, USHORT cbDataSize, VARTYPE vt, ULONG* pKey, BOOL fNullTerminated ); ULONG _FindData( BYTE * pbData, USHORT cbDataSize, VARTYPE vt, BOOL fNullTerminated ); VOID _GrowHashTable( void ); HashEntry* _IndexHashkey( HASHKEY iKey ); USHORT _cHashEntries; // size of hash table const USHORT _cbDataWidth; // width of each data item ULONG _cDataItems; // number of entries in pDataItems CFixedVarAllocator *_pAlloc; // Data allocator BOOL _fOptimizeAscii; // // Name buffers used by GetData. There are two because sorted // insertion operations in the table can require two buffers. // CStringBuffer _Buf1; CStringBuffer _Buf2; }; //+------------------------------------------------------------------------- // // Method: CCompressedColHashString::_IndexHashkey, private inline // // Synopsis: Index a hash key and return a pointer to the corresponding // data entry. // // Arguments: [iKey] - lookup key value // // Returns: HashEntry*, pointer to the indexed item // // Notes: // //-------------------------------------------------------------------------- inline CCompressedColHashString::HashEntry* CCompressedColHashString::_IndexHashkey( HASHKEY iKey ) { Win4Assert(iKey > 0 && iKey <= _cDataItems); return ((HashEntry*) _pAlloc->FirstRow()) + iKey - 1; }