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

387 lines
11 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1991 - 1994.
//
// File: TSource.cxx
//
// Contents: TEXT_SOURCE implementation
//
// Classes: CTextSource
//
// History: 14-Apr-94 KyleP Created
//
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <tsource.hxx>
#include <mapper.hxx>
//+-------------------------------------------------------------------------
//
// Member: CTextSource::CTextSource, public
//
// Synopsis: Constructor
//
// Arguments: [pFilter] -- IFilter (source of data)
// [Stat] -- Chunk statistics
//
// History: 01-Aug-93 AmyA Created
// 14-Apr-94 KyleP Sync with wordbreaker spec
//
//--------------------------------------------------------------------------
CTextSource::CTextSource( IFilter * pFilter, STAT_CHUNK & Stat, CSourceMapper* pMapper )
: _pMapper (pMapper),
_pFilter(pFilter),
_Stat( Stat ),
_sc( S_OK )
{
#if CIDBG == 1
CFullPropSpec & ps = *((CFullPropSpec *)&Stat.attribute);
ciDebugOut(( DEB_WORDS,
"TEXT SOURCE: Initial chunk of "
"%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\\",
ps.GetPropSet().Data1,
ps.GetPropSet().Data2,
ps.GetPropSet().Data3,
ps.GetPropSet().Data4[0], ps.GetPropSet().Data4[1],
ps.GetPropSet().Data4[2], ps.GetPropSet().Data4[3],
ps.GetPropSet().Data4[4], ps.GetPropSet().Data4[5],
ps.GetPropSet().Data4[6], ps.GetPropSet().Data4[7] ));
if ( ps.IsPropertyName() )
ciDebugOut(( DEB_WORDS | DEB_NOCOMPNAME,
"%ws\n", ps.GetPropertyName() ));
else
ciDebugOut(( DEB_WORDS | DEB_NOCOMPNAME,
"0x%x\n", ps.GetPropertyPropid() ));
#endif // CIDBG == 1
iEnd = 0;
iCur = 0;
awcBuffer = _awcFilterBuffer;
pfnFillTextBuffer = CTextSource::FillBuf;
if (_pMapper)
{
if (_Stat.idChunk == _Stat.idChunkSource)
{
_pMapper->NewChunk ( _Stat.idChunk, 0 );
}
else
{
_pMapper->NewDerivedChunk (
_Stat.idChunkSource,
_Stat.cwcStartSource,
_Stat.cwcLenSource);
}
}
FillBuf( this );
}
//+-------------------------------------------------------------------------
//
// Member: CTextSource::FillBuf, public
//
// Synopsis: Fills buffer with IFilter::GetText and IFilter::GetChunk
//
// History: 01-Aug-93 AmyA Created
// 20-Apr-94 KyleP Sync with spec
//
// Notes: NOTE! In several places, this function casts const away
// from awcBuffer. This is an acceptable cast from const to
// non-const. The buffer is const to the client but non-const
// to the server.
//
//--------------------------------------------------------------------------
SCODE CTextSource::FillBuf( TEXT_SOURCE * pTextSource )
{
CTextSource * pthis = (CTextSource *)pTextSource;
//
// Never continue past an error condition other than FILTER_E_NO_MORE_TEXT
//
if ( FAILED( pthis->_sc ) && pthis->_sc != FILTER_E_NO_MORE_TEXT )
return( pthis->_sc );
// Don't allow wordbreaker bugs with iEnd/iCur to overwrite memory.
Win4Assert ( pthis->iEnd >= pthis->iCur );
if ( pthis->iCur > pthis->iEnd )
{
pthis->_sc = WBREAK_E_END_OF_TEXT;
return WBREAK_E_END_OF_TEXT;
}
//
// Move any existing text to beginning of buffer.
//
ULONG ccLeftOver = pthis->iEnd - pthis->iCur;
if ( ccLeftOver > 0 )
{
RtlMoveMemory( (WCHAR *)pthis->awcBuffer,
&pthis->awcBuffer[pthis->iCur],
ccLeftOver * sizeof (WCHAR) );
}
if (pthis->_pMapper)
{
// this much has been processed from the current chunk
pthis->_pMapper->Advance ( pthis->iCur );
}
pthis->iCur = 0;
pthis->iEnd = ccLeftOver;
ULONG ccRead = PAGE_SIZE / sizeof(WCHAR) - ccLeftOver;
const BUFFER_SLOP = 10; // Buffer is attempted to be filled until BUFFER_SLOP remains
//
// Get some more text. If *previous* call to GetText returned
// FILTER_S_LAST_TEXT, or FILTER_E_NO_MORE_TEXT then don't even
// bother trying.
//
if ( pthis->_sc == FILTER_S_LAST_TEXT || pthis->_sc == FILTER_E_NO_MORE_TEXT )
pthis->_sc = FILTER_E_NO_MORE_TEXT;
else
{
pthis->_sc = pthis->_pFilter->GetText( &ccRead,
(WCHAR *) &pthis->awcBuffer[ccLeftOver] );
if ( SUCCEEDED( pthis->_sc ) )
{
pthis->iEnd += ccRead;
ccLeftOver += ccRead;
ccRead = PAGE_SIZE / sizeof(WCHAR) - ccLeftOver;
while ( pthis->_sc == S_OK && ccRead > BUFFER_SLOP )
{
//
// Attempt to fill in as much of buffer as possible before returning
//
pthis->_sc = pthis->_pFilter->GetText( &ccRead,
(WCHAR *) &pthis->awcBuffer[ccLeftOver] );
if ( SUCCEEDED( pthis->_sc ) )
{
pthis->iEnd += ccRead;
ccLeftOver += ccRead;
ccRead = PAGE_SIZE / sizeof(WCHAR) - ccLeftOver;
}
}
#if CIDBG == 1
DebugPrintBuffer( pthis );
#endif
//
// Either return FILTER_S_LAST_TEXT or return S_OK because we have succeeded in
// adding text to the buffer
//
if ( pthis->_sc == FILTER_S_LAST_TEXT )
return FILTER_S_LAST_TEXT;
else
return S_OK;
}
if ( pthis->_sc != FILTER_E_NO_MORE_TEXT )
{
//
// Weird failure, hence return, else goto next chunk
//
return pthis->_sc;
}
}
//
// Go to next chunk, if necessary.
//
while ( pthis->_sc == FILTER_E_NO_MORE_TEXT )
{
pthis->_sc = pthis->_pFilter->GetChunk( &pthis->_Stat );
if ( pthis->_sc == FILTER_E_END_OF_CHUNKS )
return WBREAK_E_END_OF_TEXT;
if ( pthis->_sc == FILTER_E_PARTIALLY_FILTERED )
return WBREAK_E_END_OF_TEXT;
if ( FAILED( pthis->_sc ) )
return( pthis->_sc );
if ( pthis->_Stat.flags & CHUNK_VALUE )
{
pthis->_sc = FILTER_E_NO_TEXT;
return WBREAK_E_END_OF_TEXT;
}
if ( pthis->_Stat.breakType != CHUNK_NO_BREAK )
{
pthis->_sc = WBREAK_E_END_OF_TEXT;
return WBREAK_E_END_OF_TEXT;
}
ciDebugOut(( DEB_WORDS, "TEXT SOURCE: NoBreak chunk\n" ));
if (pthis->_pMapper)
{
ULONG idChunk = pthis->_Stat.idChunk;
if (idChunk == pthis->_Stat.idChunkSource)
{
pthis->_pMapper->NewChunk ( idChunk, ccLeftOver );
}
else
{
pthis->_sc = WBREAK_E_END_OF_TEXT;
return WBREAK_E_END_OF_TEXT;
}
}
ccRead = PAGE_SIZE / sizeof(WCHAR) - ccLeftOver;
pthis->_sc = pthis->_pFilter->GetText( &ccRead,
(WCHAR *) &pthis->awcBuffer[ccLeftOver] );
if ( SUCCEEDED( pthis->_sc ) )
{
pthis->iEnd += ccRead;
ccLeftOver += ccRead;
ccRead = PAGE_SIZE / sizeof(WCHAR) - ccLeftOver;
while ( pthis->_sc == S_OK && ccRead > BUFFER_SLOP )
{
//
// Attempt to fill in as much of buffer as possible before returning
//
pthis->_sc = pthis->_pFilter->GetText( &ccRead,
(WCHAR *) &pthis->awcBuffer[ccLeftOver] );
if ( SUCCEEDED( pthis->_sc ) )
{
pthis->iEnd += ccRead;
ccLeftOver += ccRead;
ccRead = PAGE_SIZE / sizeof(WCHAR) - ccLeftOver;
}
}
#if CIDBG == 1
DebugPrintBuffer( pthis );
#endif
//
// Either return FILTER_S_LAST_TEXT or return S_OK because we have succeeded in
// adding text to the buffer
//
if ( pthis->_sc == FILTER_S_LAST_TEXT )
return FILTER_S_LAST_TEXT;
else
return S_OK;
}
}
if ( FAILED( pthis->_sc ) )
return( pthis->_sc );
if ( ccRead == 0 )
return WBREAK_E_END_OF_TEXT;
Win4Assert( pthis->iCur == 0 );
Win4Assert( pthis->iEnd == ccLeftOver );
ciDebugOut(( DEB_WORDS, "TEXT SOURCE: Fill buffer with %d characters. %d left over\n",
pthis->iEnd, ccLeftOver ));
return S_OK;
}
//+-------------------------------------------------------------------------
//
// Member: CTextSource::DebugPrintBuffer
//
// Synopsis: Debug print the text buffer
//
// Arguments: [pThis] -- Pointer to text source
//
// History: 08-Apr-97 SitaramR Created
//
//--------------------------------------------------------------------------
void CTextSource::DebugPrintBuffer( CTextSource *pthis )
{
#if CIDBG == 1
if ( ciInfoLevel & DEB_WORDS )
{
ciDebugOut(( DEB_WORDS, "CTextSource::FillBuf -- iCur = %u, iEnd = %u\n",
pthis->iCur, pthis->iEnd ));
BOOL fOk = TRUE;
for ( unsigned i = pthis->iCur; i < pthis->iEnd; i++ )
{
if ( pthis->awcBuffer[i] > 0xFF )
{
fOk = FALSE;
break;
}
}
if ( fOk )
{
unsigned j = 0;
WCHAR awcTemp[71];
for ( unsigned i = pthis->iCur; i < pthis->iEnd; i++ )
{
awcTemp[j] = pthis->awcBuffer[i];
j++;
if ( j == sizeof(awcTemp)/sizeof(awcTemp[0]) - 1 )
{
awcTemp[j] = 0;
ciDebugOut(( DEB_WORDS, "%ws\n", awcTemp ));
j = 0;
}
}
awcTemp[j] = 0;
ciDebugOut(( DEB_WORDS, "%ws\n", awcTemp ));
}
else
{
unsigned j = 0;
for ( unsigned i = pthis->iCur; i < pthis->iEnd; i++ )
{
if ( 0 == j )
ciDebugOut(( DEB_WORDS, "%04X", pthis->awcBuffer[i] ));
else if ( 14 == j )
{
ciDebugOut(( DEB_WORDS | DEB_NOCOMPNAME, " %04X\n", pthis->awcBuffer[i] ));
}
else
ciDebugOut(( DEB_WORDS | DEB_NOCOMPNAME, " %04X", pthis->awcBuffer[i] ));
j++;
if ( j > 14 )
j = 0;
}
ciDebugOut(( DEB_WORDS | DEB_NOCOMPNAME, "\n" ));
}
}
#endif
}