home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / FILEMEM.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-30  |  8.0 KB  |  376 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.  
  13. #ifdef AFX_CORE3_SEG
  14. #pragma code_seg(AFX_CORE3_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. #define new DEBUG_NEW
  23.  
  24. ////////////////////////////////////////////////////////////////////////////
  25. // CMemFile implementation
  26.  
  27. CMemFile::CMemFile(UINT nGrowBytes)
  28. {
  29.     ASSERT(nGrowBytes <= UINT_MAX);
  30.  
  31.     m_nGrowBytes = nGrowBytes;
  32.     m_nPosition = 0;
  33.     m_nBufferSize = 0;
  34.     m_nFileSize = 0;
  35.     m_lpBuffer = NULL;
  36.     m_bAutoDelete = TRUE;
  37. }
  38.  
  39. CMemFile::CMemFile(BYTE* lpBuffer, UINT nBufferSize, UINT nGrowBytes)
  40. {
  41.     ASSERT(nGrowBytes <= UINT_MAX);
  42.  
  43.     m_nGrowBytes = nGrowBytes;
  44.     m_nPosition = 0;
  45.     m_nBufferSize = nBufferSize;
  46.     m_nFileSize = nGrowBytes == 0 ? nBufferSize : 0;
  47.     m_lpBuffer = lpBuffer;
  48.     m_bAutoDelete = FALSE;
  49. }
  50.  
  51. void CMemFile::Attach(BYTE* lpBuffer, UINT nBufferSize, UINT nGrowBytes)
  52. {
  53.     ASSERT(m_lpBuffer == NULL);
  54.  
  55.     m_nGrowBytes = nGrowBytes;
  56.     m_nPosition = 0;
  57.     m_nBufferSize = nBufferSize;
  58.     m_nFileSize = nGrowBytes == 0 ? nBufferSize : 0;
  59.     m_lpBuffer = lpBuffer;
  60.     m_bAutoDelete = FALSE;
  61. }
  62.  
  63. BYTE* CMemFile::Detach()
  64. {
  65.     BYTE* lpBuffer = m_lpBuffer;
  66.     m_lpBuffer = NULL;
  67.     m_nFileSize = 0;
  68.     m_nBufferSize = 0;
  69.     m_nPosition = 0;
  70.  
  71.     return lpBuffer;
  72. }
  73.  
  74. CMemFile::~CMemFile()
  75. {
  76.     // Close should have already been called, but we check anyway
  77.     if (m_lpBuffer)
  78.         Close();
  79.     ASSERT(m_lpBuffer == NULL);
  80.  
  81.     m_nGrowBytes = 0;
  82.     m_nPosition = 0;
  83.     m_nBufferSize = 0;
  84.     m_nFileSize = 0;
  85. }
  86.  
  87. BYTE* CMemFile::Alloc(DWORD nBytes)
  88. {
  89.     return (BYTE*)malloc((UINT)nBytes);
  90. }
  91.  
  92. BYTE* CMemFile::Realloc(BYTE* lpMem, DWORD nBytes)
  93. {
  94.     return (BYTE*)realloc(lpMem, (UINT)nBytes);
  95. }
  96.  
  97. #pragma intrinsic(memcpy)
  98. BYTE* CMemFile::Memcpy(BYTE* lpMemTarget, const BYTE* lpMemSource,
  99.     UINT nBytes)
  100. {
  101.     ASSERT(lpMemTarget != NULL);
  102.     ASSERT(lpMemSource != NULL);
  103.  
  104.     ASSERT(AfxIsValidAddress(lpMemTarget, nBytes));
  105.     ASSERT(AfxIsValidAddress(lpMemSource, nBytes, FALSE));
  106.  
  107.     return (BYTE*)memcpy(lpMemTarget, lpMemSource, nBytes);
  108. }
  109. #pragma function(memcpy)
  110.  
  111. void CMemFile::Free(BYTE* lpMem)
  112. {
  113.     ASSERT(lpMem != NULL);
  114.  
  115.     free(lpMem);
  116. }
  117.  
  118. DWORD CMemFile::GetPosition() const
  119. {
  120.     ASSERT_VALID(this);
  121.     return m_nPosition;
  122. }
  123.  
  124. void CMemFile::GrowFile(DWORD dwNewLen)
  125. {
  126.     ASSERT_VALID(this);
  127.  
  128.     if (dwNewLen > m_nBufferSize)
  129.     {
  130.         // grow the buffer
  131.         DWORD dwNewBufferSize = (DWORD)m_nBufferSize;
  132.  
  133.         // watch out for buffers which cannot be grown!
  134.         ASSERT(m_nGrowBytes != 0);
  135.         if (m_nGrowBytes == 0)
  136.             AfxThrowMemoryException();
  137.  
  138.         // determine new buffer size
  139.         while (dwNewBufferSize < dwNewLen)
  140.             dwNewBufferSize += m_nGrowBytes;
  141.  
  142.         // allocate new buffer
  143.         BYTE* lpNew;
  144.         if (m_lpBuffer == NULL)
  145.             lpNew = Alloc(dwNewBufferSize);
  146.         else
  147.             lpNew = Realloc(m_lpBuffer, dwNewBufferSize);
  148.  
  149.         if (lpNew == NULL)
  150.             AfxThrowMemoryException();
  151.  
  152.         m_lpBuffer = lpNew;
  153.         m_nBufferSize = dwNewBufferSize;
  154.     }
  155.     ASSERT_VALID(this);
  156. }
  157.  
  158. void CMemFile::SetLength(DWORD dwNewLen)
  159. {
  160.     ASSERT_VALID(this);
  161.  
  162.     if (dwNewLen > m_nBufferSize)
  163.         GrowFile(dwNewLen);
  164.  
  165.     if (dwNewLen < m_nPosition)
  166.         m_nPosition = dwNewLen;
  167.  
  168.     m_nFileSize = dwNewLen;
  169.     ASSERT_VALID(this);
  170. }
  171.  
  172. UINT CMemFile::Read(void* lpBuf, UINT nCount)
  173. {
  174.     ASSERT_VALID(this);
  175.  
  176.     if (nCount == 0)
  177.         return 0;
  178.  
  179.     ASSERT(lpBuf != NULL);
  180.     ASSERT(AfxIsValidAddress(lpBuf, nCount));
  181.  
  182.     if (m_nPosition > m_nFileSize)
  183.         return 0;
  184.  
  185.     UINT nRead;
  186.     if (m_nPosition + nCount > m_nFileSize)
  187.         nRead = (UINT)(m_nFileSize - m_nPosition);
  188.     else
  189.         nRead = nCount;
  190.  
  191.     Memcpy((BYTE*)lpBuf, (BYTE*)m_lpBuffer + m_nPosition, nRead);
  192.     m_nPosition += nRead;
  193.  
  194.     ASSERT_VALID(this);
  195.  
  196.     return nRead;
  197. }
  198.  
  199. void CMemFile::Write(const void* lpBuf, UINT nCount)
  200. {
  201.     ASSERT_VALID(this);
  202.  
  203.     if (nCount == 0)
  204.         return;
  205.  
  206.     ASSERT(lpBuf != NULL);
  207.     ASSERT(AfxIsValidAddress(lpBuf, nCount, FALSE));
  208.  
  209.     if (m_nPosition + nCount > m_nBufferSize)
  210.         GrowFile(m_nPosition + nCount);
  211.  
  212.     ASSERT(m_nPosition + nCount <= m_nBufferSize);
  213.  
  214.     Memcpy((BYTE*)m_lpBuffer + m_nPosition, (BYTE*)lpBuf, nCount);
  215.  
  216.     m_nPosition += nCount;
  217.  
  218.     if (m_nPosition > m_nFileSize)
  219.         m_nFileSize = m_nPosition;
  220.  
  221.     ASSERT_VALID(this);
  222. }
  223.  
  224. LONG CMemFile::Seek(LONG lOff, UINT nFrom)
  225. {
  226.     ASSERT_VALID(this);
  227.     ASSERT(nFrom == begin || nFrom == end || nFrom == current);
  228.  
  229.     LONG lNewPos = m_nPosition;
  230.  
  231.     if (nFrom == begin)
  232.         lNewPos = lOff;
  233.     else if (nFrom == current)
  234.         lNewPos += lOff;
  235.     else if (nFrom == end)
  236.         lNewPos = m_nFileSize + lOff;
  237.     else
  238.         return -1;
  239.  
  240.     if (lNewPos < 0)
  241.         AfxThrowFileException(CFileException::badSeek);
  242.  
  243.     m_nPosition = lNewPos;
  244.  
  245.     ASSERT_VALID(this);
  246.     return m_nPosition;
  247. }
  248.  
  249. void CMemFile::Flush()
  250. {
  251.     ASSERT_VALID(this);
  252. }
  253.  
  254. void CMemFile::Close()
  255. {
  256.     ASSERT_VALID(this);
  257.  
  258.     m_nGrowBytes = 0;
  259.     m_nPosition = 0;
  260.     m_nBufferSize = 0;
  261.     m_nFileSize = 0;
  262.     if (m_lpBuffer && m_bAutoDelete)
  263.         Free(m_lpBuffer);
  264.     m_lpBuffer = NULL;
  265. }
  266.  
  267. void CMemFile::Abort()
  268. {
  269.     ASSERT_VALID(this);
  270.  
  271.     Close();
  272. }
  273.  
  274. void CMemFile::LockRange(DWORD /* dwPos */, DWORD /* dwCount */)
  275. {
  276.     ASSERT_VALID(this);
  277.     AfxThrowNotSupportedException();
  278. }
  279.  
  280.  
  281. void CMemFile::UnlockRange(DWORD /* dwPos */, DWORD /* dwCount */)
  282. {
  283.     ASSERT_VALID(this);
  284.     AfxThrowNotSupportedException();
  285. }
  286.  
  287. CFile* CMemFile::Duplicate() const
  288. {
  289.     ASSERT_VALID(this);
  290.     AfxThrowNotSupportedException();
  291.     return NULL;
  292. }
  293.  
  294. // only CMemFile supports "direct buffering" interaction with CArchive
  295. UINT CMemFile::GetBufferPtr(UINT nCommand, UINT nCount,
  296.     void** ppBufStart, void**ppBufMax)
  297. {
  298.     ASSERT(nCommand == bufferCheck || nCommand == bufferCommit ||
  299.         nCommand == bufferRead || nCommand == bufferWrite);
  300.  
  301.     if (nCommand == bufferCheck)
  302.         return 1;   // just a check for direct buffer support
  303.  
  304.     if (nCommand == bufferCommit)
  305.     {
  306.         // commit buffer
  307.         ASSERT(ppBufStart == NULL);
  308.         ASSERT(ppBufMax == NULL);
  309.         m_nPosition += nCount;
  310.         if (m_nPosition > m_nFileSize)
  311.             m_nFileSize = m_nPosition;
  312.         return 0;
  313.     }
  314.  
  315.     ASSERT(nCommand == bufferWrite || nCommand == bufferRead);
  316.     ASSERT(ppBufStart != NULL);
  317.     ASSERT(ppBufMax != NULL);
  318.  
  319.     // when storing, grow file as necessary to satisfy buffer request
  320.     if (nCommand == bufferWrite && m_nPosition + nCount > m_nBufferSize)
  321.         GrowFile(m_nPosition + nCount);
  322.  
  323.     // store buffer max and min
  324.     *ppBufStart = m_lpBuffer + m_nPosition;
  325.  
  326.     // end of buffer depends on whether you are reading or writing
  327.     if (nCommand == bufferWrite)
  328.         *ppBufMax = m_lpBuffer + min(m_nBufferSize, m_nPosition + nCount);
  329.     else
  330.     {
  331.         if (nCount == (UINT)-1)
  332.             nCount = m_nBufferSize - m_nPosition;
  333.         *ppBufMax = m_lpBuffer + min(m_nFileSize, m_nPosition + nCount);
  334.         m_nPosition += LPBYTE(*ppBufMax) - LPBYTE(*ppBufStart);
  335.     }
  336.  
  337.     // return number of bytes in returned buffer space (may be <= nCount)
  338.     return LPBYTE(*ppBufMax) - LPBYTE(*ppBufStart);
  339. }
  340.  
  341. /////////////////////////////////////////////////////////////////////////////
  342. // CMemFile diagonstics
  343.  
  344. #ifdef _DEBUG
  345. void CMemFile::Dump(CDumpContext& dc) const
  346. {
  347.     CFile::Dump(dc);
  348.  
  349.     dc << "m_nFileSize = " << m_nFileSize;
  350.     dc << "\nm_nBufferSize = " << m_nBufferSize;
  351.     dc << "\nm_nPosition = " << m_nPosition;
  352.     dc << "\nm_nGrowBytes = " << m_nGrowBytes;
  353.  
  354.     dc << "\n";
  355. }
  356.  
  357. void CMemFile::AssertValid() const
  358. {
  359.     CFile::AssertValid();
  360.  
  361.     ASSERT((m_lpBuffer == NULL && m_nBufferSize == 0) ||
  362.         AfxIsValidAddress(m_lpBuffer, (UINT)m_nBufferSize, FALSE));
  363.     ASSERT(m_nFileSize <= m_nBufferSize);
  364.     // m_nPosition might be after the end of file, so we cannot ASSERT
  365.     // its validity
  366. }
  367. #endif // _DEBUG
  368.  
  369. #ifdef AFX_INIT_SEG
  370. #pragma code_seg(AFX_INIT_SEG)
  371. #endif
  372.  
  373. IMPLEMENT_DYNAMIC(CMemFile, CFile)
  374.  
  375. /////////////////////////////////////////////////////////////////////////////
  376.