331 lines
8.1 KiB
C++
331 lines
8.1 KiB
C++
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1991 - 1992.
|
||
|
//
|
||
|
// File: FSTREAM.CXX
|
||
|
//
|
||
|
// Contents: Stream for accessing files with run-time libs.
|
||
|
//
|
||
|
// Classes: CStreamFile
|
||
|
//
|
||
|
// History: 16-Dec-92 AmyA Created from fstream.hxx
|
||
|
//
|
||
|
// Notes: _pCur always points to the current file position (within the
|
||
|
// buffer) EXCEPT when _pCur == _pEnd. In this case, _fp
|
||
|
// ALWAYS points to the current file position.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
#include <pch.cxx>
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include <fstream.hxx>
|
||
|
|
||
|
IMPLEMENT_UNWIND ( CStreamFile );
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CStreamFile::CStreamFile, public
|
||
|
//
|
||
|
// Synopsis: opens file for reading/writing
|
||
|
//
|
||
|
// Arguments: [filename] - ascii name of file on disk
|
||
|
// [type] - new file/existing file
|
||
|
//
|
||
|
// History: 31-Jul-92 MikeHew Created
|
||
|
//
|
||
|
// Notes: FileType NewFile will open/destroy specified file
|
||
|
// FileType ExistingFile will open file for reading/appending
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
EXPORTIMP
|
||
|
CStreamFile::CStreamFile( const char * filename, FileType type )
|
||
|
{
|
||
|
switch( type )
|
||
|
{
|
||
|
case NewFile:
|
||
|
_fp = fopen( filename, "wb+" );
|
||
|
break;
|
||
|
|
||
|
case NewOrExistingFile:
|
||
|
_fp = fopen( filename, "rb+" );
|
||
|
if ( !_fp )
|
||
|
_fp = fopen( filename, "wb+" );
|
||
|
break;
|
||
|
|
||
|
case ExistingFile:
|
||
|
_fp = fopen( filename, "rb" );
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ( _fp )
|
||
|
{
|
||
|
_pBuf = new BYTE [ defaultBufSize ];
|
||
|
Win4Assert ( _pCur == _pEnd );
|
||
|
// buffer will be filled when first character is read.
|
||
|
}
|
||
|
else
|
||
|
_eof = TRUE;
|
||
|
|
||
|
END_CONSTRUCTION ( CStreamFile );
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CStreamFile::~CStreamFile, public
|
||
|
//
|
||
|
// Synopsis: Closes stream.
|
||
|
//
|
||
|
// History: 04-Aug-92 MikeHew Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
EXPORTIMP
|
||
|
CStreamFile::~CStreamFile()
|
||
|
{
|
||
|
if ( _fp )
|
||
|
{
|
||
|
fclose( _fp );
|
||
|
|
||
|
delete [] _pBuf;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CStreamFile::Read, public
|
||
|
//
|
||
|
// Synopsis: Read data from file to destination
|
||
|
//
|
||
|
// Arguments: [dest] - pointer to destination
|
||
|
// [size] - bytes to be read
|
||
|
//
|
||
|
// History: 31-Jul-92 MikeHew Created
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
EXPORTIMP unsigned APINOT
|
||
|
CStreamFile::Read( void *dest, unsigned size )
|
||
|
{
|
||
|
BYTE *pBuf = (BYTE *)dest;
|
||
|
|
||
|
ULONG unread = size;
|
||
|
|
||
|
ULONG cb = (ULONG)(_pEnd - _pCur);
|
||
|
|
||
|
ULONG cbRead = min ( size, cb );
|
||
|
|
||
|
memcpy ( pBuf, _pCur, cbRead );
|
||
|
|
||
|
pBuf += cbRead;
|
||
|
_pCur += cbRead;
|
||
|
unread -= cbRead;
|
||
|
|
||
|
if ( unread > 0 )
|
||
|
{
|
||
|
Win4Assert ( _pCur == _pEnd ); // buffer should be "empty"
|
||
|
|
||
|
// read more
|
||
|
|
||
|
LONG cBuf = unread / defaultBufSize;
|
||
|
|
||
|
if ( cBuf != 0 )
|
||
|
{
|
||
|
cbRead = fread ( pBuf, sizeof(BYTE), cBuf*defaultBufSize, _fp );
|
||
|
pBuf += cbRead;
|
||
|
unread -= cbRead;
|
||
|
}
|
||
|
|
||
|
if ( unread > 0 )
|
||
|
{
|
||
|
if ( FillBuf() )
|
||
|
{
|
||
|
cb = (ULONG)(_pEnd - _pCur);
|
||
|
cbRead = min ( unread, cb );
|
||
|
|
||
|
memcpy ( pBuf, _pCur, cbRead );
|
||
|
_pCur += cbRead;
|
||
|
unread -= cbRead;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ( size - unread );
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CStreamFile::Write, public
|
||
|
//
|
||
|
// Synopsis: Write data to file from source buffer
|
||
|
//
|
||
|
// Arguments: [source] - pointer to source
|
||
|
// [size] - bytes to be written
|
||
|
//
|
||
|
// History: 31-Jul-92 MikeHew Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
EXPORTIMP unsigned APINOT
|
||
|
CStreamFile::Write( const void *source, unsigned size )
|
||
|
{
|
||
|
//
|
||
|
// The seeks are to guarantee seeks between read and write.
|
||
|
//
|
||
|
|
||
|
fseek( _fp, -((long)( _pEnd - _pCur )), SEEK_CUR ); // Seek to current position
|
||
|
// in stream
|
||
|
unsigned cbWritten = fwrite( source, 1, size, _fp );
|
||
|
fseek( _fp, 0, SEEK_CUR );
|
||
|
|
||
|
_pCur = _pEnd; // This guarantees a FillBuf() for the next buffer read
|
||
|
|
||
|
return cbWritten;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CStreamFile::Seek, public
|
||
|
//
|
||
|
// Synopsis: Move pointer to specified offset in file
|
||
|
//
|
||
|
// Arguments: [offset] - signed offset from origin
|
||
|
// [origin] - one of the following options:
|
||
|
//
|
||
|
// CUR => offset from current position
|
||
|
// END => offset from end of file
|
||
|
// (default) SET => offset from beginning of file
|
||
|
//
|
||
|
// History: 04-Aug-92 MikeHew Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
EXPORTIMP int APINOT
|
||
|
CStreamFile::Seek( LONG offset, CStream::SEEK origin )
|
||
|
{
|
||
|
_eof = FALSE;
|
||
|
|
||
|
if ( _pCur == _pEnd ) // the buffer is out-of-date anyway
|
||
|
{
|
||
|
return fseek( _fp, offset, origin );
|
||
|
}
|
||
|
|
||
|
LONG newBufOffset;
|
||
|
LONG oldBufOffset = (LONG)(_pCur - _pBuf);
|
||
|
|
||
|
LONG curFilePos = ftell ( _fp ) - (LONG)( _pEnd - _pCur );
|
||
|
|
||
|
// figure out the offset relative to the beginning of the buffer
|
||
|
|
||
|
switch ( origin )
|
||
|
{
|
||
|
case CStream::SET:
|
||
|
|
||
|
// test for seeking before beginning of file
|
||
|
if ( offset < 0 )
|
||
|
return FALSE;
|
||
|
|
||
|
newBufOffset = offset - curFilePos + oldBufOffset;
|
||
|
|
||
|
break;
|
||
|
|
||
|
case CStream::END:
|
||
|
{
|
||
|
int fileSize = Size();
|
||
|
|
||
|
// test for seeking before beginning of file
|
||
|
if ( offset < -fileSize )
|
||
|
return FALSE;
|
||
|
|
||
|
newBufOffset = offset + fileSize - curFilePos + oldBufOffset;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case CStream::CUR:
|
||
|
|
||
|
// test for seeking before beginning of file
|
||
|
if ( curFilePos + offset < 0 )
|
||
|
return FALSE;
|
||
|
|
||
|
newBufOffset = offset + oldBufOffset;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
_eof = FALSE;
|
||
|
|
||
|
// Check to see if newOffset is within current buffer
|
||
|
|
||
|
if ( ( newBufOffset >= 0 ) && ( newBufOffset < ( _pEnd - _pBuf ) ) )
|
||
|
{
|
||
|
_pCur = _pBuf + newBufOffset;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
// Seek to new location
|
||
|
|
||
|
if ( origin == CStream::CUR )
|
||
|
offset -= (LONG)(_pEnd - _pCur); // _fp pos is not current pos, so adjust
|
||
|
// offset
|
||
|
_pCur = _pEnd; // This guarantees a FillBuf() for the next buffer read
|
||
|
return fseek( _fp, offset, origin );
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CStreamFile::Size, public
|
||
|
//
|
||
|
// Returns Current size of stream.
|
||
|
//
|
||
|
// History: 03-Sep-92 KyleP Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
ULONG
|
||
|
CStreamFile::Size()
|
||
|
{
|
||
|
fpos_t pos;
|
||
|
ULONG size;
|
||
|
|
||
|
fgetpos( _fp, &pos );
|
||
|
|
||
|
fseek( _fp, 0, SEEK_END );
|
||
|
size = ftell( _fp );
|
||
|
|
||
|
fsetpos( _fp, &pos );
|
||
|
|
||
|
return( size );
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CStreamFile::FillBuf, public
|
||
|
//
|
||
|
// Synopsis: Fills the stream buffer from the file indicated by _fp and
|
||
|
// sets all pointers and variables accordingly.
|
||
|
//
|
||
|
// Returns: TRUE if new information was put into the buffer, FALSE
|
||
|
// if not.
|
||
|
//
|
||
|
// History: 23-Nov-92 AmyA Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
BOOL
|
||
|
CStreamFile::FillBuf()
|
||
|
{
|
||
|
unsigned size = fread( _pBuf, sizeof(char), defaultBufSize, _fp );
|
||
|
_pEnd = _pBuf + size;
|
||
|
_pCur = _pBuf;
|
||
|
if ( size == 0 )
|
||
|
{
|
||
|
_eof = TRUE;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|