windows-nt/Source/XPSP1/NT/inetsrv/query/common/fstream.cxx
2020-09-26 16:20:57 +08:00

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;
}