home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / filetxt.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  8KB  |  336 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12. #include <errno.h>
  13. #include <io.h>
  14. #include <fcntl.h>
  15.  
  16. #ifdef AFX_CORE1_SEG
  17. #pragma code_seg(AFX_CORE1_SEG)
  18. #endif
  19.  
  20. #ifdef _DEBUG
  21. #undef THIS_FILE
  22. static char THIS_FILE[] = __FILE__;
  23. #endif
  24.  
  25. #define new DEBUG_NEW
  26.  
  27. ////////////////////////////////////////////////////////////////////////////
  28. // CStdioFile implementation
  29.  
  30. CStdioFile::CStdioFile()
  31. {
  32.     m_pStream = NULL;
  33. }
  34.  
  35. CStdioFile::CStdioFile(FILE* pOpenStream) : CFile(hFileNull)
  36. {
  37.     m_pStream = pOpenStream;
  38.     m_hFile = (UINT)_get_osfhandle(_fileno(pOpenStream));
  39.     ASSERT(!m_bCloseOnDelete);
  40. }
  41.  
  42. CStdioFile::CStdioFile(LPCTSTR lpszFileName, UINT nOpenFlags)
  43. {
  44.     ASSERT(lpszFileName != NULL);
  45.     ASSERT(AfxIsValidString(lpszFileName));
  46.  
  47.     CFileException e;
  48.     if (!Open(lpszFileName, nOpenFlags, &e))
  49.         AfxThrowFileException(e.m_cause, e.m_lOsError, e.m_strFileName);
  50. }
  51.  
  52. CStdioFile::~CStdioFile()
  53. {
  54.     ASSERT_VALID(this);
  55.  
  56.     if (m_pStream != NULL && m_bCloseOnDelete)
  57.         Close();
  58. }
  59.  
  60. BOOL CStdioFile::Open(LPCTSTR lpszFileName, UINT nOpenFlags,
  61.     CFileException* pException)
  62. {
  63.     ASSERT(pException == NULL || AfxIsValidAddress(pException, sizeof(CFileException)));
  64.     ASSERT(lpszFileName != NULL);
  65.     ASSERT(AfxIsValidString(lpszFileName));
  66.  
  67.     m_pStream = NULL;
  68.     if (!CFile::Open(lpszFileName, (nOpenFlags & ~typeText), pException))
  69.         return FALSE;
  70.  
  71.     ASSERT(m_hFile != hFileNull);
  72.     ASSERT(m_bCloseOnDelete);
  73.  
  74.     char szMode[4]; // C-runtime open string
  75.     int nMode = 0;
  76.  
  77.     // determine read/write mode depending on CFile mode
  78.     if (nOpenFlags & modeCreate)
  79.     {
  80.         if (nOpenFlags & modeNoTruncate)
  81.             szMode[nMode++] = 'a';
  82.         else
  83.             szMode[nMode++] = 'w';
  84.     }
  85.     else if (nOpenFlags & modeWrite)
  86.         szMode[nMode++] = 'a';
  87.     else
  88.         szMode[nMode++] = 'r';
  89.  
  90.     // add '+' if necessary (when read/write modes mismatched)
  91.     if (szMode[0] == 'r' && (nOpenFlags & modeReadWrite) ||
  92.         szMode[0] != 'r' && !(nOpenFlags & modeWrite))
  93.     {
  94.         // current szMode mismatched, need to add '+' to fix
  95.         szMode[nMode++] = '+';
  96.     }
  97.  
  98.     // will be inverted if not necessary
  99.     int nFlags = _O_RDONLY|_O_TEXT;
  100.     if (nOpenFlags & (modeWrite|modeReadWrite))
  101.         nFlags ^= _O_RDONLY;
  102.  
  103.     if (nOpenFlags & typeBinary)
  104.         szMode[nMode++] = 'b', nFlags ^= _O_TEXT;
  105.     else
  106.         szMode[nMode++] = 't';
  107.     szMode[nMode++] = '\0';
  108.  
  109.     // open a C-runtime low-level file handle
  110.     int nHandle = _open_osfhandle(m_hFile, nFlags);
  111.  
  112.     // open a C-runtime stream from that handle
  113.     if (nHandle != -1)
  114.         m_pStream = _fdopen(nHandle, szMode);
  115.  
  116.     if (m_pStream == NULL)
  117.     {
  118.         // an error somewhere along the way...
  119.         if (pException != NULL)
  120.         {
  121.             pException->m_lOsError = _doserrno;
  122.             pException->m_cause = CFileException::OsErrorToException(_doserrno);
  123.         }
  124.  
  125.         CFile::Abort(); // close m_hFile
  126.         return FALSE;
  127.     }
  128.  
  129.     return TRUE;
  130. }
  131.  
  132. UINT CStdioFile::Read(void* lpBuf, UINT nCount)
  133. {
  134.     ASSERT_VALID(this);
  135.     ASSERT(m_pStream != NULL);
  136.  
  137.     if (nCount == 0)
  138.         return 0;   // avoid Win32 "null-read"
  139.  
  140.     ASSERT(AfxIsValidAddress(lpBuf, nCount));
  141.  
  142.     UINT nRead = 0;
  143.  
  144.     if ((nRead = fread(lpBuf, sizeof(BYTE), nCount, m_pStream)) == 0 && !feof(m_pStream))
  145.         AfxThrowFileException(CFileException::generic, _doserrno, m_strFileName);
  146.     if (ferror(m_pStream))
  147.     {
  148.         clearerr(m_pStream);
  149.         AfxThrowFileException(CFileException::generic, _doserrno, m_strFileName);
  150.     }
  151.     return nRead;
  152. }
  153.  
  154. void CStdioFile::Write(const void* lpBuf, UINT nCount)
  155. {
  156.     ASSERT_VALID(this);
  157.     ASSERT(m_pStream != NULL);
  158.     ASSERT(AfxIsValidAddress(lpBuf, nCount, FALSE));
  159.  
  160.     if (fwrite(lpBuf, sizeof(BYTE), nCount, m_pStream) != nCount)
  161.         AfxThrowFileException(CFileException::generic, _doserrno, m_strFileName);
  162. }
  163.  
  164. void CStdioFile::WriteString(LPCTSTR lpsz)
  165. {
  166.     ASSERT(lpsz != NULL);
  167.     ASSERT(m_pStream != NULL);
  168.  
  169.     if (_fputts(lpsz, m_pStream) == _TEOF)
  170.         AfxThrowFileException(CFileException::diskFull, _doserrno, m_strFileName);
  171. }
  172.  
  173. LPTSTR CStdioFile::ReadString(LPTSTR lpsz, UINT nMax)
  174. {
  175.     ASSERT(lpsz != NULL);
  176.     ASSERT(AfxIsValidAddress(lpsz, nMax));
  177.     ASSERT(m_pStream != NULL);
  178.  
  179.     LPTSTR lpszResult = _fgetts(lpsz, nMax, m_pStream);
  180.     if (lpszResult == NULL && !feof(m_pStream))
  181.     {
  182.         clearerr(m_pStream);
  183.         AfxThrowFileException(CFileException::generic, _doserrno, m_strFileName);
  184.     }
  185.     return lpszResult;
  186. }
  187.  
  188. BOOL CStdioFile::ReadString(CString& rString)
  189. {
  190.     ASSERT_VALID(this);
  191.  
  192.     rString = &afxChNil;    // empty string without deallocating
  193.     const int nMaxSize = 128;
  194.     LPTSTR lpsz = rString.GetBuffer(nMaxSize);
  195.     LPTSTR lpszResult;
  196.     int nLen = 0;
  197.     for (;;)
  198.     {
  199.         lpszResult = _fgetts(lpsz, nMaxSize+1, m_pStream);
  200.         rString.ReleaseBuffer();
  201.  
  202.         // handle error/eof case
  203.         if (lpszResult == NULL && !feof(m_pStream))
  204.         {
  205.             clearerr(m_pStream);
  206.             AfxThrowFileException(CFileException::generic, _doserrno,
  207.                 m_strFileName);
  208.         }
  209.  
  210.         // if string is read completely or EOF
  211.         if (lpszResult == NULL ||
  212.             (nLen = lstrlen(lpsz)) < nMaxSize ||
  213.             lpsz[nLen-1] == '\n')
  214.             break;
  215.  
  216.         nLen = rString.GetLength();
  217.         lpsz = rString.GetBuffer(nMaxSize + nLen) + nLen;
  218.     }
  219.  
  220.     // remove '\n' from end of string if present
  221.     lpsz = rString.GetBuffer(0);
  222.     nLen = rString.GetLength();
  223.     if (nLen != 0 && lpsz[nLen-1] == '\n')
  224.         rString.GetBufferSetLength(nLen-1);
  225.  
  226.     return lpszResult != NULL;
  227. }
  228.  
  229. LONG CStdioFile::Seek(LONG lOff, UINT nFrom)
  230. {
  231.     ASSERT_VALID(this);
  232.     ASSERT(nFrom == begin || nFrom == end || nFrom == current);
  233.     ASSERT(m_pStream != NULL);
  234.  
  235.     if (fseek(m_pStream, lOff, nFrom) != 0)
  236.         AfxThrowFileException(CFileException::badSeek, _doserrno,
  237.             m_strFileName);
  238.  
  239.     long pos = ftell(m_pStream);
  240.     return pos;
  241. }
  242.  
  243. DWORD CStdioFile::GetPosition() const
  244. {
  245.     ASSERT_VALID(this);
  246.     ASSERT(m_pStream != NULL);
  247.  
  248.     long pos = ftell(m_pStream);
  249.     if (pos == -1)
  250.         AfxThrowFileException(CFileException::invalidFile, _doserrno,
  251.             m_strFileName);
  252.     return pos;
  253. }
  254.  
  255. void CStdioFile::Flush()
  256. {
  257.     ASSERT_VALID(this);
  258.  
  259.     if (m_pStream != NULL && fflush(m_pStream) != 0)
  260.         AfxThrowFileException(CFileException::diskFull, _doserrno,
  261.             m_strFileName);
  262. }
  263.  
  264. void CStdioFile::Close()
  265. {
  266.     ASSERT_VALID(this);
  267.     ASSERT(m_pStream != NULL);
  268.  
  269.     int nErr = 0;
  270.  
  271.     if (m_pStream != NULL)
  272.         nErr = fclose(m_pStream);
  273.  
  274.     m_hFile = (UINT) hFileNull;
  275.     m_bCloseOnDelete = FALSE;
  276.     m_pStream = NULL;
  277.  
  278.     if (nErr != 0)
  279.         AfxThrowFileException(CFileException::diskFull, _doserrno,
  280.             m_strFileName);
  281. }
  282.  
  283. void CStdioFile::Abort()
  284. {
  285.     ASSERT_VALID(this);
  286.  
  287.     if (m_pStream != NULL && m_bCloseOnDelete)
  288.         fclose(m_pStream);  // close but ignore errors
  289.     m_hFile = (UINT) hFileNull;
  290.     m_pStream = NULL;
  291.     m_bCloseOnDelete = FALSE;
  292. }
  293.  
  294. CFile* CStdioFile::Duplicate() const
  295. {
  296.     ASSERT_VALID(this);
  297.     ASSERT(m_pStream != NULL);
  298.  
  299.     AfxThrowNotSupportedException();
  300.     return NULL;
  301. }
  302.  
  303. void CStdioFile::LockRange(DWORD /* dwPos */, DWORD /* dwCount */)
  304. {
  305.     ASSERT_VALID(this);
  306.     ASSERT(m_pStream != NULL);
  307.  
  308.     AfxThrowNotSupportedException();
  309. }
  310.  
  311. void CStdioFile::UnlockRange(DWORD /* dwPos */, DWORD /* dwCount */)
  312. {
  313.     ASSERT_VALID(this);
  314.     ASSERT(m_pStream != NULL);
  315.  
  316.     AfxThrowNotSupportedException();
  317. }
  318.  
  319. #ifdef _DEBUG
  320. void CStdioFile::Dump(CDumpContext& dc) const
  321. {
  322.     CFile::Dump(dc);
  323.  
  324.     dc << "m_pStream = " << (void*)m_pStream;
  325.     dc << "\n";
  326. }
  327. #endif
  328.  
  329. #ifdef AFX_INIT_SEG
  330. #pragma code_seg(AFX_INIT_SEG)
  331. #endif
  332.  
  333. IMPLEMENT_DYNAMIC(CStdioFile, CFile)
  334.  
  335. /////////////////////////////////////////////////////////////////////////////
  336.