234 lines
4.8 KiB
C++
234 lines
4.8 KiB
C++
// Copyright (C) 1997 Microsoft Corporation. All rights reserved.
|
|
|
|
#include "header.h"
|
|
|
|
#include "subfile.h"
|
|
#include "fs.h"
|
|
#include "toc.h"
|
|
|
|
static CPagesList listSubfiles;
|
|
|
|
//////////////////////////////////////////////
|
|
//
|
|
// CPagesList
|
|
//
|
|
//////////////////////////////////////////////
|
|
|
|
CPagesList::~CPagesList()
|
|
{
|
|
CPages* p;
|
|
|
|
while (p = m_pFirst)
|
|
{
|
|
m_pFirst = p->m_pNext;
|
|
delete p;
|
|
}
|
|
}
|
|
|
|
CPages* CPagesList::GetPages( HASH hash )
|
|
{
|
|
CPages * p;
|
|
|
|
for (p = m_pFirst; p; p = p->m_pNext)
|
|
if ( hash == p->m_hash )
|
|
return p;
|
|
|
|
p = new CPages( hash );
|
|
p->m_pNext = m_pFirst;
|
|
m_pFirst = p;
|
|
|
|
return p;
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
//
|
|
// CPages
|
|
//
|
|
////////////////////////////////////////
|
|
|
|
CPages::CPages( HASH hash )
|
|
{
|
|
m_pNext = 0;
|
|
m_hash = hash;
|
|
Flush();
|
|
}
|
|
|
|
void* CPages::Find(const CExTitle * pTitle, HASH hashPathname, DWORD dwPage)
|
|
{
|
|
int i;
|
|
|
|
for( i = 0; i < CACHE_PAGE_COUNT; i++ )
|
|
{
|
|
// test if lowest LRU
|
|
if( m_pages[i].dwLRU < m_pages[m_dwLRUPage].dwLRU ) {
|
|
m_dwLRUPage = i;
|
|
}
|
|
|
|
if( m_pages[i].dwLRU &&
|
|
m_pages[i].hashPathname == hashPathname &&
|
|
m_pages[i].dwPage == dwPage &&
|
|
m_pages[i].pTitle == pTitle )
|
|
{
|
|
m_pages[i].dwLRU = ++m_dwLRUCount; // update LRU
|
|
return m_pages[i].rgb;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void* CPages::Alloc(CExTitle * pTitle, HASH hashPathname, DWORD dwPage)
|
|
{
|
|
// if we reached the max LRU number then flush the cache and start over
|
|
if( m_dwLRUCount == ((DWORD) -1) )
|
|
Flush();
|
|
|
|
m_pages[m_dwLRUPage].dwLRU = ++m_dwLRUCount;
|
|
m_pages[m_dwLRUPage].hashPathname = hashPathname;
|
|
m_pages[m_dwLRUPage].dwPage = dwPage;
|
|
m_pages[m_dwLRUPage].pTitle = pTitle;
|
|
|
|
return m_pages[m_dwLRUPage].rgb;
|
|
}
|
|
|
|
void CPages::Flush(void)
|
|
{
|
|
int i;
|
|
|
|
for( i = 0; i < CACHE_PAGE_COUNT; i++ )
|
|
m_pages[i].dwLRU = 0;
|
|
m_dwLRUPage = 0;
|
|
m_dwLRUCount = 0;
|
|
}
|
|
|
|
void CPages::Flush( CExTitle* pTitle )
|
|
{
|
|
if( !pTitle )
|
|
return;
|
|
|
|
int i;
|
|
|
|
for( i = 0; i < CACHE_PAGE_COUNT; i++ )
|
|
if( m_pages[i].pTitle == pTitle )
|
|
m_pages[i].dwLRU = 0;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////
|
|
//
|
|
// CPagedSubfile
|
|
//
|
|
//////////////////////////////////////////////
|
|
|
|
CPagedSubfile::CPagedSubfile()
|
|
{
|
|
m_pCSubFileSystem = 0; // type CSubFileSystem from fs.h/fs.cpp
|
|
m_pTitle = 0;
|
|
m_pPages = 0;
|
|
m_cbSize = 0xFFFFFFFF;
|
|
}
|
|
|
|
CPagedSubfile::~CPagedSubfile()
|
|
{
|
|
if ( m_pCSubFileSystem )
|
|
delete m_pCSubFileSystem;
|
|
|
|
// flush all of its owned pages since
|
|
// the same pTitle value may be re-used and thus
|
|
// the cache is invalid
|
|
m_pPages->Flush( m_pTitle );
|
|
}
|
|
|
|
HRESULT CPagedSubfile::Open(CExTitle * pTitle, LPCSTR lpsz)
|
|
{
|
|
if (m_pCSubFileSystem || m_pTitle || m_pPages || !pTitle->m_pCFileSystem )
|
|
return E_FAIL;
|
|
|
|
m_pTitle = pTitle;
|
|
|
|
// hash the filename
|
|
m_hashPathname = HashFromSz( lpsz );
|
|
|
|
#ifdef _DEBUG
|
|
char sz[1024];
|
|
wsprintf( sz, "Hash:%d File:%s\n", m_hashPathname, lpsz );
|
|
OutputDebugString( sz );
|
|
#endif
|
|
|
|
#if defined( HH_FAST_CACHE )
|
|
// keep CACHE_PAGE_COUNT small (2-3) and hash the title and the filename
|
|
char szHash[MAX_PATH*2];
|
|
strcpy( szHash, pTitle->GetInfo2()->GetShortName() );
|
|
strcat( szHash, "::" );
|
|
strcat( szHash, lpsz );
|
|
m_hash = HashFromSz( szHash );
|
|
#elif defined ( HH_EFFICIENT_CACHE )
|
|
// keep CACHE_PAGE_COUNT moderately low (3-5) and hash just the filename
|
|
m_hash = HashFromSz( lpsz );
|
|
#else // HH_SHARED_CACHE
|
|
// keep CACHE_PAGE_COUNT high (30+) and have only one shared cache group
|
|
m_hash = HashFromSz( "HTMLHelpSharedCache" );
|
|
#endif
|
|
|
|
if (!(m_pPages = listSubfiles.GetPages(m_hash)))
|
|
return E_FAIL;
|
|
|
|
m_pCSubFileSystem = new CSubFileSystem(pTitle->m_pCFileSystem);
|
|
|
|
if(FAILED(m_pCSubFileSystem->OpenSub(lpsz)))
|
|
{
|
|
delete m_pCSubFileSystem;
|
|
m_pCSubFileSystem = NULL;
|
|
return E_FAIL;
|
|
}
|
|
m_cbSize = m_pCSubFileSystem->GetUncompressedSize();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void* CPagedSubfile::Offset(DWORD dwOffs)
|
|
{
|
|
DWORD dwPage;
|
|
void* pv;
|
|
|
|
if (dwOffs >= m_cbSize)
|
|
return NULL;
|
|
|
|
dwPage = dwOffs / PAGE_SIZE;
|
|
|
|
dwOffs -= (dwPage * PAGE_SIZE);
|
|
|
|
if (pv = Page(dwPage))
|
|
return (BYTE*)pv + dwOffs;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
void* CPagedSubfile::Page(DWORD dwPage)
|
|
{
|
|
void* pv;
|
|
|
|
if (pv = m_pPages->Find(m_pTitle, m_hashPathname, dwPage))
|
|
return pv;
|
|
|
|
if (!(pv = m_pPages->Alloc(m_pTitle, m_hashPathname, dwPage)))
|
|
return NULL;
|
|
|
|
DWORD li = dwPage * PAGE_SIZE;
|
|
|
|
if ( m_pCSubFileSystem->SeekSub(li,0) != li )
|
|
return NULL;
|
|
|
|
// init the page in case we don't read it all...
|
|
//
|
|
#ifdef _DEBUG
|
|
memset(pv,0xFF,PAGE_SIZE);
|
|
#endif
|
|
|
|
ULONG cb;
|
|
if (FAILED(m_pCSubFileSystem->ReadSub(pv, PAGE_SIZE, &cb)))
|
|
return NULL;
|
|
|
|
return pv;
|
|
}
|