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

497 lines
13 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1991 - 2001.
//
// File: DREP.CXX
//
// Contents: Data Repository
//
// Classes: CDataRepository
//
// History: 18-Apr-91 BartoszM Created
// 03-June-91 t-WadeR Added PutStream, PutPhrase, PutWord
// 01-July-91 t-WadeR Ignores data with invalid property.
//
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <propvar.h>
#include <drep.hxx>
#include <lang.hxx>
#include <streams.hxx>
#include <pfilter.hxx>
#include <keymak.hxx>
#include <pidmap.hxx>
#include <codepage.hxx>
#include "psource.hxx"
#if CIDBG == 1
CCumulTimer::~CCumulTimer()
{
if (_count)
{
ciDebugOut (( DEB_ITRACE, "%ws:\n", _szActivity ));
ciDebugOut (( DEB_ITRACE, "\taverage %d ms, count %d, total time %d ms\n",
_totalTime/_count, _count, _totalTime ));
}
}
#endif //CIDBG
//+---------------------------------------------------------------------------
//
// Member: CDataRepository::CDataRepository
//
// Arguments: [krep] - the key repository
// [langlist] - the language list
// [langId] - language
// [fuzzy] - the fuzzy flag
//
// History: 18-Apr-91 BartoszM Created
// 08-May-91 t-WadeR Added default language
// 03-June-91 t-WadeR rewritten for input-driven pipeline
// 14-Sep-92 AmyA Added pCat
//
//----------------------------------------------------------------------------
CDataRepository::CDataRepository (
PKeyRepository& krep, IPhraseSink *pPhraseSink,
BOOL fQuery, ULONG fuzzy, CPidMapper & pidMap,
CLangList & langList )
: _krep (krep),
_valueNorm (krep),
_fQuery(fQuery),
_ulGenerateMethod(fuzzy),
_pPhraseSink(pPhraseSink),
_pidMap(pidMap),
_lcidSystemDefault( GetSystemDefaultLCID() ),
_langList(langList),
_pid( pidInvalid ),
_lcid( lcidInvalid ),
_prevPid( 0 ), // Different than _pid
_prevLcid( 0 ), // Different than _lcid
_cwcFoldedPhrase( 0 )
#if CIDBG == 1
, timerBind ( L"Binding" )
, timerNoBind ( L"Creating filter without binding" )
, timerFilter ( L"Filtering" )
#endif
{
}
//+---------------------------------------------------------------------------
//
// Member: CDataRepository::PutStream
//
// Synopsis: Passes stream to key maker to be added to key repository
//
// History: 03-June-91 t-WadeR Created
// 18-Nov-92 AmyA Overloaded
//
//----------------------------------------------------------------------------
void CDataRepository::PutStream ( TEXT_SOURCE * stm )
{
if ( LoadKeyMaker() )
{
Win4Assert( !_xKeyMaker.IsNull() );
_xKeyMaker->PutStream ( _occArray.Get(_pid), stm );
}
}
//+---------------------------------------------------------------------------
//
// Member: CDataRepository::PutPhrase
//
// Synopsis: Passes ASCII string of words to key maker to be added to
// key repository
//
// History: 23-Sept-92 AmyA Created
//
//----------------------------------------------------------------------------
void CDataRepository::PutPhrase ( const char* str, unsigned cc )
{
ULONG cwcOut = cc * 2 + 2;
WCHAR *pwcOut = new WCHAR[cwcOut];
ULONG cwcActual = 0;
do
{
cwcActual = MultiByteToWideChar( _ulCodePage,
0,
str,
cc,
pwcOut,
cwcOut );
if ( cwcActual == 0 )
{
delete[] pwcOut;
pwcOut = 0;
if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
{
cwcOut *= 2;
pwcOut = new WCHAR[cwcOut];
}
else
THROW( CException() );
}
} while ( cwcActual == 0 );
XArray<WCHAR> xOut;
xOut.Set( cwcOut, pwcOut );
PutPhrase( pwcOut, cwcActual );
}
//+---------------------------------------------------------------------------
//
// Member: CDataRepository::PutPhrase
//
// Synopsis: Passes unicode string of words to key maker to be added to
// key repository
//
// History: 23-Sept-92 AmyA Created
//
//----------------------------------------------------------------------------
void CDataRepository::PutPhrase ( const WCHAR* str, unsigned cwc )
{
if ( 0 != str && cwc > 0 && LoadKeyMaker() )
{
//
// Normalize to precomposed Unicode
//
_xwcsFoldedPhrase.ReSize( cwc );
ULONG cwcFolded = FoldStringW( MAP_PRECOMPOSED,
str,
cwc,
_xwcsFoldedPhrase.Get(),
cwc );
if ( cwcFolded == 0 )
{
Win4Assert( GetLastError() != ERROR_INSUFFICIENT_BUFFER );
THROW( CException() );
}
_cwcFoldedPhrase = cwcFolded;
CPhraseSource s( _xwcsFoldedPhrase.GetPointer(), cwcFolded );
Win4Assert( !_xKeyMaker.IsNull() );
_xKeyMaker->PutStream ( _occArray.Get(_pid), &s );
}
}
//+---------------------------------------------------------------------------
//
// Member: CDataRepository::PutPropName
//
// Arguments: [strProp] -- name of the property
//
// History: 18-Apr-91 BartoszM Created
// 01-June-91 t-WadeR Ignores data with invalid property
// 21-Feb-95 DwightKr Added fake property id mapping
//
//----------------------------------------------------------------------------
BOOL CDataRepository::PutPropName ( CFullPropSpec const & Prop )
{
//
// Find the pid
//
PROPID fakePid = _pidMap.NameToPid( Prop );
return PutPropId( fakePid );
}
//+---------------------------------------------------------------------------
//----------------------------------------------------------------------------
BOOL CDataRepository::PutPropId ( PROPID fakePid )
{
_prevPid = _pid;
if ( fakePid == pidInvalid )
{
_pid = pidInvalid;
}
else
{
_pid = _pidMap.PidToRealPid( fakePid );
if ( !_krep.PutPropId( _pid ) )
{
ciDebugOut(( DEB_WARN, "Key repository didn't accept pid %u\n", _pid ));
_pid = pidInvalid;
}
}
return (pidInvalid != _pid);
}
//+---------------------------------------------------------------------------
//
// Member: CDataRepository::PutLanguage
//
// Synopsis: if the lcid is different, it frees the current lang. dependent
// key maker, and gets a new one
//
// Arguments: [lcid] -- language descriptor
//
// History: 18-Apr-91 BartoszM Created
// 03-June-91 t-WadeR Changed to use CLangDepKeyMaker pool.
//
//----------------------------------------------------------------------------
BOOL CDataRepository::PutLanguage ( LCID lcid )
{
_prevLcid = _lcid;
//
// Special cases for language: system default and user default.
//
if ( lcid == LOCALE_SYSTEM_DEFAULT )
_lcid = GetSystemDefaultLCID();
else if ( lcid == LOCALE_USER_DEFAULT )
_lcid = GetUserDefaultLCID();
else
_lcid = lcid;
//
// Set codepage, for conversion of narrow strings.
//
if ( _prevLcid != _lcid )
{
_ulCodePage = LocaleToCodepage( _lcid );
}
return TRUE;
}
//+---------------------------------------------------------------------------
//
// Member: CDataRepository::PutValue
//
// Synopsis: Store a property value.
//
// Arguments: [var] -- Value
//
// History: 08-Feb-94 KyleP Added header
//
//----------------------------------------------------------------------------
void CDataRepository::PutValue( CStorageVariant const & var )
{
//
// Textual values are special. They are treated as contents, and
// thus need language identification and word breaking. Unlike contents,
// we do not provide support for choosing the language.
//
switch ( var.Type() )
{
case VT_LPWSTR:
{
unsigned cwc = 0;
if ( 0 != var.GetLPWSTR() )
{
cwc = wcslen( var.GetLPWSTR() );
}
if (cwc > 0)
PutPhrase( var.GetLPWSTR(), cwc + 1);
break;
}
case VT_LPSTR:
{
unsigned cb = 0;
if ( 0 != var.GetLPSTR() )
{
cb = strlen( var.GetLPSTR() );
}
if (cb > 0)
PutPhrase( var.GetLPSTR(), cb + 1);
break;
}
case VT_BSTR :
{
if ( ( 0 != var.GetBSTR() ) &&
( 0 != BSTRLEN( var.GetBSTR() ) ) )
{
PutPhrase( var.GetBSTR(),
1 + ( BSTRLEN( var.GetBSTR() ) / sizeof WCHAR ) );
}
break;
}
case VT_VECTOR | VT_LPWSTR:
{
for ( ULONG j = 0; j < var.Count(); j++ )
{
unsigned cb = 0;
if ( 0 != var.GetLPWSTR(j) )
{
cb = wcslen( var.GetLPWSTR(j) );
}
if (cb > 0)
{
PutPhrase( var.GetLPWSTR(j), cb + 1);
}
}
break;
}
case VT_VECTOR | VT_BSTR:
{
for ( ULONG j = 0; j < var.Count(); j++ )
{
if ( ( 0 != var.GetBSTR(j) ) &&
( 0 != BSTRLEN( var.GetBSTR(j) ) ) )
{
PutPhrase( var.GetBSTR(j),
1 + ( BSTRLEN( var.GetBSTR(j) ) / sizeof WCHAR ) );
}
}
break;
}
case VT_VECTOR | VT_LPSTR:
{
for ( ULONG j = 0; j < var.Count(); j++ )
{
unsigned cb = 0;
if ( 0 != var.GetLPSTR(j) )
{
cb = strlen( var.GetLPSTR(j) );
}
if (cb > 0)
{
PutPhrase( var.GetLPSTR(j), cb + 1);
}
}
break;
}
case VT_VECTOR | VT_VARIANT :
{
for ( ULONG j=0; j < var.Count(); j++ )
{
ciDebugOut (( DEB_ITRACE, "Filtering vector variant[%d] of type 0x%x\n",
j, (ULONG) var.GetVARIANT(j).Type() ));
PutValue( (CStorageVariant const &)var.GetVARIANT(j) );
}
break;
}
default:
_valueNorm.PutValue( _pid, _occArray.Get(_pid), var );
break;
}
}
//+---------------------------------------------------------------------------
//
// Member: CDataRepository::ContainedNoiseWords
//
// Returns: TRUE if any text sent to repository had a noise word in it.
//
// History: 03-Oct-95 KyleP Created
//
//----------------------------------------------------------------------------
BOOL CDataRepository::ContainedNoiseWords()
{
if ( _xKeyMaker.IsNull() )
return FALSE;
return _xKeyMaker->ContainedNoiseWords();
}
//+---------------------------------------------------------------------------
//
// Member: CDataRepository::LoadKeyMaker, private
//
// Synopsis: Loads new key maker, if necessary
//
// Returns: TRUE if an appropriate key maker was located (and loaded).
//
// History: 05-Jan-98 KyleP Created
//
//----------------------------------------------------------------------------
BOOL CDataRepository::LoadKeyMaker()
{
if ( pidInvalid == _pid || lcidInvalid == _lcid )
return FALSE;
if ( _pid == _prevPid && _lcid == _prevLcid )
{
Win4Assert( !_xKeyMaker.IsNull() );
return TRUE;
}
//
// Locate an appropriate Key Maker
//
if ( _xKeyMaker.IsNull() || !_xKeyMaker->Supports( _pid, _lcid ) )
{
delete _xKeyMaker.Acquire();
_xKeyMaker.Set( new CKeyMaker( _lcid, _pid, _krep, _pPhraseSink, _fQuery, _ulGenerateMethod, _langList ) );
}
return TRUE;
}
//+---------------------------------------------------------------------------
//
// Member: CDataRepository::NormalizeWStr - Public
//
// Synopsis: Normalizes a UniCode string
//
// Arguments: [pbOutBuf] -- output buffer.
// [pcbOutBuf] - pointer to output count of bytes.
//
// History: 10-Feb-2000 KitmanH Created
//
//----------------------------------------------------------------------------
void CDataRepository::NormalizeWStr( BYTE *pbOutBuf, unsigned *pcbOutBuf )
{
// Chop off the trailing null character
if ( 0 == _xwcsFoldedPhrase[_cwcFoldedPhrase-1] )
_cwcFoldedPhrase--;
Win4Assert( _cwcFoldedPhrase > 0 );
ciDebugOut(( DEB_ITRACE, "CDdataRepository::NormailizeWStr: %ws, %d\n",
_xwcsFoldedPhrase.Get(),
_cwcFoldedPhrase ));
_xKeyMaker->NormalizeWStr( _xwcsFoldedPhrase.Get(),
_cwcFoldedPhrase,
pbOutBuf,
pcbOutBuf );
}