mirror of https://github.com/lianthony/NT4.0
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.
373 lines
7.6 KiB
373 lines
7.6 KiB
// This is a part of the Microsoft Foundation Classes C++ library.
|
|
// Copyright (C) 1992-1995 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_VALID(this);
|
|
|
|
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
|
|
{
|
|
*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)
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|