|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1995 - 2000.
//
// File: pathstor.cxx
//
// Classes: CSplitPath, CSplitPathCompare, CPathStore
//
// Functions:
//
// History: 5-02-95 srikants Created
//
//----------------------------------------------------------------------------
#include "pch.cxx"
#pragma hdrstop
#include "pathstor.hxx"
#include "pathcomp.hxx"
#include "tabledbg.hxx"
const WCHAR CSplitPath::_awszPathSep[] = L"\\";
//+---------------------------------------------------------------------------
//
// Function: CSplitPath
//
// Synopsis: ~ctor for CSplitPath which can be initialized given the
// "pathId".
//
// Arguments: [pathStore] - Reference to the path store.
// [pathid] - PathId to be used for initialization.
//
// History: 5-09-95 srikants Created
//
//----------------------------------------------------------------------------
CSplitPath::CSplitPath( CPathStore & pathStore, PATHID pathid ) { const CShortPath & path = pathStore.GetShortPath( pathid );
CStringStore & strStore = pathStore.GetStringStore();
if ( stridInvalid != path.GetParent() ) { _pParent = strStore.GetCountedWStr( path.GetParent(), _cwcParent ); } else { _pParent = 0; _cwcParent = 0; }
if ( stridInvalid != path.GetFileName() ) { _pFile = strStore.GetCountedWStr( path.GetFileName(), _cwcFile ); } else { _pFile = 0; _cwcParent = 0; } }
//+---------------------------------------------------------------------------
//
// Function: CSplitPath
//
// Synopsis: ~ctor - initialized using a NULL terminated path.
//
// Arguments: [pwszPath] - The null terminated path.
//
// History: 5-09-95 srikants Created
//
//----------------------------------------------------------------------------
CSplitPath::CSplitPath( const WCHAR * pwszPath ) { const ULONG cwcPath = wcslen( pwszPath ); Win4Assert( 0 != cwcPath );
const WCHAR * pwszFinalComponent = wcsrchr(pwszPath, wchPathSep);
if ( 0 == pwszFinalComponent ) { _pParent = 0; _cwcParent = 0;
_pFile = pwszPath; _cwcFile = cwcPath; } else { _pParent = pwszPath; _cwcParent = (DWORD)(pwszFinalComponent - pwszPath);
_cwcFile = cwcPath - ( _cwcParent + 1 ); // skip over the path separator
if ( 0 != _cwcFile ) { _pFile = pwszPath + ( _cwcParent + 1 ); } else { //
// There is a path separator at the end of the string.
//
_pFile = 0; } } }
//+---------------------------------------------------------------------------
//
// Function: Advance
//
// Synopsis: Advances the current pointer by "cwc" characters during
// comparison of split paths.
//
// Arguments: [cwc] - Number of characters to advance by.
//
// History: 5-09-95 srikants Created
//
//----------------------------------------------------------------------------
inline void CSplitPath::Advance( ULONG cwc ) { Win4Assert( cwc <= _cwcCurr ); Win4Assert( !IsDone() );
_cwcCurr -= cwc;
if ( 0 == _cwcCurr ) { //
// We must go to the next step.
//
switch ( _step ) { case eUseParent:
if ( 0 != _pParent ) { _SetUsePathSep(); } else { if ( 0 != _pFile ) { _SetUseFile(); } else { _SetUsePathSep(); } }
break;
case eUsePathSep:
if ( 0 == _pFile ) { _SetDone(); } else { _SetUseFile(); }
break;
case eUseFile:
_SetDone(); break;
default: Win4Assert( !"Impossible Case Condition" ); break; } } else { _pCurr += cwc; } }
//+---------------------------------------------------------------------------
//
// Function: GetFullPathLen
//
// Synopsis: Determines the length of the fully path (in characters)
// INCLUDING the NULL terminator.
//
// History: 5-10-95 srikants Created
//
//----------------------------------------------------------------------------
ULONG CSplitPath::GetFullPathLen() const { ULONG cwcTotal = 0;
if ( 0 != _cwcParent ) { cwcTotal += (_cwcParent+1); // extra 1 is for the path separator
}
cwcTotal += GetFileNameLen(); Win4Assert( cwcTotal > 1 );
return cwcTotal; }
//+---------------------------------------------------------------------------
//
// Function: FormFullPath
//
// Synopsis: Forms the full path and copies it to pwszPath. It will
// be NULL terminated.
//
// Arguments: [pwszPath] - OUTPUT buffer for the path
// [cwcPath] - INPUT max. length of the buffer
//
// History: 5-10-95 srikants Created
//
//----------------------------------------------------------------------------
void CSplitPath::FormFullPath( WCHAR * pwszPath, ULONG cwcPath ) const { ULONG cwcParent;
Win4Assert( cwcPath >= GetFullPathLen() );
if ( 0 != _pParent ) { cwcParent = _cwcParent; RtlCopyMemory( pwszPath, _pParent, cwcParent * sizeof(WCHAR) ); //
// Append a backslash after the parent's part.
//
Win4Assert( cwcParent < cwcPath ); pwszPath[cwcParent++] = wchPathSep; // Append a backslash
pwszPath += cwcParent; }
ULONG cwcFileName = _cwcFile; if ( 0 != _pFile ) { Win4Assert( 0 != _cwcFile ); RtlCopyMemory( pwszPath, _pFile, _cwcFile * sizeof(WCHAR) ); }
pwszPath[cwcFileName] = L'\0'; }
//+---------------------------------------------------------------------------
//
// Function: FormFileName
//
// Synopsis: Fills just the "FileName" component of the path in the
// given buffer.
//
// Arguments: [pwszPath] - OUTPUT buffer - will contain the NULL
// terminated filename.
// [cwcFileName] - MAXLEN of pwszPath
//
// History: 5-10-95 srikants Created
//
//----------------------------------------------------------------------------
inline void CSplitPath::FormFileName( WCHAR * pwszPath, ULONG cwcFileName ) const { Win4Assert( cwcFileName >= GetFileNameLen() );
if ( 0 != _pFile ) { RtlCopyMemory( pwszPath, _pFile, sizeof(WCHAR)*_cwcFile ); }
pwszPath[_cwcFile] = L'\0'; return; }
//+---------------------------------------------------------------------------
//
// Function: _Compare
//
// Synopsis: Compars the lhs and rhs split paths.
//
// Returns: -1, 0, +1 depending on whether lhs <, =, > rhs
//
// History: 5-23-95 srikants Created
//
//----------------------------------------------------------------------------
int CSplitPathCompare::_Compare() { int iComp = 0; while ( !_IsDone() ) { iComp = _lhs.CompareCurr( _rhs ); if ( 0 != iComp ) { return iComp; }
ULONG cwcMin = min ( _lhs.GetCurrLen(), _rhs.GetCurrLen() ); _lhs.Advance( cwcMin ); _rhs.Advance( cwcMin ); }
iComp = _rhs.GetStep() - _lhs.GetStep(); if ( iComp > 0 ) { iComp = 1; } else if ( iComp < 0 ) { iComp = -1; }
return iComp;
}
//+---------------------------------------------------------------------------
//
// Function: ComparePaths
//
// Synopsis: Compares the two paths.
//
// Returns: 0 if equal
// -1 if lhs < rhs
// +1 if lhs > rhs
//
// History: 5-09-95 srikants Created
//
//----------------------------------------------------------------------------
int CSplitPathCompare::ComparePaths() { _lhs.InitForPathCompare(); _rhs.InitForPathCompare();
return _Compare();
}
//+---------------------------------------------------------------------------
//
// Function: CompareNames
//
// Synopsis: Compares the "Name" component of two paths.
//
// Returns: 0 if equal
// -1 if lhs < rhs
// +1 if lhs > rhs
//
// History: 5-11-95 srikants Created
//
//----------------------------------------------------------------------------
int CSplitPathCompare::CompareNames() { _lhs.InitForNameCompare(); _rhs.InitForNameCompare();
return _Compare(); }
//+---------------------------------------------------------------------------
//
// Function: Constructor for the CStringStore
//
// History: 5-03-95 srikants Created
//
//----------------------------------------------------------------------------
CStringStore::CStringStore() : _pStrHash(0) { _pStrHash = new CCompressedColHashString( FALSE ); // Don't optimize for ascii
END_CONSTRUCTION( CStringStore ); }
//+---------------------------------------------------------------------------
//
// Function: CStringStore
//
// Synopsis: Destructor for CStringStore.
//
// History: 5-03-95 srikants Created
//
//----------------------------------------------------------------------------
CStringStore::~CStringStore() { delete _pStrHash; }
//+---------------------------------------------------------------------------
//
// Function: Add
//
// Synopsis: Adds the NULL terminated pwszStr to the string store.
//
// Arguments: [pwszStr] - NULL terminated string to be added.
//
// Returns: The STRINGID of the string in the store.
//
// History: 5-03-95 srikants Created
//
//----------------------------------------------------------------------------
STRINGID CStringStore::Add( const WCHAR * pwszStr ) {
ULONG strId; GetValueResult gvr; _pStrHash->AddData( pwszStr, strId, gvr ); Win4Assert( GVRSuccess == gvr );
return strId; }
//+---------------------------------------------------------------------------
//
// Function: AddCountedWStr
//
// Synopsis: Adds a "counted" string to the store.
//
// Arguments: [pwszStr] - Pointer to the string to be added.
// [cwcStr] - Number of WCHARS in the string.
//
// Returns: The ID of the string.
//
// History: 5-09-95 srikants Created
//
//----------------------------------------------------------------------------
STRINGID CStringStore::AddCountedWStr( const WCHAR * pwszStr, ULONG cwcStr ) {
ULONG strId; GetValueResult gvr; _pStrHash->AddCountedWStr( pwszStr, cwcStr, strId, gvr ); Win4Assert( GVRSuccess == gvr );
return strId; }
//+---------------------------------------------------------------------------
//
// Function: FindCountedWStr
//
// Synopsis: Finds a "counted" string in the store.
//
// Arguments: [pwszStr] - Pointer to the string to be added.
// [cwcStr] - Number of WCHARS in the string.
//
// Returns: The ID of the string.
//
// History: 7-17-95 dlee Created
//
//----------------------------------------------------------------------------
STRINGID CStringStore::FindCountedWStr( const WCHAR * pwszStr, ULONG cwcStr ) {
if ( 0 != pwszStr ) return _pStrHash->FindCountedWStr( pwszStr, cwcStr ); else return stridInvalid; }
//+---------------------------------------------------------------------------
//
// Function: StrLen
//
// Synopsis: Length of the String associated with strId EXCLUDING the
// terminating NULL.
//
// Arguments: [strId] - Id of the string whose length is needed.
//
// Returns:
//
// History: 5-09-95 srikants Created
//
//----------------------------------------------------------------------------
ULONG CStringStore::StrLen( STRINGID strId ) { return _pStrHash->DataLength( strId )-1; }
//+---------------------------------------------------------------------------
//
// Function: GetCountedWStr
//
// Synopsis: Gets the string identified by the "strId.
//
// Arguments: [strId] - The id of the string to lookup.
// [cwcStr] - On output, will have the count of the chars
// in the string.
//
//
// Returns: Pointer to the string - NOT NULL terminated.
//
// History: 5-03-95 srikants Created
//
//----------------------------------------------------------------------------
const WCHAR * CStringStore::GetCountedWStr( STRINGID strId, ULONG & cwcStr ) { return _pStrHash->GetCountedWStr( strId, cwcStr ); }
//+---------------------------------------------------------------------------
//
// Function: GetString
//
// Synopsis: Returns the string identified by the strId.
//
// Arguments: [strId] - ID of the string to retrieve
// [pwszPath] - Pointer to the buffer to hold the string
// [cwcPath] - On input, the max capacity of pwszPath. On
// output, it will have the count of the chars
// in the string, excluding the terminating NULL.
//
// Returns:
//
// Modifies:
//
// History: 5-09-95 srikants Created
//
//----------------------------------------------------------------------------
GetValueResult CStringStore::GetString( STRINGID strId, WCHAR * pwszPath, ULONG & cwcPath ) { return _pStrHash->GetData( strId, pwszPath, cwcPath ); }
CPathStore::~CPathStore() { }
//+---------------------------------------------------------------------------
//
// Function: FindData
//
// Synopsis: Finds the given data (pidPath/pidName) in the path store.
//
// Arguments: [pVarnt] - string to look for
// [rKey] - returns key
//
// Returns: TRUE if found, FALSE otherwise
//
// History: 7-3-95 dlee Created
//
//----------------------------------------------------------------------------
BOOL CPathStore::FindData( PROPVARIANT const * const pvarnt, ULONG & rKey ) { Win4Assert(pvarnt->vt == VT_LPWSTR); WCHAR * pwszData = pvarnt->pwszVal;
CSplitPath path( pwszData );
STRINGID idParent = _strStore.FindCountedWStr( path._pParent, path._cwcParent ); STRINGID idName = _strStore.FindCountedWStr( path._pFile, path._cwcFile );
CShortPath shortPath( idParent, idName );
for ( unsigned i = 0; i < _aShortPath.Count(); i++ ) { if ( shortPath.IsSame( _aShortPath[ i ] ) ) { rKey = i + 1; // keys are 1-based
return TRUE; } }
return FALSE; } //FindData
//+---------------------------------------------------------------------------
//
// Function: AddData
//
// Synopsis: Adds the given data (pidPath/pidName) to the path store.
//
// Arguments: [pVarnt] -
// [pKey] -
// [reIndicator] -
//
// History: 5-09-95 srikants Created
//
//----------------------------------------------------------------------------
void CPathStore::AddData( PROPVARIANT const * const pVarnt, ULONG* pKey, GetValueResult& reIndicator ) { //
// Specially handle the VT_EMPTY case
//
if (pVarnt->vt == VT_EMPTY) { *pKey = 0; reIndicator = GVRSuccess; return; }
Win4Assert(pVarnt->vt == VT_LPWSTR); WCHAR * pwszData = pVarnt->pwszVal;
*pKey = AddPath( pwszData ); reIndicator = GVRSuccess; return; }
//+---------------------------------------------------------------------------
//
// Function: GetData
//
// Synopsis:
//
// Arguments: [pVarnt] - OUTPUT- Variant to hold the data.
// [PreferredType] - UNUSED
// [ulKey] - The "Key" (PathId) of the path to be
// retrieved.
// [PropId] - pidPath/pidWorkId/pidName
//
// Returns: GVRSuccess if successful.
// a GVR* failure code o/w.
//
// History: 5-09-95 srikants Created
//
// Notes: FreeVariant MUST be called.
//
//----------------------------------------------------------------------------
GetValueResult CPathStore::GetData( PROPVARIANT * pVarnt, VARTYPE PreferredType, ULONG ulKey, PROPID PropId ) { if (ulKey == 0) { pVarnt->vt = VT_EMPTY; return GVRNotAvailable; }
Win4Assert( _IsValid( ulKey ) );
if ( pidWorkId == PropId ) { pVarnt->vt = VT_I4; pVarnt->lVal = (LONG) ulKey; return GVRSuccess; }
CSplitPath path( *this, ulKey );
if ( pidName == PropId ) { ULONG cwcFileName = path.GetFileNameLen(); Win4Assert( cwcFileName > 0 );
WCHAR * pwszFileName = _GetPathBuffer( cwcFileName ); path.FormFileName( pwszFileName, cwcFileName );
pVarnt->vt = VT_LPWSTR; pVarnt->pwszVal = pwszFileName;
return GVRSuccess; } else { Win4Assert( pidPath == PropId );
//
// Retrieve entire path name.
//
// First, compute the required size of the return buffer.
//
ULONG cwcPathLen = path.GetFullPathLen( ); WCHAR * pwszDest = _GetPathBuffer( cwcPathLen );
pVarnt->vt = VT_LPWSTR; pVarnt->pwszVal = pwszDest;
path.FormFullPath( pwszDest, cwcPathLen ); return GVRSuccess; }
}
//+---------------------------------------------------------------------------
//
// Function: FreeVariant
//
// Synopsis: Frees the variant created in the "GetData" call.
//
// Arguments: [pVarnt] - Pointer to the variant to be freed.
//
// History: 5-09-95 srikants Created
//
//----------------------------------------------------------------------------
void CPathStore::FreeVariant(PROPVARIANT * pVarnt) { if ( pVarnt->vt != VT_EMPTY && pVarnt->vt != VT_I4 ) { Win4Assert(pVarnt->vt == VT_LPWSTR); _strStore.FreeVariant( pVarnt ); pVarnt->pwszVal = 0; // To prevent accidental re-use
} }
//+---------------------------------------------------------------------------
//
// Function: _AddPath
//
// Synopsis: Adds the given path to the store.
//
// Arguments: [path] -
//
// Returns: ID of the path.
//
// History: 5-23-95 srikants Created
//
//----------------------------------------------------------------------------
PATHID CPathStore::_AddPath( CSplitPath & path ) {
STRINGID idParent = stridInvalid; STRINGID idName = stridInvalid;
if ( 0 != path._pParent ) { idParent = _strStore.AddCountedWStr( path._pParent, path._cwcParent ); }
if ( 0 != path._pFile ) { idName = _strStore.AddCountedWStr( path._pFile, path._cwcFile ); }
return _AddEntry( idParent, idName );
}
//+---------------------------------------------------------------------------
//
// Function: AddPath
//
// Synopsis: Adds the given path to the path store.
//
// Arguments: [pwszPath] - Pointer to the path to be added.
//
// Returns: An ID for the path.
//
// History: 5-03-95 srikants Created
//
// Notes: There is NO duplicate detection for paths. A new ID is given
// everytime this method is called.
//
//----------------------------------------------------------------------------
PATHID CPathStore::AddPath( WCHAR * pwszPath ) { Win4Assert( 0 != pwszPath ); CSplitPath path( pwszPath ); PATHID pathId = _AddPath( path );
tbDebugOut(( DEB_BOOKMARK, "WorkId=0x%8X Path=%ws\n", pathId, pwszPath ));
return pathId; }
//+---------------------------------------------------------------------------
//
// Function: AddPath
//
// Synopsis: Given a source path store and an id in the source pathstore,
// this method adds the path from the source pathstore to this
// store.
//
// Arguments: [srcStore] - Reference to the source path store.
// [srcPathId] - Id in the source path store.
//
// Returns: PATHID for the path added.
//
// History: 5-23-95 srikants Created
//
//----------------------------------------------------------------------------
PATHID CPathStore::AddPath( CPathStore & srcStore, PATHID srcPathId ) {
CSplitPath srcPath( srcStore, srcPathId ); return _AddPath( srcPath ); }
//+---------------------------------------------------------------------------
//
// Function: PathLen
//
// Synopsis: Length of the path (INCLUDING terminating NULL) given the
// pathid.
//
// Arguments: [pathId] - Id of the path whose length is requested.
//
// Returns: Length of the path including terminating null.
//
// History: 5-03-95 srikants Created
//
//----------------------------------------------------------------------------
ULONG CPathStore::PathLen( PATHID pathId ) {
CSplitPath path( *this, pathId ); return path.GetFullPathLen(); }
//+---------------------------------------------------------------------------
//
// Function: GetPath
//
// Synopsis: Given a pathId, it returns the path for that pathid.
//
// Arguments: [pathId] - Id of the path to be retrieved
// [vtPath] - Variant to hold the output
// [cbVarnt] - On Input, the maximum length of the variant.
// On output, the actual length of the variant.
//
// Returns: GVRSuccess if successful
// GVRNotEnoughSpace if the length of the variant is less
// than needed.
//
// History: 5-08-95 srikants Created
//
//----------------------------------------------------------------------------
GetValueResult CPathStore::GetPath( PATHID pathId, PROPVARIANT & vtPath, ULONG & cbVarnt ) { CSplitPath splitPath( *this, pathId );
const ULONG cbPath = splitPath.GetFullPathLen() * sizeof(WCHAR); const ULONG cbHeader = sizeof(PROPVARIANT); const ULONG cbTotal = cbHeader + cbPath;
if ( cbVarnt < cbTotal ) { cbVarnt = cbTotal; return GVRNotEnoughSpace; }
const ULONG cwcPath = (cbTotal-cbHeader)/sizeof(WCHAR);
WCHAR * pwszPath = (WCHAR *) ( ((BYTE*) &vtPath) + cbHeader ); splitPath.FormFullPath( pwszPath, cwcPath );
vtPath.vt = VT_LPWSTR; vtPath.pwszVal = pwszPath;
cbVarnt = cbTotal; return GVRSuccess; }
//+---------------------------------------------------------------------------
//
// Function: Get
//
// Synopsis: Retrieves the path specified by the pathId into a buffer
// allocated from the dstPool.
//
// Arguments: [pathId] - Id of the path to be retrieved.
// [propId] - pidName/pidPath
// [dstPool] - Pool from which to allocate memory.
//
// Returns: Pointer to a WCHAR * containing the requested data
// (NULL Terminated).
//
// History: 5-23-95 srikants Created
//
//----------------------------------------------------------------------------
WCHAR * CPathStore::Get( PATHID pathId, PROPID propId, PVarAllocator & dstPool ) { // summary catalogs can have empty paths
if ( 0 == pathId ) return 0;
CSplitPath path( *this, pathId );
WCHAR * pwszDest = 0;
if ( pidName == propId ) { ULONG cwcFileName = path.GetFileNameLen(); ULONG cbDst = cwcFileName * sizeof(WCHAR); Win4Assert( cwcFileName > 0 ); pwszDest = (WCHAR *) dstPool.Allocate( cbDst ); path.FormFileName( pwszDest, cwcFileName ); } else { Win4Assert( pidPath == propId );
//
// Retrieve entire path name.
//
// First, compute the required size of the return buffer.
//
ULONG cwcPathLen = path.GetFullPathLen(); Win4Assert( cwcPathLen > 0 ); ULONG cbDst = cwcPathLen * sizeof(WCHAR); pwszDest = (WCHAR *) dstPool.Allocate( cbDst ); path.FormFullPath( pwszDest, cwcPathLen ); }
return pwszDest; }
//+---------------------------------------------------------------------------
//
// Function: _AddEntry
//
// Synopsis: Adds an entry consisting of a ParentId and a FileId to the
// store and returns a PATHID representing this short path.
//
// Arguments: [idParent] - Id of the parent in the path
// [idFileName] - Id of the file in the path.
//
// History: 5-10-95 srikants Created
//
//----------------------------------------------------------------------------
PATHID CPathStore::_AddEntry( STRINGID idParent, STRINGID idFileName ) { CShortPath path( idParent, idFileName ); _aShortPath.Add( path, _aShortPath.Count() ); return _aShortPath.Count(); }
//+---------------------------------------------------------------------------
//
// Function: Compare
//
// Synopsis: Compares two paths given their pathids.
//
// Arguments: [pathid1] -
// [pathid2] -
// [propId] - pidName/pidFile
//
// History: 5-11-95 srikants Created
//
//----------------------------------------------------------------------------
int CPathStore::Compare( PATHID pathid1, PATHID pathid2, PROPID propId ) { // summary catalogs can have empty paths
if ( 0 == pathid1 || 0 == pathid2 ) return pathid1 - pathid2;
Win4Assert( pidName == propId || pidPath == propId );
CSplitPath path1( *this, pathid1 ); CSplitPath path2( *this, pathid2 );
CSplitPathCompare comp( path1, path2 );
if ( pidName == propId ) { return comp.CompareNames(); } else { return comp.ComparePaths(); }
}
//+---------------------------------------------------------------------------
//
// Function: Compare
//
// Synopsis: Compares a NULL terminated path with a pathid.
//
// Arguments: [pwszPath1] - NULL terminated path.
// [pathid2] - Id of the second path.
// [propId] - pidName/pidPath
//
// History: 5-11-95 srikants Created
//
//----------------------------------------------------------------------------
int CPathStore::Compare( const WCHAR * pwszPath1, PATHID pathid2, PROPID propId ) { if ( 0 == pathid2 ) return 0;
Win4Assert( pidName == propId || pidPath == propId );
CSplitPath path1( pwszPath1 ); CSplitPath path2( *this, pathid2 );
CSplitPathCompare comp( path1, path2 );
if ( pidName == propId ) { return comp.CompareNames(); } else { return comp.ComparePaths(); } }
//+---------------------------------------------------------------------------
//
// Function: Compare
//
// Synopsis: Compares a path in the variant form to a pathId.
//
// Arguments: [varnt] -
// [pathid2] -
// [propId] -
//
// History: 5-11-95 srikants Created
//
//----------------------------------------------------------------------------
int CPathStore::Compare( PROPVARIANT &varnt, PATHID pathid2, PROPID propId ) { Win4Assert( pidName == propId || pidPath == propId );
Win4Assert( varnt.vt == VT_LPWSTR ); const WCHAR * pwszPath1 = varnt.pwszVal;
return Compare( pwszPath1, pathid2, propId ); }
|