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.

242 lines
4.9 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: ccsv.cpp
  4. //
  5. // Module: CMPBK32.DLL
  6. //
  7. // Synopsis: Implementation of the class CCSVFile.
  8. //
  9. // Copyright (c) 1998 Microsoft Corporation
  10. //
  11. // Author: quintinb created header 08/17/99
  12. //
  13. //+----------------------------------------------------------------------------
  14. // ############################################################################
  15. // INCLUDES
  16. #include "cmmaster.h"
  17. // ############################################################################
  18. // DEFINES
  19. #define chComma ','
  20. #define chNewline '\n'
  21. #define chReturn '\r'
  22. #define chSpace ' '
  23. // ############################################################################
  24. //
  25. // CCSVFile - simple file i/o for CSV files
  26. //
  27. CCSVFile::CCSVFile()
  28. {
  29. m_hFile = INVALID_HANDLE_VALUE;
  30. m_chLastRead = 0;
  31. m_pchLast = m_pchBuf = NULL;
  32. m_fReadFail = FALSE;
  33. m_fUseLastRead = FALSE;
  34. }
  35. // ############################################################################
  36. CCSVFile::~CCSVFile()
  37. {
  38. CMASSERTMSG(m_hFile==INVALID_HANDLE_VALUE,"CCSV file is still open");
  39. }
  40. // ############################################################################
  41. BOOLEAN CCSVFile::Open(LPCSTR pszFileName)
  42. {
  43. CMASSERTMSG(m_hFile==INVALID_HANDLE_VALUE, "a file is already open.");
  44. m_hFile = CreateFile((LPCTSTR) pszFileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
  45. if (INVALID_HANDLE_VALUE == m_hFile)
  46. {
  47. return FALSE;
  48. }
  49. m_pchLast = m_pchBuf = NULL;
  50. return TRUE;
  51. }
  52. // ############################################################################
  53. BOOL CCSVFile::ClearNewLines(void)
  54. {
  55. //
  56. // This routine is designed to eat characters until a non-newline char or
  57. // the end-of-file is encountered. If a non-newline char is encountered,
  58. // the fUseLast flag is set to ensure that the next call to ChNext will
  59. // return the correct current character.
  60. //
  61. char ch = chNewline;
  62. WORD wRet;
  63. BYTE bErr;
  64. //
  65. // eat leading newlines
  66. //
  67. while (chNewline == ch)
  68. {
  69. //
  70. // eat the leading space first
  71. //
  72. do
  73. {
  74. wRet = ChNext();
  75. } while ((wRet == chSpace) || (wRet == TEXT('\t')));
  76. bErr = HIBYTE(wRet);
  77. ch = LOBYTE(wRet);
  78. // if EOF return false
  79. if (0xff == bErr)
  80. {
  81. return FALSE;
  82. }
  83. }
  84. //
  85. // we hit a character other than newline, use current char as next.
  86. //
  87. m_fUseLastRead = TRUE;
  88. return TRUE;
  89. }
  90. // ############################################################################
  91. BOOLEAN CCSVFile::ReadToken(char *psz, DWORD cbMax)
  92. {
  93. char *pszOrig = psz;
  94. DWORD dwLen = 0;
  95. char ch;
  96. BYTE bErr = 0xff;
  97. WORD wRet;
  98. wRet = ChNext();
  99. bErr = HIBYTE(wRet);
  100. ch = LOBYTE(wRet);
  101. if (0xff == bErr)
  102. {
  103. return FALSE;
  104. }
  105. // read chars until we hit a comma, newline, or run out of file
  106. while (dwLen < cbMax - 1 && chComma != ch && chNewline != ch && 0xff != bErr)
  107. {
  108. *psz++ = ch;
  109. wRet = ChNext(); //Read in the next character
  110. bErr = HIBYTE(wRet);
  111. ch = LOBYTE(wRet);
  112. dwLen++;
  113. }
  114. *psz++ = '\0';
  115. // eat leading spaces
  116. while (*pszOrig == chSpace)
  117. {
  118. lstrcpy(pszOrig,pszOrig+1);
  119. }
  120. psz = pszOrig + lstrlen(pszOrig);
  121. // eat trailing spaces
  122. while ((psz != pszOrig) && (*(psz-1) == chSpace))
  123. {
  124. psz--;
  125. *psz = 0;
  126. }
  127. return TRUE;
  128. }
  129. // ############################################################################
  130. void CCSVFile::Close(void)
  131. {
  132. if (m_hFile != INVALID_HANDLE_VALUE)
  133. {
  134. CloseHandle(m_hFile);
  135. }
  136. #ifdef DEBUG
  137. if (m_hFile==INVALID_HANDLE_VALUE)
  138. {
  139. CMTRACE("CCSVFile::Close was called, but m_hFile was already INVALID_HANDLE_VALUE\n");
  140. }
  141. #endif
  142. m_hFile = INVALID_HANDLE_VALUE;
  143. }
  144. // ############################################################################
  145. BOOL CCSVFile::ReadError(void)
  146. {
  147. return (m_fReadFail);
  148. }
  149. // ############################################################################
  150. BOOL CCSVFile::FReadInBuffer(void)
  151. {
  152. //Read another buffer
  153. if (!ReadFile(m_hFile, m_rgchBuf, CCSVFILE_BUFFER_SIZE, &m_cchAvail, NULL) || !m_cchAvail)
  154. {
  155. m_fReadFail = TRUE;
  156. return FALSE; //nothing more to read
  157. }
  158. m_pchBuf = m_rgchBuf;
  159. m_pchLast = m_pchBuf + m_cchAvail;
  160. return TRUE; //success
  161. }
  162. // ############################################################################
  163. inline WORD CCSVFile::ChNext(void)
  164. {
  165. //
  166. // If the fUseLastRead flag is set, clear the
  167. // flag and use the existing m_chLastRead
  168. //
  169. if (m_fUseLastRead)
  170. {
  171. m_fUseLastRead = FALSE;
  172. }
  173. else
  174. {
  175. //
  176. // Get the next char in the buffer. Load new buffer if necessary.
  177. //
  178. LNextChar:
  179. if (m_pchBuf >= m_pchLast && !FReadInBuffer()) //implies that we finished reading the buffer. Read in some more.
  180. {
  181. return MAKEWORD(0, 0xff); //nothing more to read
  182. }
  183. m_chLastRead = *m_pchBuf++;
  184. //
  185. // If its a carriage return, read another char
  186. //
  187. if (chReturn == m_chLastRead)
  188. {
  189. goto LNextChar; //faster to NOT make extra function call
  190. }
  191. }
  192. return MAKEWORD(m_chLastRead, 0);
  193. }