Source code of Windows XP (NT5)
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.

280 lines
7.6 KiB

  1. // Copyright (C) 1996-1997 Microsoft Corporation. All rights reserved.
  2. #include "header.h"
  3. #include "cinput.h"
  4. #include "system.h"
  5. #include "toc.h"
  6. #ifndef _DEBUG
  7. #pragma optimize("a", on)
  8. #endif
  9. const int INPUT_BUF_SIZE = (16 * 1024);
  10. CInput::CInput()
  11. {
  12. m_pfsClient = NULL;
  13. m_pbuf = NULL;
  14. m_hfile = INVALID_HANDLE_VALUE;
  15. }
  16. CInput::CInput(LPCSTR pszFile)
  17. {
  18. m_pfsClient = NULL;
  19. m_pbuf = NULL;
  20. m_hfile = INVALID_HANDLE_VALUE;
  21. Open(pszFile);
  22. }
  23. BOOL
  24. CInput::isInitialized()
  25. {
  26. return (m_pbuf != NULL && (m_hfile != INVALID_HANDLE_VALUE || m_pfsClient != NULL));
  27. }
  28. BOOL CInput::Open(PCSTR pszFile, CHmData* phmData)
  29. {
  30. CStr csz;
  31. if (phmData && !stristr(pszFile, txtDoubleColonSep) &&
  32. !stristr(pszFile, txtFileHeader) && !stristr(pszFile, txtHttpHeader)) {
  33. csz = phmData->GetCompiledFile();
  34. csz += txtDoubleColonSep;
  35. csz += pszFile;
  36. pszFile = csz.psz;
  37. }
  38. Close();
  39. // Is this a compiled HTML file?
  40. CStr cszCompiled;
  41. if (IsCompiledHtmlFile(pszFile, &cszCompiled)) {
  42. m_pfsClient = new CFSClient;
  43. CStr cszFind;
  44. PCSTR pszSubFile = GetCompiledName(cszCompiled, &cszFind);
  45. // Check if we have a valid subfile name.
  46. if (!pszSubFile || pszSubFile[0] == '\0')
  47. {
  48. Close() ;
  49. return FALSE ;
  50. }
  51. for (int i = 0; i < g_cHmSlots; i++) {
  52. if (g_phmData[i] &&
  53. lstrcmpi(cszFind, g_phmData[i]->GetCompiledFile()) == 0)
  54. break;
  55. }
  56. if (i < g_cHmSlots) {
  57. CExTitle* pTitle = g_phmData[i]->m_pTitleCollection->GetFirstTitle();
  58. if (pTitle->isChiFile())
  59. m_pfsClient->Initialize(cszFind);
  60. else
  61. m_pfsClient->Initialize(g_phmData[i]->m_pTitleCollection->GetFirstTitle()->GetFileSystem());
  62. if (FAILED(m_pfsClient->OpenStream(pszSubFile)))
  63. {
  64. Close();
  65. return FALSE;
  66. }
  67. }
  68. else if (!m_pfsClient->Initialize(cszCompiled)) {
  69. Close();
  70. return FALSE;
  71. }
  72. m_hfile = (HANDLE) 1;
  73. }
  74. else {
  75. m_pfsClient = NULL;
  76. m_hfile = CreateFile(pszFile, GENERIC_READ, FILE_SHARE_READ,
  77. NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  78. if (m_hfile == INVALID_HANDLE_VALUE) {
  79. Close();
  80. return FALSE;
  81. }
  82. }
  83. m_pbuf = (PBYTE) lcMalloc(INPUT_BUF_SIZE + 4);
  84. m_pbuf[INPUT_BUF_SIZE + 1] = 0; // so we can search
  85. // Position current buffer at end to force a read
  86. m_pCurBuf = m_pEndBuf = m_pbuf + INPUT_BUF_SIZE;
  87. fFastRead = FALSE;
  88. return TRUE;
  89. }
  90. CInput::~CInput(void)
  91. {
  92. Close();
  93. }
  94. void CInput::Close()
  95. {
  96. if (m_pfsClient) {
  97. delete m_pfsClient;
  98. m_pfsClient = NULL;
  99. }
  100. else if (m_hfile != INVALID_HANDLE_VALUE) {
  101. CloseHandle(m_hfile);
  102. }
  103. m_hfile = INVALID_HANDLE_VALUE;
  104. if (m_pbuf)
  105. lcClearFree(&m_pbuf);
  106. }
  107. /***************************************************************************
  108. FUNCTION: CInput::getline
  109. PURPOSE: Reads a line into a CStr buffer, increasing that buffer
  110. as necessary to hold the line.
  111. PARAMETERS:
  112. pcsz CStr pointer
  113. RETURNS:
  114. COMMENTS:
  115. This function relies HEAVILY on the implementation of the CStr
  116. class, namely in CStr's use of lcmem functions.
  117. MODIFICATION DATES:
  118. 05-Sep-1994 [ralphw]
  119. ***************************************************************************/
  120. BOOL CInput::getline(CStr* pcsz)
  121. {
  122. // Only read the line if we are initialized.
  123. if (!isInitialized())
  124. return FALSE ;
  125. if (!pcsz->psz)
  126. pcsz->psz = (PSTR) lcMalloc(256);
  127. PSTR pszDst = pcsz->psz;
  128. PSTR pszEnd = pszDst + lcSize(pszDst);
  129. /*
  130. * If we previously saw a \r then we are going to assume we will see
  131. * files with \r\n, which means we can do a fast search to find the first
  132. * occurence of \r, copy everything up to that character into the
  133. * destination buffer, and the continue normally. This will die horribly
  134. * if there's only one \r in a file...
  135. */
  136. if (fFastRead) {
  137. if (m_pCurBuf >= m_pEndBuf) {
  138. if (!ReadNextBuffer()) {
  139. // End of file: return TRUE if we got any text.
  140. if (pszDst > pcsz->psz) {
  141. *pszDst = '\0';
  142. return TRUE;
  143. }
  144. else
  145. return FALSE;
  146. }
  147. }
  148. PCSTR psz = StrChr((PCSTR) m_pCurBuf, '\r');
  149. if (psz) {
  150. INT_PTR cb = psz - (PCSTR) m_pCurBuf;
  151. while (pszDst + cb >= pszEnd) {
  152. /*
  153. * Our input buffer is too small, so increase it by
  154. * 128 bytes.
  155. */
  156. INT_PTR offset = (pszDst - pcsz->psz);
  157. pcsz->ReSize((int)(pszEnd - pcsz->psz) + 128);
  158. pszDst = pcsz->psz + offset;
  159. pszEnd = pcsz->psz + pcsz->SizeAlloc();
  160. }
  161. memcpy(pszDst, m_pCurBuf, (int)cb);
  162. pszDst += cb;
  163. m_pCurBuf += (cb + 1); // skip over the \r
  164. }
  165. }
  166. for (;;) {
  167. if (m_pCurBuf >= m_pEndBuf) {
  168. if (!ReadNextBuffer()) {
  169. // End of file: return TRUE if we got any text.
  170. if (pszDst > pcsz->psz) {
  171. *pszDst = '\0';
  172. return TRUE;
  173. }
  174. else
  175. return FALSE;
  176. }
  177. }
  178. switch (*pszDst = *m_pCurBuf++) {
  179. case '\n':
  180. if (pszDst > pcsz->psz) {
  181. while (pszDst[-1] == ' ') { // remove trailing spaces
  182. pszDst--;
  183. if (pszDst == pcsz->psz)
  184. break;
  185. }
  186. }
  187. *pszDst = '\0';
  188. return TRUE;
  189. case '\r':
  190. fFastRead = TRUE;
  191. break; // ignore it
  192. case 0: // This shouldn't happen in a text file
  193. /*
  194. * Check to see if this is a WinWord file. This test is
  195. * not definitve, but catches most .doc format files.
  196. */
  197. if ((m_pbuf[0] == 0xdb || m_pbuf[0] == 0xd0) &&
  198. (m_pbuf[1] == 0xa5 || m_pbuf[1] == 0xcf)) {
  199. return FALSE;
  200. }
  201. break;
  202. default:
  203. pszDst++;
  204. if (pszDst == pszEnd) {
  205. /*
  206. * Our input buffer is too small, so increase it by
  207. * 128 bytes.
  208. */
  209. INT_PTR offset = (pszDst - pcsz->psz);
  210. pcsz->ReSize((int)(pszEnd - pcsz->psz) + 128);
  211. pszDst = pcsz->psz + offset;
  212. pszEnd = pcsz->psz + pcsz->SizeAlloc();
  213. }
  214. break;
  215. }
  216. }
  217. }
  218. BOOL CInput::ReadNextBuffer(void)
  219. {
  220. DWORD cbRead;
  221. // Only read the line if we are initialized.
  222. if (!isInitialized())
  223. return FALSE ;
  224. if (m_pfsClient) {
  225. if (!SUCCEEDED(m_pfsClient->Read(m_pbuf, INPUT_BUF_SIZE, (ULONG*) &cbRead)) ||
  226. cbRead == 0)
  227. return FALSE;
  228. }
  229. else {
  230. if (!ReadFile(m_hfile, m_pbuf, INPUT_BUF_SIZE, &cbRead, NULL) || !cbRead)
  231. return FALSE;
  232. }
  233. m_pCurBuf = m_pbuf;
  234. m_pEndBuf = m_pbuf + cbRead;
  235. *m_pEndBuf = '\0'; // so we can search
  236. return TRUE;
  237. }