//+--------------------------------------------------------------------------- // // 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 #pragma hdrstop #include 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; }