home *** CD-ROM | disk | FTP | other *** search
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
-
- #include "stdafx.h"
-
- #ifdef AFX_CORE3_SEG
- #pragma code_seg(AFX_CORE3_SEG)
- #endif
-
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
-
- #define new DEBUG_NEW
-
- ////////////////////////////////////////////////////////////////////////////
- // CMemFile implementation
-
- CMemFile::CMemFile(UINT nGrowBytes)
- {
- ASSERT(nGrowBytes <= UINT_MAX);
-
- m_nGrowBytes = nGrowBytes;
- m_nPosition = 0;
- m_nBufferSize = 0;
- m_nFileSize = 0;
- m_lpBuffer = NULL;
- m_bAutoDelete = TRUE;
- }
-
- CMemFile::CMemFile(BYTE* lpBuffer, UINT nBufferSize, UINT nGrowBytes)
- {
- ASSERT(nGrowBytes <= UINT_MAX);
-
- m_nGrowBytes = nGrowBytes;
- m_nPosition = 0;
- m_nBufferSize = nBufferSize;
- m_nFileSize = nGrowBytes == 0 ? nBufferSize : 0;
- m_lpBuffer = lpBuffer;
- m_bAutoDelete = FALSE;
- }
-
- void CMemFile::Attach(BYTE* lpBuffer, UINT nBufferSize, UINT nGrowBytes)
- {
- ASSERT(m_lpBuffer == NULL);
-
- m_nGrowBytes = nGrowBytes;
- m_nPosition = 0;
- m_nBufferSize = nBufferSize;
- m_nFileSize = nGrowBytes == 0 ? nBufferSize : 0;
- m_lpBuffer = lpBuffer;
- m_bAutoDelete = FALSE;
- }
-
- BYTE* CMemFile::Detach()
- {
- BYTE* lpBuffer = m_lpBuffer;
- m_lpBuffer = NULL;
- m_nFileSize = 0;
- m_nBufferSize = 0;
- m_nPosition = 0;
-
- return lpBuffer;
- }
-
- CMemFile::~CMemFile()
- {
- // Close should have already been called, but we check anyway
- if (m_lpBuffer)
- Close();
- ASSERT(m_lpBuffer == NULL);
-
- m_nGrowBytes = 0;
- m_nPosition = 0;
- m_nBufferSize = 0;
- m_nFileSize = 0;
- }
-
- BYTE* CMemFile::Alloc(DWORD nBytes)
- {
- return (BYTE*)malloc((UINT)nBytes);
- }
-
- BYTE* CMemFile::Realloc(BYTE* lpMem, DWORD nBytes)
- {
- return (BYTE*)realloc(lpMem, (UINT)nBytes);
- }
-
- #pragma intrinsic(memcpy)
- BYTE* CMemFile::Memcpy(BYTE* lpMemTarget, const BYTE* lpMemSource,
- UINT nBytes)
- {
- ASSERT(lpMemTarget != NULL);
- ASSERT(lpMemSource != NULL);
-
- ASSERT(AfxIsValidAddress(lpMemTarget, nBytes));
- ASSERT(AfxIsValidAddress(lpMemSource, nBytes, FALSE));
-
- return (BYTE*)memcpy(lpMemTarget, lpMemSource, nBytes);
- }
- #pragma function(memcpy)
-
- void CMemFile::Free(BYTE* lpMem)
- {
- ASSERT(lpMem != NULL);
-
- free(lpMem);
- }
-
- DWORD CMemFile::GetPosition() const
- {
- ASSERT_VALID(this);
- return m_nPosition;
- }
-
- void CMemFile::GrowFile(DWORD dwNewLen)
- {
- ASSERT_VALID(this);
-
- if (dwNewLen > m_nBufferSize)
- {
- // grow the buffer
- DWORD dwNewBufferSize = (DWORD)m_nBufferSize;
-
- // watch out for buffers which cannot be grown!
- ASSERT(m_nGrowBytes != 0);
- if (m_nGrowBytes == 0)
- AfxThrowMemoryException();
-
- // determine new buffer size
- while (dwNewBufferSize < dwNewLen)
- dwNewBufferSize += m_nGrowBytes;
-
- // allocate new buffer
- BYTE* lpNew;
- if (m_lpBuffer == NULL)
- lpNew = Alloc(dwNewBufferSize);
- else
- lpNew = Realloc(m_lpBuffer, dwNewBufferSize);
-
- if (lpNew == NULL)
- AfxThrowMemoryException();
-
- m_lpBuffer = lpNew;
- m_nBufferSize = dwNewBufferSize;
- }
- ASSERT_VALID(this);
- }
-
- void CMemFile::SetLength(DWORD dwNewLen)
- {
- ASSERT_VALID(this);
-
- if (dwNewLen > m_nBufferSize)
- GrowFile(dwNewLen);
-
- if (dwNewLen < m_nPosition)
- m_nPosition = dwNewLen;
-
- m_nFileSize = dwNewLen;
- ASSERT_VALID(this);
- }
-
- UINT CMemFile::Read(void* lpBuf, UINT nCount)
- {
- ASSERT_VALID(this);
-
- if (nCount == 0)
- return 0;
-
- ASSERT(lpBuf != NULL);
- ASSERT(AfxIsValidAddress(lpBuf, nCount));
-
- if (m_nPosition > m_nFileSize)
- return 0;
-
- UINT nRead;
- if (m_nPosition + nCount > m_nFileSize)
- nRead = (UINT)(m_nFileSize - m_nPosition);
- else
- nRead = nCount;
-
- Memcpy((BYTE*)lpBuf, (BYTE*)m_lpBuffer + m_nPosition, nRead);
- m_nPosition += nRead;
-
- ASSERT_VALID(this);
-
- return nRead;
- }
-
- void CMemFile::Write(const void* lpBuf, UINT nCount)
- {
- ASSERT_VALID(this);
-
- if (nCount == 0)
- return;
-
- ASSERT(lpBuf != NULL);
- ASSERT(AfxIsValidAddress(lpBuf, nCount, FALSE));
-
- if (m_nPosition + nCount > m_nBufferSize)
- GrowFile(m_nPosition + nCount);
-
- ASSERT(m_nPosition + nCount <= m_nBufferSize);
-
- Memcpy((BYTE*)m_lpBuffer + m_nPosition, (BYTE*)lpBuf, nCount);
-
- m_nPosition += nCount;
-
- if (m_nPosition > m_nFileSize)
- m_nFileSize = m_nPosition;
-
- ASSERT_VALID(this);
- }
-
- LONG CMemFile::Seek(LONG lOff, UINT nFrom)
- {
- ASSERT_VALID(this);
- ASSERT(nFrom == begin || nFrom == end || nFrom == current);
-
- LONG lNewPos = m_nPosition;
-
- if (nFrom == begin)
- lNewPos = lOff;
- else if (nFrom == current)
- lNewPos += lOff;
- else if (nFrom == end)
- lNewPos = m_nFileSize + lOff;
- else
- return -1;
-
- if (lNewPos < 0)
- AfxThrowFileException(CFileException::badSeek);
-
- m_nPosition = lNewPos;
-
- ASSERT_VALID(this);
- return m_nPosition;
- }
-
- void CMemFile::Flush()
- {
- ASSERT_VALID(this);
- }
-
- void CMemFile::Close()
- {
- ASSERT((m_lpBuffer == NULL && m_nBufferSize == 0) ||
- !m_bAutoDelete || AfxIsValidAddress(m_lpBuffer, (UINT)m_nBufferSize, FALSE));
- ASSERT(m_nFileSize <= m_nBufferSize);
-
- m_nGrowBytes = 0;
- m_nPosition = 0;
- m_nBufferSize = 0;
- m_nFileSize = 0;
- if (m_lpBuffer && m_bAutoDelete)
- Free(m_lpBuffer);
- m_lpBuffer = NULL;
- }
-
- void CMemFile::Abort()
- {
- ASSERT_VALID(this);
-
- Close();
- }
-
- void CMemFile::LockRange(DWORD /* dwPos */, DWORD /* dwCount */)
- {
- ASSERT_VALID(this);
- AfxThrowNotSupportedException();
- }
-
-
- void CMemFile::UnlockRange(DWORD /* dwPos */, DWORD /* dwCount */)
- {
- ASSERT_VALID(this);
- AfxThrowNotSupportedException();
- }
-
- CFile* CMemFile::Duplicate() const
- {
- ASSERT_VALID(this);
- AfxThrowNotSupportedException();
- return NULL;
- }
-
- // only CMemFile supports "direct buffering" interaction with CArchive
- UINT CMemFile::GetBufferPtr(UINT nCommand, UINT nCount,
- void** ppBufStart, void**ppBufMax)
- {
- ASSERT(nCommand == bufferCheck || nCommand == bufferCommit ||
- nCommand == bufferRead || nCommand == bufferWrite);
-
- if (nCommand == bufferCheck)
- return 1; // just a check for direct buffer support
-
- if (nCommand == bufferCommit)
- {
- // commit buffer
- ASSERT(ppBufStart == NULL);
- ASSERT(ppBufMax == NULL);
- m_nPosition += nCount;
- if (m_nPosition > m_nFileSize)
- m_nFileSize = m_nPosition;
- return 0;
- }
-
- ASSERT(nCommand == bufferWrite || nCommand == bufferRead);
- ASSERT(ppBufStart != NULL);
- ASSERT(ppBufMax != NULL);
-
- // when storing, grow file as necessary to satisfy buffer request
- if (nCommand == bufferWrite && m_nPosition + nCount > m_nBufferSize)
- GrowFile(m_nPosition + nCount);
-
- // store buffer max and min
- *ppBufStart = m_lpBuffer + m_nPosition;
-
- // end of buffer depends on whether you are reading or writing
- if (nCommand == bufferWrite)
- *ppBufMax = m_lpBuffer + min(m_nBufferSize, m_nPosition + nCount);
- else
- {
- if (nCount == (UINT)-1)
- nCount = m_nBufferSize - m_nPosition;
- *ppBufMax = m_lpBuffer + min(m_nFileSize, m_nPosition + nCount);
- m_nPosition += LPBYTE(*ppBufMax) - LPBYTE(*ppBufStart);
- }
-
- // return number of bytes in returned buffer space (may be <= nCount)
- return LPBYTE(*ppBufMax) - LPBYTE(*ppBufStart);
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CMemFile diagonstics
-
- #ifdef _DEBUG
- void CMemFile::Dump(CDumpContext& dc) const
- {
- CFile::Dump(dc);
-
- dc << "m_nFileSize = " << m_nFileSize;
- dc << "\nm_nBufferSize = " << m_nBufferSize;
- dc << "\nm_nPosition = " << m_nPosition;
- dc << "\nm_nGrowBytes = " << m_nGrowBytes;
-
- dc << "\n";
- }
-
- void CMemFile::AssertValid() const
- {
- CFile::AssertValid();
-
- ASSERT((m_lpBuffer == NULL && m_nBufferSize == 0) ||
- AfxIsValidAddress(m_lpBuffer, (UINT)m_nBufferSize, FALSE));
- ASSERT(m_nFileSize <= m_nBufferSize);
- // m_nPosition might be after the end of file, so we cannot ASSERT
- // its validity
- }
- #endif // _DEBUG
-
- #ifdef AFX_INIT_SEG
- #pragma code_seg(AFX_INIT_SEG)
- #endif
-
- IMPLEMENT_DYNAMIC(CMemFile, CFile)
-
- /////////////////////////////////////////////////////////////////////////////
-