// 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; }