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

351 lines
8.6 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1991 - 1999.
//
// File: RECOGNIZ.CXX
//
// Contents: Scan restriction for keys and create recognizers for them
//
// Classes: CScanRst
//
// History: 30-Sep-94 BartoszM Created
//
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <recogniz.hxx>
BOOL CKeyDetector::Match ( const CKeyBuf& key ) const
{
return _key.MatchPid (key) && _key.CompareStr (key) == 0;
}
DetectorType CKeyDetector::Type () const
{
return DetSingleKey;
}
BOOL CKeyRangeDetector::Match ( const CKeyBuf& key ) const
{
return _key.MatchPid (key) && _key.CompareStr (key) <= 0
&& _keyEnd.MatchPid (key) && _keyEnd.CompareStr (key) > 0;
}
DetectorType CKeyRangeDetector::Type () const
{
return DetRange;
}
BOOL CKeyPrefixDetector::Match ( const CKeyBuf& key ) const
{
return _key.MatchPid (key) && _key.CompareStr (key) <= 0
&& _keyEnd.MatchPid (key) && _keyEnd.CompareStr (key) > 0;
}
DetectorType CKeyPrefixDetector::Type () const
{
return DetPrefix;
}
CRecognizer::CRecognizer ()
: _iDet(-1), _aRegionList(0)
{
}
CRecognizer::~CRecognizer ()
{
delete []_aRegionList;
}
void CRecognizer::MakeDetectors ( const CRestriction* pRst )
{
if (pRst)
{
// find all keys and create detectors for them
ScanRst (pRst);
// prepare the array to hold matched key positions
_aRegionList = new CRegionList [Count()];
}
}
void CRecognizer::ScanRst ( const CRestriction* pRst )
{
if (pRst->IsLeaf())
{
ScanLeaf (pRst);
}
else
{
switch (pRst->Type())
{
case RTPhrase:
case RTProximity:
case RTVector:
case RTAnd:
case RTOr:
ScanNode (pRst->CastToNode());
break;
case RTNot:
ScanRst ( ((CNotRestriction *)pRst)->GetChild() );
break;
default:
Win4Assert ( !"Bad Restriction Type" );
THROW (CException(QUERY_E_INVALIDRESTRICTION));
}
}
}
void CRecognizer::ScanNode (const CNodeRestriction * pNode)
{
unsigned cChild = pNode->Count();
for (unsigned i = 0; i < cChild; i++)
{
ScanRst (pNode->GetChild(i));
}
}
void CRecognizer::ScanLeaf (const CRestriction* pRst )
{
switch (pRst->Type())
{
case RTWord:
{
CWordRestriction* wordRst = (CWordRestriction*) pRst;
const CKey* pKey = wordRst->GetKey();
if ( wordRst->IsRange() )
AddPrefix (pKey);
else
AddKey (pKey);
break;
}
case RTSynonym:
{
CSynRestriction* pSynRst = (CSynRestriction*) pRst;
CKeyArray& keyArray = pSynRst->GetKeys();
AddKeyArray ( keyArray, pSynRst->IsRange() );
break;
}
case RTRange:
{
CRangeRestriction* pRangRst = (CRangeRestriction*) pRst;
AddRange ( pRangRst->GetStartKey(), pRangRst->GetEndKey () );
break;
}
case RTNone:
{
// Noise words from vector queries come in as RTNone. Ignore them.
break;
}
default:
Win4Assert ( !"Bad Restriction Type" );
THROW (CException(QUERY_E_INVALIDRESTRICTION));
}
}
//+---------------------------------------------------------------------------
//
// Member: CRecognizer::AddKey, public
//
// Synopsis: Add a key detector
//
// History: 01-Oct-94 BartoszM Created
//
//----------------------------------------------------------------------------
void CRecognizer::AddKey ( const CKey* pKey )
{
int i = FindDet ( DetSingleKey, pKey );
if (i == -1)
{
_aDetector.Push ( new CKeyDetector (*pKey) );
}
}
//+---------------------------------------------------------------------------
//
// Member: CRecognizer::AddPrefix, public
//
// Synopsis: Add a prefix detector
//
// History: 01-Oct-94 BartoszM Created
//
//----------------------------------------------------------------------------
void CRecognizer::AddPrefix ( const CKey* pKey )
{
int i = FindDet ( DetPrefix, pKey );
if (i == -1)
{
_aDetector.Push ( new CKeyPrefixDetector (*pKey) );
}
}
//+---------------------------------------------------------------------------
//
// Member: CRecognizer::AddRange, public
//
// Synopsis: Add a range detector
//
// History: 01-Oct-94 BartoszM Created
//
//----------------------------------------------------------------------------
void CRecognizer::AddRange ( const CKey* pKeyStart, const CKey* pKeyEnd )
{
int i = FindDet ( DetRange, pKeyStart, pKeyEnd );
if (i == -1)
{
_aDetector.Push ( new CKeyRangeDetector (*pKeyStart, *pKeyEnd) );
}
}
//+---------------------------------------------------------------------------
//
// Member: CRecognizer::AddKeyArray, public
//
// Synopsis: Add key detectors
//
// History: 01-Oct-94 BartoszM Created
//
//----------------------------------------------------------------------------
void CRecognizer::AddKeyArray ( const CKeyArray& keyArray, BOOL isRange )
{
if (isRange)
{
for (int i = 0; i < keyArray.Count(); i++ )
{
int j = FindDet (DetPrefix, &keyArray.Get(i));
if (j == -1)
{
_aDetector.Push ( new CKeyPrefixDetector (keyArray.Get(i)) );
}
}
}
else
{
for ( int i = 0; i < keyArray.Count(); i++ )
{
int j = FindDet (DetSingleKey, &keyArray.Get(i));
if (j == -1)
{
_aDetector.Push ( new CKeyDetector (keyArray.Get(i)) );
}
}
}
}
int CRecognizer::FindDet (DetectorType type, const CKey* pKey1, const CKey* pKey2) const
{
Win4Assert ( 0 != pKey1 );
for (unsigned i = 0; i < _aDetector.Count(); i++)
{
const CDetector* pDet = _aDetector.Get (i);
if ( pDet->Type() == type && pKey1->IsExactMatch (*pDet->GetKey()) )
{
switch (type)
{
case DetSingleKey:
case DetPrefix:
Win4Assert ( 0 == pKey2 );
return i;
break;
case DetRange:
Win4Assert ( 0 != pKey2 );
if (pKey2->IsExactMatch (*pDet->GetSecondKey()))
{
return i;
}
break;
}
}
}
return -1;
}
//+---------------------------------------------------------------------------
//
// Member: CRecognizer::Match, public
//
// History: 05-Oct-94 BartoszM Created
//
// Synopsis: It is a sort of an iterator.
// If Match returns TRUE, you should Record the hit,
// after which Match should be called again with the same key
// and so on, until Match returns FALSE
//
//----------------------------------------------------------------------------
BOOL CRecognizer::Match ( const CKeyBuf& key )
{
// start just after the last match
for (unsigned i = _iDet + 1; i < _aDetector.Count(); i++)
{
if ( _aDetector.Get(i)->Match (key) )
{
_iDet = i; // leave it in this state
return TRUE;
}
}
_iDet = -1; // reset the state
return FALSE;
}
//+---------------------------------------------------------------------------
//
// Member: CRecognizer::Record, public
//
// History: 05-Oct-94 BartoszM Created
//
// Synopsis: Records the filter region position of a matched key
//
//----------------------------------------------------------------------------
void CRecognizer::Record ( const FILTERREGION& region, OCCURRENCE occ)
{
Win4Assert ( -1 != _iDet );
CRegionHit* pReg = new CRegionHit ( region, occ );
_aRegionList[_iDet].Insert ( pReg );
}
// Foo* CFooList::Insert ( CFoo* pFoo )
// {
// for ( CBackFooIter it(*this); !AtEnd(it); BackUp(it) )
// {
// if ( it->Size() <= pFoo->Size() ) // overloaded operator ->
// {
// pFoo->InsertAfter(it.GetFoo());
// return;
// }
// }
// // end of list
// Push(pFoo);
// }
//
void CRegionList::Insert (CRegionHit* pHit)
{
for (CRegionBackIter it(*this); !AtEnd(it); BackUp(it))
{
if ( it.GetRegionHit()->Occurrence() <= pHit->Occurrence() )
{
pHit->InsertAfter (it.GetRegionHit());
return;
}
}
_Push(pHit);
}
CRegionList::~CRegionList ()
{
CRegionHit* pHit;
while ( (pHit = (CRegionHit*) _Pop ()) != 0 )
{
delete pHit;
}
}