WindowsXP-SP1/enduser/stuff/hhctrl/cinput.cpp

281 lines
7.8 KiB
C++

// Copyright (C) 1996-1997 Microsoft Corporation. All rights reserved.
#include "header.h"
#include "cinput.h"
#include "system.h"
#include "toc.h"
#ifndef _DEBUG
#pragma optimize("a", on)
#endif
const int INPUT_BUF_SIZE = (16 * 1024);
CInput::CInput()
{
m_pfsClient = NULL;
m_pbuf = NULL;
m_hfile = INVALID_HANDLE_VALUE;
}
CInput::CInput(LPCSTR pszFile)
{
m_pfsClient = NULL;
m_pbuf = NULL;
m_hfile = INVALID_HANDLE_VALUE;
Open(pszFile);
}
BOOL
CInput::isInitialized()
{
return (m_pbuf != NULL && (m_hfile != INVALID_HANDLE_VALUE || m_pfsClient != NULL));
}
BOOL CInput::Open(PCSTR pszFile, CHmData* phmData)
{
CStr csz;
if (phmData && !stristr(pszFile, txtDoubleColonSep) &&
!stristr(pszFile, txtFileHeader) && !stristr(pszFile, txtHttpHeader)) {
csz = phmData->GetCompiledFile();
csz += txtDoubleColonSep;
csz += pszFile;
pszFile = csz.psz;
}
Close();
// Is this a compiled HTML file?
CStr cszCompiled;
if (IsCompiledHtmlFile(pszFile, &cszCompiled)) {
m_pfsClient = new CFSClient;
CStr cszFind;
PCSTR pszSubFile = GetCompiledName(cszCompiled, &cszFind);
// Check if we have a valid subfile name.
if (!pszSubFile || pszSubFile[0] == '\0')
{
Close() ;
return FALSE ;
}
for (int i = 0; i < g_cHmSlots; i++) {
if (g_phmData[i] &&
lstrcmpi(cszFind, g_phmData[i]->GetCompiledFile()) == 0)
break;
}
if (i < g_cHmSlots) {
CExTitle* pTitle = g_phmData[i]->m_pTitleCollection->GetFirstTitle();
if (pTitle->isChiFile())
m_pfsClient->Initialize(cszFind);
else
m_pfsClient->Initialize(g_phmData[i]->m_pTitleCollection->GetFirstTitle()->GetFileSystem());
if (FAILED(m_pfsClient->OpenStream(pszSubFile)))
{
Close();
return FALSE;
}
}
else if (!m_pfsClient->Initialize(cszCompiled)) {
Close();
return FALSE;
}
m_hfile = (HANDLE) 1;
}
else {
m_pfsClient = NULL;
m_hfile = CreateFile(pszFile, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (m_hfile == INVALID_HANDLE_VALUE) {
Close();
return FALSE;
}
}
m_pbuf = (PBYTE) lcMalloc(INPUT_BUF_SIZE + 4);
m_pbuf[INPUT_BUF_SIZE + 1] = 0; // so we can search
// Position current buffer at end to force a read
m_pCurBuf = m_pEndBuf = m_pbuf + INPUT_BUF_SIZE;
fFastRead = FALSE;
return TRUE;
}
CInput::~CInput(void)
{
Close();
}
void CInput::Close()
{
if (m_pfsClient) {
delete m_pfsClient;
m_pfsClient = NULL;
}
else if (m_hfile != INVALID_HANDLE_VALUE) {
CloseHandle(m_hfile);
}
m_hfile = INVALID_HANDLE_VALUE;
if (m_pbuf)
lcClearFree(&m_pbuf);
}
/***************************************************************************
FUNCTION: CInput::getline
PURPOSE: Reads a line into a CStr buffer, increasing that buffer
as necessary to hold the line.
PARAMETERS:
pcsz CStr pointer
RETURNS:
COMMENTS:
This function relies HEAVILY on the implementation of the CStr
class, namely in CStr's use of lcmem functions.
MODIFICATION DATES:
05-Sep-1994 [ralphw]
***************************************************************************/
BOOL CInput::getline(CStr* pcsz)
{
// Only read the line if we are initialized.
if (!isInitialized())
return FALSE ;
if (!pcsz->psz)
pcsz->psz = (PSTR) lcMalloc(256);
PSTR pszDst = pcsz->psz;
PSTR pszEnd = pszDst + lcSize(pszDst);
/*
* If we previously saw a \r then we are going to assume we will see
* files with \r\n, which means we can do a fast search to find the first
* occurence of \r, copy everything up to that character into the
* destination buffer, and the continue normally. This will die horribly
* if there's only one \r in a file...
*/
if (fFastRead) {
if (m_pCurBuf >= m_pEndBuf) {
if (!ReadNextBuffer()) {
// End of file: return TRUE if we got any text.
if (pszDst > pcsz->psz) {
*pszDst = '\0';
return TRUE;
}
else
return FALSE;
}
}
PCSTR psz = StrChr((PCSTR) m_pCurBuf, '\r');
if (psz) {
INT_PTR cb = psz - (PCSTR) m_pCurBuf;
while (pszDst + cb >= pszEnd) {
/*
* Our input buffer is too small, so increase it by
* 128 bytes.
*/
INT_PTR offset = (pszDst - pcsz->psz);
pcsz->ReSize((int)(pszEnd - pcsz->psz) + 128);
pszDst = pcsz->psz + offset;
pszEnd = pcsz->psz + pcsz->SizeAlloc();
}
memcpy(pszDst, m_pCurBuf, (int)cb);
pszDst += cb;
m_pCurBuf += (cb + 1); // skip over the \r
}
}
for (;;) {
if (m_pCurBuf >= m_pEndBuf) {
if (!ReadNextBuffer()) {
// End of file: return TRUE if we got any text.
if (pszDst > pcsz->psz) {
*pszDst = '\0';
return TRUE;
}
else
return FALSE;
}
}
switch (*pszDst = *m_pCurBuf++) {
case '\n':
if (pszDst > pcsz->psz) {
while (pszDst[-1] == ' ') { // remove trailing spaces
pszDst--;
if (pszDst == pcsz->psz)
break;
}
}
*pszDst = '\0';
return TRUE;
case '\r':
fFastRead = TRUE;
break; // ignore it
case 0: // This shouldn't happen in a text file
/*
* Check to see if this is a WinWord file. This test is
* not definitve, but catches most .doc format files.
*/
if ((m_pbuf[0] == 0xdb || m_pbuf[0] == 0xd0) &&
(m_pbuf[1] == 0xa5 || m_pbuf[1] == 0xcf)) {
return FALSE;
}
break;
default:
pszDst++;
if (pszDst == pszEnd) {
/*
* Our input buffer is too small, so increase it by
* 128 bytes.
*/
INT_PTR offset = (pszDst - pcsz->psz);
pcsz->ReSize((int)(pszEnd - pcsz->psz) + 128);
pszDst = pcsz->psz + offset;
pszEnd = pcsz->psz + pcsz->SizeAlloc();
}
break;
}
}
}
BOOL CInput::ReadNextBuffer(void)
{
DWORD cbRead;
// Only read the line if we are initialized.
if (!isInitialized())
return FALSE ;
if (m_pfsClient) {
if (!SUCCEEDED(m_pfsClient->Read(m_pbuf, INPUT_BUF_SIZE, (ULONG*) &cbRead)) ||
cbRead == 0)
return FALSE;
}
else {
if (!ReadFile(m_hfile, m_pbuf, INPUT_BUF_SIZE, &cbRead, NULL) || !cbRead)
return FALSE;
}
m_pCurBuf = m_pbuf;
m_pEndBuf = m_pbuf + cbRead;
*m_pEndBuf = '\0'; // so we can search
return TRUE;
}