home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / FILETXT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-30  |  8.1 KB  |  351 lines

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