You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
413 lines
10 KiB
413 lines
10 KiB
/******************************************************************************
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
QueryResultCollection.cpp
|
|
|
|
Abstract:
|
|
This file contains the implementation of the CPCHQueryResultCollection class,
|
|
which is used to store results of queries.
|
|
|
|
Revision History:
|
|
Davide Massarenti (Dmassare) 07/26/99
|
|
created
|
|
|
|
******************************************************************************/
|
|
|
|
#include "stdafx.h"
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static const DWORD l_dwVersion = 0x02425251; // QRC 02
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
struct ElementHolder
|
|
{
|
|
CPCHQueryResult* obj;
|
|
long pos;
|
|
};
|
|
|
|
class ElementSorter
|
|
{
|
|
CPCHQueryResultCollection::SortMode m_mode;
|
|
|
|
public:
|
|
ElementSorter( /*[in]*/ CPCHQueryResultCollection::SortMode mode ) : m_mode(mode) {}
|
|
|
|
bool operator()( ElementHolder& left, ElementHolder& right )
|
|
{
|
|
const CPCHQueryResult::Payload& leftData = left .obj->GetData();
|
|
const CPCHQueryResult::Payload& rightData = right.obj->GetData();
|
|
int iCmp = 0;
|
|
|
|
//
|
|
// Priority is sorted from highest to lowest, so negate iCmp;
|
|
//
|
|
switch(m_mode)
|
|
{
|
|
case CPCHQueryResultCollection::SORT_BYCONTENTTYPE: iCmp = ( leftData.m_lType - rightData.m_lType ); break;
|
|
case CPCHQueryResultCollection::SORT_BYPRIORITY : iCmp = -( leftData.m_lPriority - rightData.m_lPriority ); break;
|
|
case CPCHQueryResultCollection::SORT_BYURL : iCmp = MPC::StrICmp( leftData.m_bstrTopicURL, rightData.m_bstrTopicURL ); break;
|
|
case CPCHQueryResultCollection::SORT_BYTITLE : iCmp = MPC::StrICmp( leftData.m_bstrTitle , rightData.m_bstrTitle ); break;
|
|
}
|
|
|
|
if(iCmp < 0) return true;
|
|
if(iCmp > 0) return false;
|
|
|
|
return (left.pos < right.pos);
|
|
}
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CPCHQueryResultCollection::CPCHQueryResultCollection()
|
|
{
|
|
// List m_results;
|
|
}
|
|
|
|
CPCHQueryResultCollection::~CPCHQueryResultCollection()
|
|
{
|
|
Erase();
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
|
|
HRESULT CPCHQueryResultCollection::MakeLocalCopyIfPossible( /*[in]*/ IPCHCollection* pRemote ,
|
|
/*[out]*/ IPCHCollection* *pLocal )
|
|
{
|
|
__HCP_FUNC_ENTRY( "CPCHQueryResultCollection::MakeLocalCopyIfPossible" );
|
|
|
|
HRESULT hr;
|
|
CComPtr<CPCHQueryResultCollection> pColl;
|
|
CComPtr<IPersistStream> persistRemote;
|
|
CComPtr<IPersistStream> persistLocal;
|
|
CComPtr<IStream> stream;
|
|
MPC::Serializer_IStream ser;
|
|
|
|
|
|
__MPC_PARAMCHECK_BEGIN(hr)
|
|
__MPC_PARAMCHECK_NOTNULL(pRemote);
|
|
__MPC_PARAMCHECK_POINTER_AND_SET(pLocal,NULL);
|
|
__MPC_PARAMCHECK_END();
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pColl ));
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pRemote->QueryInterface( IID_IPersistStream, (void**)&persistRemote ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pColl ->QueryInterface( IID_IPersistStream, (void**)&persistLocal ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, ser.GetStream ( &stream ));
|
|
|
|
//
|
|
// Convert from stream to live object.
|
|
//
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, persistRemote->Save( stream, FALSE ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, ser.Reset ( )); // Rewind stream.
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, persistLocal ->Load( stream ));
|
|
|
|
*pLocal = pColl.Detach();
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
//
|
|
// In case of failure, use the remote copy...
|
|
//
|
|
if(FAILED(hr) && pRemote && pLocal)
|
|
{
|
|
(*pLocal = pRemote)->AddRef();
|
|
}
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
|
|
STDMETHODIMP CPCHQueryResultCollection::GetClassID( /*[out]*/ CLSID *pClassID )
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
STDMETHODIMP CPCHQueryResultCollection::IsDirty()
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
STDMETHODIMP CPCHQueryResultCollection::Load( /*[in]*/ IStream *pStm )
|
|
{
|
|
MPC::Serializer_IStream stream ( pStm );
|
|
MPC::Serializer_Buffering stream2( stream );
|
|
|
|
return pStm ? Load( stream2 ) : E_POINTER;
|
|
}
|
|
|
|
STDMETHODIMP CPCHQueryResultCollection::Save( /*[in]*/ IStream *pStm, /*[in]*/ BOOL fClearDirty )
|
|
{
|
|
HRESULT hr;
|
|
MPC::Serializer_IStream stream ( pStm );
|
|
MPC::Serializer_Buffering stream2( stream );
|
|
|
|
|
|
if(pStm)
|
|
{
|
|
if(SUCCEEDED(hr = Save( stream2 ))) hr = stream2.Flush();
|
|
}
|
|
else
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CPCHQueryResultCollection::GetSizeMax( /*[out]*/ ULARGE_INTEGER *pcbSize )
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
|
|
int CPCHQueryResultCollection::Size() const
|
|
{
|
|
return m_results.size();
|
|
}
|
|
|
|
void CPCHQueryResultCollection::Erase()
|
|
{
|
|
CPCHBaseCollection::Erase();
|
|
|
|
MPC::ReleaseAll( m_results );
|
|
}
|
|
|
|
HRESULT CPCHQueryResultCollection::Load( /*[in]*/ MPC::Serializer& streamIn )
|
|
{
|
|
__HCP_FUNC_ENTRY( "CPCHQueryResultCollection::Load" );
|
|
|
|
HRESULT hr;
|
|
CComPtr<CPCHQueryResult> item;
|
|
DWORD dwVer;
|
|
int iCount;
|
|
|
|
|
|
Erase();
|
|
|
|
|
|
if(FAILED(streamIn >> dwVer ) || dwVer != l_dwVersion) __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
|
|
if(FAILED(streamIn >> iCount) ) __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
|
|
|
|
for(int i=0; i<iCount; i++)
|
|
{
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, CreateItem( &item ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, item->Load( streamIn ));
|
|
|
|
item.Release();
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT CPCHQueryResultCollection::Save( /*[in]*/ MPC::Serializer& streamOut ) const
|
|
{
|
|
__HCP_FUNC_ENTRY( "CPCHQueryResultCollection::Save" );
|
|
|
|
HRESULT hr;
|
|
Iter it;
|
|
DWORD dwVer = l_dwVersion;
|
|
int iCount = m_results.size();
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, streamOut << dwVer );
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, streamOut << iCount );
|
|
|
|
for(it = m_results.begin(); it != m_results.end(); it++)
|
|
{
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, (*it)->Save( streamOut ));
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT CPCHQueryResultCollection::CreateItem( /*[out]*/ CPCHQueryResult* *item )
|
|
{
|
|
__HCP_FUNC_ENTRY( "CPCHQueryResultCollection::CreateItem" );
|
|
|
|
HRESULT hr;
|
|
CComPtr<CPCHQueryResult> hpcqr;
|
|
|
|
__MPC_PARAMCHECK_BEGIN(hr)
|
|
__MPC_PARAMCHECK_POINTER_AND_SET(item,NULL);
|
|
__MPC_PARAMCHECK_END();
|
|
|
|
|
|
//
|
|
// Create a new item and link it to the system.
|
|
//
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &hpcqr )); (*item = hpcqr)->AddRef();
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, AddItem( hpcqr ));
|
|
|
|
m_results.push_back( hpcqr.Detach() );
|
|
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT CPCHQueryResultCollection::GetItem( /*[in]*/ long lPos, /*[out]*/ CPCHQueryResult* *item )
|
|
{
|
|
__HCP_FUNC_ENTRY( "CPCHQueryResultCollection::GetItem" );
|
|
|
|
HRESULT hr;
|
|
Iter it;
|
|
|
|
__MPC_PARAMCHECK_BEGIN(hr)
|
|
__MPC_PARAMCHECK_POINTER_AND_SET(item,NULL);
|
|
__MPC_PARAMCHECK_END();
|
|
|
|
it = m_results.begin();
|
|
while(1)
|
|
{
|
|
if(it == m_results.end())
|
|
{
|
|
__MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
|
|
}
|
|
|
|
if(lPos-- == 0) break;
|
|
|
|
it++;
|
|
}
|
|
|
|
(*item = *it)->AddRef();
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT CPCHQueryResultCollection::LoadFromCache( /*[in]*/ IStream* stream )
|
|
{
|
|
__HCP_FUNC_ENTRY( "CPCHQueryResultCollection::LoadFromCache" );
|
|
|
|
HRESULT hr;
|
|
MPC::Serializer_IStream streamReal( stream );
|
|
MPC::Serializer_Buffering streamBuf ( streamReal );
|
|
|
|
|
|
Erase();
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, Load( streamBuf ));
|
|
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT CPCHQueryResultCollection::SaveToCache( /*[in]*/ IStream* stream ) const
|
|
{
|
|
__HCP_FUNC_ENTRY( "CPCHQueryResultCollection::SaveToCache" );
|
|
|
|
HRESULT hr;
|
|
MPC::Serializer_IStream streamReal( stream );
|
|
MPC::Serializer_Buffering streamBuf ( streamReal );
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, Save( streamBuf ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf.Flush());
|
|
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT CPCHQueryResultCollection::Sort( /*[in]*/ SortMode mode, /*[in]*/ int iLimit )
|
|
{
|
|
__HCP_FUNC_ENTRY( "CPCHQueryResultCollection::Sort" );
|
|
|
|
HRESULT hr;
|
|
ElementHolder* ptr;
|
|
ElementHolder* rgBuf = NULL;
|
|
int iSize = m_results.size();
|
|
int i;
|
|
|
|
if(iSize > 1)
|
|
{
|
|
ElementSorter sorted( mode );
|
|
Iter it;
|
|
|
|
__MPC_EXIT_IF_ALLOC_FAILS(hr, rgBuf, new ElementHolder[iSize]);
|
|
|
|
for(i=0, ptr=rgBuf, it=m_results.begin(); i<iSize && it!=m_results.end(); i++, ptr++, it++)
|
|
{
|
|
CPCHQueryResult* obj = *it;
|
|
|
|
ptr->obj = obj; obj->AddRef();
|
|
ptr->pos = i;
|
|
}
|
|
|
|
std::sort( rgBuf, ptr, sorted );
|
|
|
|
if(iLimit < 0 || iLimit > iSize) iLimit = iSize;
|
|
|
|
Erase();
|
|
for(i=0, ptr=rgBuf; i<iLimit; i++, ptr++)
|
|
{
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, AddItem( ptr->obj ));
|
|
|
|
m_results.push_back( ptr->obj ); ptr->obj = NULL;
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
if(rgBuf)
|
|
{
|
|
for(i=0, ptr=rgBuf; i<iSize; i++, ptr++)
|
|
{
|
|
if(ptr->obj) ptr->obj->Release();
|
|
}
|
|
|
|
delete [] rgBuf;
|
|
}
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|