diff options
author | Willem Jan Palenstijn | 2008-09-14 22:28:53 +0000 |
---|---|---|
committer | Willem Jan Palenstijn | 2008-09-14 22:28:53 +0000 |
commit | c8eeae8d4dffa5849a23cf963884027a7789504b (patch) | |
tree | 1f2a0de23851cb7e7d1d77114c8379aa27f4fb85 | |
parent | fbfe30bf861af9b83325e0c7fecd4b0a68da5af9 (diff) | |
download | scummvm-rg350-c8eeae8d4dffa5849a23cf963884027a7789504b.tar.gz scummvm-rg350-c8eeae8d4dffa5849a23cf963884027a7789504b.tar.bz2 scummvm-rg350-c8eeae8d4dffa5849a23cf963884027a7789504b.zip |
Big patch changing semantics of ReadStream::eos():
eos() now only returns true _after_ trying to read past the end of the stream.
This has a large potential for regressions. Please test!
svn-id: r34549
34 files changed, 294 insertions, 152 deletions
diff --git a/backends/fs/stdiostream.cpp b/backends/fs/stdiostream.cpp index fafcca989b..4f353ee7c2 100644 --- a/backends/fs/stdiostream.cpp +++ b/backends/fs/stdiostream.cpp @@ -114,11 +114,11 @@ StdioStream::~StdioStream() { fclose((FILE *)_handle); } -bool StdioStream::ioFailed() const { - return eos() || ferror((FILE *)_handle) != 0; +bool StdioStream::err() const { + return ferror((FILE *)_handle) != 0; } -void StdioStream::clearIOFailed() { +void StdioStream::clearErr() { clearerr((FILE *)_handle); } diff --git a/backends/fs/stdiostream.h b/backends/fs/stdiostream.h index f40ddd9867..3d44062d7f 100644 --- a/backends/fs/stdiostream.h +++ b/backends/fs/stdiostream.h @@ -46,8 +46,8 @@ public: StdioStream(void *handle); virtual ~StdioStream(); - bool ioFailed() const; - void clearIOFailed(); + bool err() const; + void clearErr(); bool eos() const; virtual uint32 write(const void *dataPtr, uint32 dataSize); diff --git a/backends/fs/symbian/symbianstream.cpp b/backends/fs/symbian/symbianstream.cpp index 4d2ec11ab3..5944cab892 100644 --- a/backends/fs/symbian/symbianstream.cpp +++ b/backends/fs/symbian/symbianstream.cpp @@ -177,12 +177,13 @@ SymbianStdioStream::~SymbianStdioStream() { delete (TSymbianFileEntry*)(_handle); } -bool SymbianStdioStream::ioFailed() const { - return eos() || ((TSymbianFileEntry*)(_handle))->_lastError != 0; +bool SymbianStdioStream::err() const { + return ((TSymbianFileEntry*)(_handle))->_lastError != 0; } -void SymbianStdioStream::clearIOFailed() { +void SymbianStdioStream::clearErr() { ((TSymbianFileEntry*)(_handle))->_lastError = 0; + ((TSymbianFileEntry*)(_handle))->_eofReached = 0; } bool SymbianStdioStream::eos() const { diff --git a/backends/fs/symbian/symbianstream.h b/backends/fs/symbian/symbianstream.h index 180e6bffcb..d783856687 100644 --- a/backends/fs/symbian/symbianstream.h +++ b/backends/fs/symbian/symbianstream.h @@ -46,8 +46,8 @@ public: SymbianStdioStream(void *handle); virtual ~SymbianStdioStream(); - bool ioFailed() const; - void clearIOFailed(); + bool err() const; + void clearErr(); bool eos() const; virtual uint32 write(const void *dataPtr, uint32 dataSize); diff --git a/backends/platform/dc/vmsave.cpp b/backends/platform/dc/vmsave.cpp index 5fe532e1f1..d17e1f6213 100644 --- a/backends/platform/dc/vmsave.cpp +++ b/backends/platform/dc/vmsave.cpp @@ -269,6 +269,7 @@ class InVMSave : public Common::InSaveFile { private: char *buffer; int _pos, _size; + bool _eos; uint32 read(void *buf, uint32 cnt); bool skip(uint32 offset); @@ -276,7 +277,7 @@ private: public: InVMSave() - : _pos(0), buffer(NULL) + : _pos(0), buffer(NULL), _eos(false) { } ~InVMSave() @@ -285,7 +286,8 @@ public: delete[] buffer; } - bool eos() const { return _pos >= _size; } + bool eos() const { return _eos; } + void clearErr() { _eos = false; } int32 pos() const { return _pos; } int32 size() const { return _size; } @@ -312,8 +314,8 @@ public: ~OutVMSave(); - bool ioFailed() const { return iofailed; } - void clearIOFailed() { iofailed = false; } + bool err() const { return iofailed; } + void clearErr() { iofailed = false; } void finalize(); }; @@ -370,6 +372,7 @@ uint32 InVMSave::read(void *buf, uint32 cnt) int nbyt = cnt; if (_pos + nbyt > _size) { cnt = (_size - _pos); + _eos = true; nbyt = cnt; } if (nbyt) @@ -404,6 +407,7 @@ bool InVMSave::seek(int32 offs, int whence) _pos = 0; else if (_pos > _size) _pos = _size; + _eos = false; return true; } diff --git a/backends/platform/ds/arm9/source/ramsave.cpp b/backends/platform/ds/arm9/source/ramsave.cpp index 8442fd6b88..30c3a06721 100644 --- a/backends/platform/ds/arm9/source/ramsave.cpp +++ b/backends/platform/ds/arm9/source/ramsave.cpp @@ -64,6 +64,7 @@ DSSaveFile::DSSaveFile(SCUMMSave* s, bool compressed, u8* data) { } isTempFile = false; + eosReached = false; } DSSaveFile::~DSSaveFile() { @@ -167,11 +168,13 @@ int DSSaveFile::saveToSaveRAM(vu8* address) { void DSSaveFile::reset() { ptr = 0; + eosReached = false; } uint32 DSSaveFile::read(void *buf, uint32 size) { if (ptr + size > save.size) { size = save.size - ptr; + eosReached = true; if (size < 0) size = 0; } memcpy(buf, saveData + ptr, size); @@ -204,11 +207,16 @@ bool DSSaveFile::seek(int32 pos, int whence) { break; } } + eosReached = false; return true; } bool DSSaveFile::eos() const { - return ptr >= (int) save.size; + return eosReached; +} + +void DSSaveFile::clearErr() { + eosReached = false; } bool DSSaveFile::skip(uint32 bytes) { diff --git a/backends/platform/ds/arm9/source/ramsave.h b/backends/platform/ds/arm9/source/ramsave.h index e276775b66..98430b9d11 100644 --- a/backends/platform/ds/arm9/source/ramsave.h +++ b/backends/platform/ds/arm9/source/ramsave.h @@ -52,6 +52,7 @@ class DSSaveFile : public Common::InSaveFile, public Common::OutSaveFile { SCUMMSave* origHeader; bool isOpenFlag; bool isTempFile; + bool eosReached; public: DSSaveFile(); @@ -62,6 +63,7 @@ public: bool isOpen() const { return isOpenFlag; } virtual bool eos() const; + virtual void clearErr(); virtual bool skip(uint32 size); virtual int32 pos() const; diff --git a/backends/platform/ps2/rawsavefile.cpp b/backends/platform/ps2/rawsavefile.cpp index 03270ea9ce..aa3cc57fe7 100644 --- a/backends/platform/ps2/rawsavefile.cpp +++ b/backends/platform/ps2/rawsavefile.cpp @@ -31,6 +31,7 @@ RawReadFile::RawReadFile(McAccess *mcAccess) { _size = -1; _pos = 0; _buf = NULL; + _eof = false; } RawReadFile::~RawReadFile(void) { @@ -79,12 +80,16 @@ int RawReadFile::bufSeek(int ofs, int whence) { _pos = 0; else if (_pos > _size) _pos = _size; + + _eof = false; return _pos; } int RawReadFile::bufRead(void *dest, int size) { - if (_pos + size > _size) + if (_pos + size > _size) { size = _size - _pos; + _eof = true; + } memcpy(dest, _buf + _pos, size); _pos += size; return size; @@ -94,7 +99,13 @@ int RawReadFile::bufSize(void) const { return _size; } +bool RawReadFile::bufEof(void) const { + return _eof; +} +void RawReadFile::bufClearErr(void) const { + _eof = false; +} RawWriteFile::RawWriteFile(McAccess *mcAccess) { _mcAccess = mcAccess; diff --git a/backends/platform/ps2/rawsavefile.h b/backends/platform/ps2/rawsavefile.h index b638d106ab..8e0dba4ab9 100644 --- a/backends/platform/ps2/rawsavefile.h +++ b/backends/platform/ps2/rawsavefile.h @@ -40,11 +40,14 @@ public: int bufTell(void) const; int bufSeek(int ofs, int whence); int bufSize(void) const; + bool bufEof(void) const; + void bufClearErr(void); protected: McAccess *_mcAccess; int _size; uint8 *_buf; int _pos; + bool _eof; }; class RawWriteFile { diff --git a/backends/platform/ps2/savefile.cpp b/backends/platform/ps2/savefile.cpp index 7d45aabda7..bfcaf0f57f 100644 --- a/backends/platform/ps2/savefile.cpp +++ b/backends/platform/ps2/savefile.cpp @@ -71,7 +71,7 @@ uint32 AutoSaveFile::write(const void *ptr, uint32 size) { UclInSaveFile::UclInSaveFile(const char *filename, Gs2dScreen *screen, McAccess *mcAccess) : RawReadFile(mcAccess) { _screen = screen; - _ioFailed = true; + _err = true; if (bufOpen(filename)) { if ((_size > 8) && (*(uint32 *)_buf == UCL_MAGIC)) { @@ -82,13 +82,13 @@ UclInSaveFile::UclInSaveFile(const char *filename, Gs2dScreen *screen, McAccess free(_buf); _buf = decBuf; _size = resSize; - _ioFailed = false; + _err = false; _pos = 0; } else free(decBuf); } } - if (_ioFailed) { + if (_err) { if (_buf) free(_buf); _buf = NULL; @@ -100,16 +100,17 @@ UclInSaveFile::~UclInSaveFile(void) { _screen->wantAnim(false); } -bool UclInSaveFile::ioFailed(void) const { - return _ioFailed; +bool UclInSaveFile::err(void) const { + return _err; } -void UclInSaveFile::clearIOFailed(void) { - _ioFailed = false; +void UclInSaveFile::clearErr(void) { + _err = false; + bufClearErr(); } bool UclInSaveFile::eos(void) const { - return bufTell() == bufSize(); + return bufEof(); } int32 UclInSaveFile::pos(void) const { @@ -131,7 +132,7 @@ uint32 UclInSaveFile::read(void *ptr, uint32 size) { bool UclInSaveFile::skip(uint32 offset) { bufSeek(offset, SEEK_CUR); - return true;s + return true; } UclOutSaveFile::UclOutSaveFile(const char *filename, OSystem_PS2 *system, Gs2dScreen *screen, McAccess *mc) : RawWriteFile(mc) { @@ -139,7 +140,7 @@ UclOutSaveFile::UclOutSaveFile(const char *filename, OSystem_PS2 *system, Gs2dSc _system = system; strcpy(_fileName, filename); - _ioFailed = !bufOpen(filename); + _err = !bufOpen(filename); _wasFlushed = false; } @@ -148,7 +149,7 @@ UclOutSaveFile::~UclOutSaveFile(void) { if (_pos != 0) { printf("Engine didn't call SaveFile::flush()\n"); flush(); - if (ioFailed()) { + if (err()) { // unable to save to memory card and it's too late to return an error code to the engine _system->msgPrintf(5000, "!WARNING!\nCan't write to memory card.\nGame was NOT saved."); printf("~UclOutSaveFile: Flush failed!\n"); @@ -162,19 +163,19 @@ uint32 UclOutSaveFile::write(const void *ptr, uint32 size) { return size; } -bool UclOutSaveFile::ioFailed(void) const { - return _ioFailed; +bool UclOutSaveFile::err(void) const { + return _err; } -void UclOutSaveFile::clearIOFailed(void) { - _ioFailed = false; +void UclOutSaveFile::clearErr(void) { + _err = false; } bool UclOutSaveFile::flush(void) { if (_pos != 0) { if (_wasFlushed) { printf("Multiple calls to UclOutSaveFile::flush!\n"); - _ioFailed = true; + _err = true; return false; } uint32 compSize = _pos * 2; @@ -190,7 +191,7 @@ bool UclOutSaveFile::flush(void) { _pos = compSize + 8; if (!bufFlush()) { printf("UclOutSaveFile::flush failed!\n"); - _ioFailed = true; + _err = true; removeFile(); } _wasFlushed = true; @@ -270,6 +271,3 @@ int Ps2McWriteFile::seek(int32 offset, int origin) { return 0; } -bool Ps2McWriteFile::eof(void) { - return true; -} diff --git a/backends/platform/ps2/savefile.h b/backends/platform/ps2/savefile.h index fd09c823d0..0c0cf922f4 100644 --- a/backends/platform/ps2/savefile.h +++ b/backends/platform/ps2/savefile.h @@ -42,13 +42,13 @@ public: virtual ~UclOutSaveFile(void); virtual uint32 write(const void *ptr, uint32 size); virtual bool flush(void); - virtual bool ioFailed(void) const; - virtual void clearIOFailed(void); + virtual bool err(void) const; + virtual void clearErr(void); private: OSystem_PS2 *_system; Gs2dScreen *_screen; - bool _ioFailed, _wasFlushed; + bool _err, _wasFlushed; char _fileName[128]; }; @@ -58,8 +58,8 @@ public: virtual ~UclInSaveFile(void); virtual bool eos(void) const; virtual uint32 read(void *ptr, uint32 size); - virtual bool ioFailed(void) const; - virtual void clearIOFailed(void); + virtual bool err(void) const; + virtual void clearErr(void); virtual bool skip(uint32 offset); virtual int32 pos(void) const; @@ -67,7 +67,7 @@ public: virtual bool seek(int pos, int whence = SEEK_SET); private: Gs2dScreen *_screen; - bool _ioFailed; + bool _err; }; class AutoSaveFile : public Common::OutSaveFile { @@ -76,8 +76,8 @@ public: ~AutoSaveFile(void); virtual uint32 write(const void *ptr, uint32 size); virtual bool flush(void) {} - virtual bool ioFailed(void) { return false; }; - virtual void clearIOFailed(void) {} + virtual bool err(void) const { return false; } + virtual void clearErr(void) {} private: Ps2SaveFileManager *_saveMan; char _fileName[256]; @@ -111,7 +111,6 @@ public: virtual int32 tell(void); virtual int32 size(void); virtual int seek(int32 offset, int origin); - virtual bool eof(void); }; #endif // __PS2_SAVEFILE__ diff --git a/backends/saves/compressed/compressed-saves.cpp b/backends/saves/compressed/compressed-saves.cpp index 27b8749911..000fec9553 100644 --- a/backends/saves/compressed/compressed-saves.cpp +++ b/backends/saves/compressed/compressed-saves.cpp @@ -98,8 +98,8 @@ public: delete _wrapped; } - bool ioFailed() const { return (_zlibErr != Z_OK) && (_zlibErr != Z_STREAM_END); } - void clearIOFailed() { /* errors here are not recoverable! */ } + bool err() const { return (_zlibErr != Z_OK) && (_zlibErr != Z_STREAM_END); } + void clearErr() { /* errors here are not recoverable! */ } uint32 read(void *dataPtr, uint32 dataSize) { _stream.next_out = (byte *)dataPtr; @@ -166,7 +166,7 @@ public: // huge amounts of data, but usually client code will only skip a few // bytes, so this should be fine. byte tmpBuf[1024]; - while (!ioFailed() && offset > 0) { + while (!err() && offset > 0) { offset -= read(tmpBuf, MIN((int32)sizeof(tmpBuf), offset)); } @@ -236,14 +236,15 @@ public: delete _wrapped; } - bool ioFailed() const { - return (_zlibErr != Z_OK && _zlibErr != Z_STREAM_END) || _wrapped->ioFailed(); + bool err() const { + // CHECKME: does Z_STREAM_END make sense here? + return (_zlibErr != Z_OK && _zlibErr != Z_STREAM_END) || _wrapped->err(); } - void clearIOFailed() { + void clearErr() { // Note: we don't reset the _zlibErr here, as it is not - // clear in general ho - _wrapped->clearIOFailed(); + // clear in general how + _wrapped->clearErr(); } void finalize() { @@ -267,7 +268,7 @@ public: } uint32 write(const void *dataPtr, uint32 dataSize) { - if (ioFailed()) + if (err()) return 0; // Hook in the new data ... diff --git a/common/file.cpp b/common/file.cpp index 1297775f15..668c97a734 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -170,6 +170,16 @@ void File::clearIOFailed() { _handle->clearIOFailed(); } +bool File::err() const { + assert(_handle); + return _handle->err(); +} + +void File::clearErr() { + assert(_handle); + _handle->clearErr(); +} + bool File::eos() const { assert(_handle); return _handle->eos(); @@ -236,12 +246,12 @@ bool DumpFile::isOpen() const { return _handle != NULL; } -bool DumpFile::ioFailed() const { +bool DumpFile::err() const { assert(_handle); return _handle->ioFailed(); } -void DumpFile::clearIOFailed() { +void DumpFile::clearErr() { assert(_handle); _handle->clearIOFailed(); } diff --git a/common/file.h b/common/file.h index b4cadd7256..a2739f795f 100644 --- a/common/file.h +++ b/common/file.h @@ -90,6 +90,8 @@ public: bool ioFailed() const; void clearIOFailed(); + bool err() const; + void clearErr(); bool eos() const; virtual int32 pos() const; @@ -126,9 +128,8 @@ public: */ bool isOpen() const; - - bool ioFailed() const; - void clearIOFailed(); + bool err() const; + void clearErr(); virtual uint32 write(const void *dataPtr, uint32 dataSize); diff --git a/common/iff_container.h b/common/iff_container.h index 9d477276fc..a70548abd4 100644 --- a/common/iff_container.h +++ b/common/iff_container.h @@ -162,7 +162,7 @@ public: void incBytesRead(uint32 inc) { bytesRead += inc; if (bytesRead > size) { - error("Chunk overead"); + error("Chunk overread"); } } @@ -172,19 +172,23 @@ public: bytesRead = 0; } + bool hasReadAll() const { + return (size - bytesRead) == 0; + } + void feed() { if (size % 2) { size++; } - while (!_input->eos() && !eos()) { + while (!hasReadAll()) { readByte(); } } // Common::ReadStream implementation - bool eos() const { - return (size - bytesRead) == 0; - } + bool eos() const { return _input->eos(); } + bool err() const { return _input->err(); } + void clearErr() { _input->clearErr(); } uint32 read(void *dataPtr, uint32 dataSize) { incBytesRead(dataSize); @@ -209,7 +213,7 @@ public: _chunk.feed(); _formChunk.incBytesRead(_chunk.size); - if (_formChunk.eos()) + if (_formChunk.hasReadAll()) return 0; _formChunk.incBytesRead(8); diff --git a/common/stream.cpp b/common/stream.cpp index 1ddaa17575..9bcc29550f 100644 --- a/common/stream.cpp +++ b/common/stream.cpp @@ -43,8 +43,10 @@ MemoryReadStream *ReadStream::readStream(uint32 dataSize) { uint32 MemoryReadStream::read(void *dataPtr, uint32 dataSize) { // Read at most as many bytes as are still available... - if (dataSize > _size - _pos) + if (dataSize > _size - _pos) { dataSize = _size - _pos; + _eos = true; + } memcpy(dataPtr, _ptr, dataSize); if (_encbyte) { @@ -81,7 +83,9 @@ bool MemoryReadStream::seek(int32 offs, int whence) { } // Post-Condition assert(_pos <= _size); - + + // Reset end-of-stream flag on a successful seek + _eos = false; return true; // FIXME: STREAM REWRITE } @@ -158,22 +162,27 @@ char *SeekableReadStream::readLine_NEW(char *buf, size_t bufSize) { // If end-of-file occurs before any characters are read, return NULL // and the buffer contents remain unchanged. - if (eos() || ioFailed()) { + if (eos() || err()) { return 0; } - // Loop as long as the stream has not ended, there is still free - // space in the buffer, and the line has not ended - while (!eos() && len + 1 < bufSize && c != LF) { + // Loop as long as there is still free space in the buffer, + // and the line has not ended + while (len + 1 < bufSize && c != LF) { c = readByte(); - - // If end-of-file occurs before any characters are read, return - // NULL and the buffer contents remain unchanged. - if (len == 0 && eos()) - return 0; - - // If an error occurs, return NULL and the buffer contents are indeterminate. - if (ioFailed()) + + if (eos()) { + // If end-of-file occurs before any characters are read, return + // NULL and the buffer contents remain unchanged. + if (len == 0) + return 0; + + break; + } + + // If an error occurs, return NULL and the buffer contents + // are indeterminate. + if (err()) return 0; // Check for CR or CR/LF @@ -183,8 +192,18 @@ char *SeekableReadStream::readLine_NEW(char *buf, size_t bufSize) { if (c == CR) { // Look at the next char -- is it LF? If not, seek back c = readByte(); - if (c != LF && !eos()) + + if (err()) { + return 0; // error: the buffer contents are indeterminate + } + if (eos()) { + // The CR was the last character in the file. + // Reset the eos() flag since we successfully finished a line + clearErr(); + } else if (c != LF) { seek(-1, SEEK_CUR); + } + // Treat CR & CR/LF as plain LF c = LF; } @@ -193,15 +212,6 @@ char *SeekableReadStream::readLine_NEW(char *buf, size_t bufSize) { len++; } - // FIXME: - // This should fix a bug while using readLine with Common::File - // it seems that it sets the eos flag after an invalid read - // and at the same time the ioFailed flag - // the config file parser fails out of that reason for the new themes - if (eos()) { - clearIOFailed(); - } - // We always terminate the buffer if no error occured *p = 0; return buf; @@ -226,9 +236,13 @@ String SeekableReadStream::readLine() { uint32 SubReadStream::read(void *dataPtr, uint32 dataSize) { - dataSize = MIN(dataSize, _end - _pos); + if (dataSize > _end - _pos) { + dataSize = _end - _pos; + _eos = true; + } dataSize = _parentStream->read(dataPtr, dataSize); + _eos |= _parentStream->eos(); _pos += dataSize; return dataSize; @@ -241,6 +255,7 @@ SeekableSubReadStream::SeekableSubReadStream(SeekableReadStream *parentStream, u assert(_begin <= _end); _pos = _begin; _parentStream->seek(_pos); + _eos = false; } bool SeekableSubReadStream::seek(int32 offset, int whence) { @@ -261,7 +276,10 @@ bool SeekableSubReadStream::seek(int32 offset, int whence) { assert(_pos >= _begin); assert(_pos <= _end); - return _parentStream->seek(_pos); + bool ret = _parentStream->seek(_pos); + if (ret) _eos = false; // reset eos on successful seek + + return ret; } BufferedReadStream::BufferedReadStream(ReadStream *parentStream, uint32 bufSize, bool disposeParentStream) diff --git a/common/stream.h b/common/stream.h index 14449a5075..d88e252661 100644 --- a/common/stream.h +++ b/common/stream.h @@ -41,19 +41,30 @@ public: virtual ~Stream() {} /** - * Returns true if any I/O failure occurred. - * This flag is never cleared automatically. In order to clear it, - * client code has to call clearIOFailed() explicitly. - * - * @todo Instead of returning a plain bool, maybe we should define - * a list of error codes which can be returned here. + * DEPRECATED: Use err() or eos() instead. + * Returns true if any I/O failure occurred or the end of the + * stream was reached while reading. */ - virtual bool ioFailed() const { return false; } + virtual bool ioFailed() const { return err(); } /** + * DEPRECATED: Don't use this unless you are still using ioFailed(). * Reset the I/O error status. */ - virtual void clearIOFailed() {} + virtual void clearIOFailed() { clearErr(); } + + /** + * Returns true if an I/O failure occurred. + * This flag is never cleared automatically. In order to clear it, + * client code has to call clearErr() explicitly. + */ + virtual bool err() const { return false; } + + /** + * Reset the I/O error status as returned by err(). + * For a ReadStream, also reset the end-of-stream status returned by eos(). + */ + virtual void clearErr() {} }; /** @@ -87,7 +98,7 @@ public: * closing (and this flushing, if buffered) the stream. * * After this method has been called, no further writes may be - * performed on the stream. Calling ioFailed() is allowed. + * performed on the stream. Calling err() is allowed. * * By default, this just flushes the stream. */ @@ -153,7 +164,9 @@ public: class ReadStream : virtual public Stream { public: /** - * Returns true if the end of the stream has been reached. + * Returns true if a read failed because the stream has been reached. + * This flag is cleared by clearErr(). + * For a SeekableReadStream, it is also cleared by a successful seek. */ virtual bool eos() const = 0; @@ -172,10 +185,16 @@ public: // in general should not overload them. /** + * DEPRECATED + * Default implementation for backward compatibility + */ + virtual bool ioFailed() { return (eos() || err()); } + + /** * Read an unsigned byte from the stream and return it. * Performs no error checking. The return value is undefined * if a read error occurred (for which client code can check by - * calling ioFailed()). + * calling err() and eos() ). */ byte readByte() { byte b = 0; @@ -187,7 +206,7 @@ public: * Read a signed byte from the stream and return it. * Performs no error checking. The return value is undefined * if a read error occurred (for which client code can check by - * calling ioFailed()). + * calling err() and eos() ). */ int8 readSByte() { int8 b = 0; @@ -200,7 +219,7 @@ public: * from the stream and return it. * Performs no error checking. The return value is undefined * if a read error occurred (for which client code can check by - * calling ioFailed()). + * calling err() and eos() ). */ uint16 readUint16LE() { uint16 a = readByte(); @@ -213,7 +232,7 @@ public: * from the stream and return it. * Performs no error checking. The return value is undefined * if a read error occurred (for which client code can check by - * calling ioFailed()). + * calling err() and eos() ). */ uint32 readUint32LE() { uint32 a = readUint16LE(); @@ -226,7 +245,7 @@ public: * from the stream and return it. * Performs no error checking. The return value is undefined * if a read error occurred (for which client code can check by - * calling ioFailed()). + * calling err() and eos() ). */ uint16 readUint16BE() { uint16 b = readByte(); @@ -239,7 +258,7 @@ public: * from the stream and return it. * Performs no error checking. The return value is undefined * if a read error occurred (for which client code can check by - * calling ioFailed()). + * calling err() and eos() ). */ uint32 readUint32BE() { uint32 b = readUint16BE(); @@ -252,7 +271,7 @@ public: * from the stream and return it. * Performs no error checking. The return value is undefined * if a read error occurred (for which client code can check by - * calling ioFailed()). + * calling err() and eos() ). */ int16 readSint16LE() { return (int16)readUint16LE(); @@ -263,7 +282,7 @@ public: * from the stream and return it. * Performs no error checking. The return value is undefined * if a read error occurred (for which client code can check by - * calling ioFailed()). + * calling err() and eos() ). */ int32 readSint32LE() { return (int32)readUint32LE(); @@ -274,7 +293,7 @@ public: * from the stream and return it. * Performs no error checking. The return value is undefined * if a read error occurred (for which client code can check by - * calling ioFailed()). + * calling err() and eos() ). */ int16 readSint16BE() { return (int16)readUint16BE(); @@ -285,7 +304,7 @@ public: * from the stream and return it. * Performs no error checking. The return value is undefined * if a read error occurred (for which client code can check by - * calling ioFailed()). + * calling err() and eos() ). */ int32 readSint32BE() { return (int32)readUint32BE(); @@ -295,7 +314,9 @@ public: * Read the specified amount of data into a malloc'ed buffer * which then is wrapped into a MemoryReadStream. * The returned stream might contain less data than requested, - * if reading more failed. + * if reading more failed, because of an I/O error or because + * the end of the stream was reached. Which can be determined by + * calling err() and eos(). */ MemoryReadStream *readStream(uint32 dataSize); @@ -365,7 +386,7 @@ public: * and the buffer contents remain unchanged. If an error occurs, * returns NULL and the buffer contents are indeterminate. * This method does not distinguish between end-of-file and error; - * callers muse use ioFailed() or eos() to determine which occurred. + * callers must use err() or eos() to determine which occurred. * * @note This methods is closely modeled after the standard fgets() * function from stdio.h. @@ -403,6 +424,7 @@ protected: bool _disposeParentStream; uint32 _pos; uint32 _end; + bool _eos; public: SubReadStream(ReadStream *parentStream, uint32 end, bool disposeParentStream = false) : _parentStream(parentStream), @@ -415,7 +437,9 @@ public: if (_disposeParentStream) delete _parentStream; } - virtual bool eos() const { return _pos == _end; } + virtual bool eos() const { return _eos; } + virtual bool err() const { return _parentStream->err(); } + virtual void clearErr() { _eos = false; _parentStream->clearErr(); } virtual uint32 read(void *dataPtr, uint32 dataSize); }; @@ -487,6 +511,8 @@ public: virtual bool eos() const { return (_pos == _bufSize) && _parentStream->eos(); } virtual bool ioFailed() const { return _parentStream->ioFailed(); } virtual void clearIOFailed() { _parentStream->clearIOFailed(); } + virtual bool err() const { return _parentStream->err(); } + virtual void clearErr() { _parentStream->clearErr(); } virtual uint32 read(void *dataPtr, uint32 dataSize); }; @@ -521,6 +547,7 @@ private: uint32 _pos; byte _encbyte; bool _disposeMemory; + bool _eos; public: @@ -535,7 +562,8 @@ public: _size(dataSize), _pos(0), _encbyte(0), - _disposeMemory(disposeMemory) {} + _disposeMemory(disposeMemory), + _eos(false) {} ~MemoryReadStream() { if (_disposeMemory) @@ -546,7 +574,9 @@ public: uint32 read(void *dataPtr, uint32 dataSize); - bool eos() const { return _pos == _size; } // FIXME: Wrong + bool eos() const { return _eos; } + void clearErr() { _eos = false; } + int32 pos() const { return _pos; } int32 size() const { return _size; } @@ -603,7 +633,6 @@ public: return dataSize; } - bool eos() const { return _pos == _bufSize; } uint32 pos() const { return _pos; } uint32 size() const { return _bufSize; } }; @@ -657,7 +686,6 @@ public: return dataSize; } - bool eos() const { return false; } uint32 pos() const { return _pos; } uint32 size() const { return _size; } diff --git a/engines/drascula/drascula.cpp b/engines/drascula/drascula.cpp index af32a0c2e5..34f3701f31 100644 --- a/engines/drascula/drascula.cpp +++ b/engines/drascula/drascula.cpp @@ -598,8 +598,10 @@ char *DrasculaEngine::getLine(char *buf, int len) { for (;;) { b = buf; - while (!_arj.eos()) { + while (true) { c = ~_arj.readByte(); + if (_arj.eos()) break; + if (c == '\r') continue; if (c == '\n' || b - buf >= (len - 1)) diff --git a/engines/gob/dataio.cpp b/engines/gob/dataio.cpp index 0a3f317ada..d154a01de9 100644 --- a/engines/gob/dataio.cpp +++ b/engines/gob/dataio.cpp @@ -95,7 +95,7 @@ bool DataStream::eos() const { if (_stream) return _stream->eos(); - return pos() >= size(); + return pos() >= size(); // FIXME (eos definition change) } uint32 DataStream::read(void *dataPtr, uint32 dataSize) { diff --git a/engines/m4/converse.cpp b/engines/m4/converse.cpp index 47d84f6a28..11131783e2 100644 --- a/engines/m4/converse.cpp +++ b/engines/m4/converse.cpp @@ -406,10 +406,12 @@ void Converse::loadConversation(const char *convName) { convS->read(buffer, 8); if (debugFlag) printf("Conversation name: %s\n", buffer); - while(!convS->eos()) { + while(true) { chunkPos = convS->pos(); - if (debugFlag) printf("***** Pos: %i -> ", chunkPos); chunk = convS->readUint32LE(); // read chunk + if (convS->eos()) break; + + if (debugFlag) printf("***** Pos: %i -> ", chunkPos); switch(chunk) { case CHUNK_DECL: // Declare if (debugFlag) printf("DECL chunk\n"); @@ -714,7 +716,7 @@ void Converse::loadConversationMads(const char *convName) { printf("Chunk 0\n"); printf("Conv stream size: %i\n", convS->size()); - while(!convS->eos()) { + while(!convS->eos()) { // FIXME (eos changed) printf("%i ", convS->readByte()); } printf("\n"); @@ -725,7 +727,7 @@ void Converse::loadConversationMads(const char *convName) { printf("Chunk 1\n"); printf("Conv stream size: %i\n", convS->size()); - while(!convS->eos()) { + while(!convS->eos()) { // FIXME (eos changed) printf("%i ", convS->readByte()); } printf("\n"); @@ -736,7 +738,7 @@ void Converse::loadConversationMads(const char *convName) { printf("Chunk 2\n"); printf("Conv stream size: %i\n", convS->size()); - while(!convS->eos()) { + while(!convS->eos()) { // FIXME (eos changed) printf("%i ", convS->readByte()); } printf("\n"); @@ -790,7 +792,7 @@ void Converse::loadConversationMads(const char *convName) { convS->read(buffer, 14); // speech file printf("Speech file: %s\n", buffer); - while(!convS->eos()) { + while(!convS->eos()) { // FIXME: eos changed printf("%i ", convS->readByte()); } printf("\n"); @@ -803,9 +805,12 @@ void Converse::loadConversationMads(const char *convName) { printf("Chunk 1: conversation nodes\n"); printf("Conv stream size: %i\n", convS->size()); - while(!convS->eos()) { + while(true) { + uint16 id = convS->readUint16LE(); + if (convS->eos()) break; + curEntry = new ConvEntry(); - curEntry->id = convS->readUint16LE(); + curEntry->id = id; curEntry->entryCount = convS->readUint16LE(); curEntry->flags = convS->readUint16LE(); if (curEntry->entryCount == 1 && curEntry->flags != 65535) { @@ -839,10 +844,13 @@ void Converse::loadConversationMads(const char *convName) { *buffer = 0; - while(!convS->eos()) { + while(true) { //if (curPos == 0) // printf("%i: Offset %i: ", _convStrings.size(), convS->pos()); - buffer[curPos++] = convS->readByte(); + uint8 b = convS->readByte(); + if (convS->eos()) break; + + buffer[curPos++] = b; if (buffer[curPos - 1] == '~') { // filter out special characters curPos--; continue; @@ -892,9 +900,12 @@ void Converse::loadConversationMads(const char *convName) { //printf("Chunk 3 - MESG chunk data\n"); //printf("Conv stream size: %i\n", convS->size()); - while(!convS->eos()) { + while(true) { + uint16 index = convS->readUint16LE(); + if (convS->eos()) break; + curMessage = new MessageEntry(); - stringIndex = convS->readUint16LE(); + stringIndex = index; stringCount = convS->readUint16LE(); *buffer = 0; //printf("Message: %i\n", _madsMessageList.size()); @@ -915,7 +926,7 @@ void Converse::loadConversationMads(const char *convName) { convS = convData.getItemStream(6); printf("Chunk 6\n"); printf("Conv stream size: %i\n", convS->size()); - /*while(!convS->eos()) { + /*while(!convS->eos()) { // FIXME (eos changed) printf("%i ", convS->readByte()); printf("%i ", convS->readByte()); printf("%i ", convS->readByte()); @@ -954,8 +965,10 @@ void Converse::readConvEntryActions(Common::SubReadStream *convS, ConvEntry *cur int messageIndex = 0; int unk = 0; - while(!convS->eos()) { + while(true) { chunk = convS->readByte(); + if (convS->eos()) break; + type = convS->readByte(); switch (chunk) { diff --git a/engines/m4/globals.cpp b/engines/m4/globals.cpp index 58c68979d1..98d007f67e 100644 --- a/engines/m4/globals.cpp +++ b/engines/m4/globals.cpp @@ -295,8 +295,11 @@ void Globals::loadMadsVocab() { char buffer[30]; strcpy(buffer, ""); - while(!vocabS->eos()) { - buffer[curPos++] = vocabS->readByte(); + while(true) { + uint8 b = vocabS->readByte(); + if (vocabS->eos()) break; + + buffer[curPos++] = b; if (buffer[curPos - 1] == '\0') { // end of string, add it to the strings list _madsVocab.push_back(strdup(buffer)); @@ -315,8 +318,11 @@ void Globals::loadMadsQuotes() { char buffer[128]; strcpy(buffer, ""); - while(!quoteS->eos()) { - buffer[curPos++] = quoteS->readByte(); + while(true) { + uint8 b = quoteS->readByte(); + if (quoteS->eos()) break; + + buffer[curPos++] = b; if (buffer[curPos - 1] == '\0') { // end of string, add it to the strings list _madsQuotes.push_back(strdup(buffer)); diff --git a/engines/m4/mads_anim.cpp b/engines/m4/mads_anim.cpp index e028f5e0f1..71b45ca77c 100644 --- a/engines/m4/mads_anim.cpp +++ b/engines/m4/mads_anim.cpp @@ -247,15 +247,16 @@ void TextviewView::scriptDone() { } void TextviewView::processLines() { + _script->readLine_OLD(_currentLine, 79); if (_script->eos()) error("Attempted to read past end of response file"); while (!_script->eos()) { - _script->readLine_OLD(_currentLine, 79); - // Commented out line, so go loop for another - if (_currentLine[0] == '#') + if (_currentLine[0] == '#') { + _script->readLine_OLD(_currentLine, 79); continue; + } // Process the line char *cStart = strchr(_currentLine, '['); @@ -284,6 +285,8 @@ void TextviewView::processLines() { processText(); break; } + + _script->readLine_OLD(_currentLine, 79); } } @@ -594,6 +597,7 @@ void AnimviewView::scriptDone() { } void AnimviewView::processLines() { + _script->readLine_OLD(_currentLine, 79); if (_script->eos()) { // end of script, end animation scriptDone(); @@ -601,8 +605,6 @@ void AnimviewView::processLines() { } while (!_script->eos()) { - _script->readLine_OLD(_currentLine, 79); - // Process the line char *cStart = strchr(_currentLine, '-'); if (cStart) { @@ -635,6 +637,8 @@ void AnimviewView::processLines() { //printf("File: %s\n", _currentLine); break; } + + _script->readLine_OLD(_currentLine, 79); } } diff --git a/engines/made/redreader.cpp b/engines/made/redreader.cpp index 5d0721bc1f..a61d122041 100644 --- a/engines/made/redreader.cpp +++ b/engines/made/redreader.cpp @@ -55,9 +55,11 @@ Common::MemoryReadStream *RedReader::loadFromRed(const char *redFilename, const bool RedReader::seekFile(Common::File &fd, FileEntry &fileEntry, const char *filename) { char arcFilename[13]; - while (!fd.eos()) { + while (true) { fd.skip(8); // skip unknown fileEntry.compSize = fd.readUint32LE(); + if (fd.eos()) break; + fileEntry.origSize = fd.readUint32LE(); fd.skip(10); // skip unknown fd.read(arcFilename, 13); diff --git a/engines/parallaction/disk_ns.cpp b/engines/parallaction/disk_ns.cpp index c50373aba1..54d4d1e5da 100644 --- a/engines/parallaction/disk_ns.cpp +++ b/engines/parallaction/disk_ns.cpp @@ -165,7 +165,7 @@ int32 Archive::pos() const { } bool Archive::eos() const { - return (_file == true ? _fileCursor == _fileEndOffset : true ); + return (_file == true ? _fileCursor == _fileEndOffset : true ); // FIXME (eos definition change) } bool Archive::seek(int32 offs, int whence) { diff --git a/engines/parallaction/parser.h b/engines/parallaction/parser.h index 7bf41b2bea..f0cc448518 100644 --- a/engines/parallaction/parser.h +++ b/engines/parallaction/parser.h @@ -456,7 +456,7 @@ public: } bool eos() const { - return _pos == _size; + return _pos == _size; // FIXME (eos definition change) } }; diff --git a/engines/saga/animation.cpp b/engines/saga/animation.cpp index 9fffb0f8bf..e9e146013f 100644 --- a/engines/saga/animation.cpp +++ b/engines/saga/animation.cpp @@ -866,7 +866,7 @@ int Anim::fillFrameOffsets(AnimationData *anim, bool reallyFill) { readS._bigEndian = !_vm->isBigEndian(); // RLE has inversion BE<>LE - while (!readS.eos()) { + while (readS.pos() != readS.size()) { if (reallyFill) { anim->frameOffsets[currentFrame] = readS.pos(); diff --git a/engines/saga/sprite.cpp b/engines/saga/sprite.cpp index d9c7b446ba..ee2e2b922f 100644 --- a/engines/saga/sprite.cpp +++ b/engines/saga/sprite.cpp @@ -423,6 +423,7 @@ void Sprite::decodeRLEBuffer(const byte *inputBuffer, size_t inLength, size_t ou } for (c = 0; c < fg_runcount && !readS.eos(); c++) { + // FIXME: eos changed; error handling? *outPointer = readS.readByte(); if (outPointer < outPointerEnd) outPointer++; diff --git a/engines/scumm/file.cpp b/engines/scumm/file.cpp index 22079332e4..f258ddd420 100644 --- a/engines/scumm/file.cpp +++ b/engines/scumm/file.cpp @@ -126,7 +126,7 @@ bool ScummFile::openSubFile(const Common::String &filename) { bool ScummFile::eos() { - return _subFileLen ? (pos() >= _subFileLen) : File::eos(); + return _subFileLen ? (pos() >= _subFileLen) : File::eos(); // FIXME } int32 ScummFile::pos() { diff --git a/graphics/iff.cpp b/graphics/iff.cpp index 514fba9cc0..b3846c5d26 100644 --- a/graphics/iff.cpp +++ b/graphics/iff.cpp @@ -219,7 +219,7 @@ void PBMDecoder::readBODY(Common::IFFChunk& chunk) { switch (_bitmapHeader.pack) { case 0: - while (!chunk.eos()) { + while (!chunk.hasReadAll()) { ((byte*)_surface->pixels)[si++] = chunk.readByte(); } break; @@ -245,7 +245,9 @@ PackBitsReadStream::~PackBitsReadStream() { } bool PackBitsReadStream::eos() const { - return _input->eos() & (_rStoragePos == _wStoragePos); + //FIXME: eos definition needs to be changed in parallaction engine + // which is the only place where this class is used + return _input->eos() && (_rStoragePos == _wStoragePos); } uint32 PackBitsReadStream::read(void *dataPtr, uint32 dataSize) { @@ -291,6 +293,9 @@ void PackBitsReadStream::unpack() { while (_out < _outEnd && !_input->eos()) { byteRun = _input->readByte(); + //FIXME: eos definition needs to be changed in parallaction engine + // which is the only place where this class is used + //if (_input->eos()) break; if (byteRun <= 127) { i = byteRun + 1; for (j = 0; j < i; j++) { diff --git a/test/common/bufferedreadstream.h b/test/common/bufferedreadstream.h index 2644745af2..c580fd18de 100644 --- a/test/common/bufferedreadstream.h +++ b/test/common/bufferedreadstream.h @@ -9,7 +9,7 @@ class BufferedReadStreamTestSuite : public CxxTest::TestSuite { Common::MemoryReadStream ms(contents, 10); // Use a buffer size of 4 -- note that 10 % 4 != 0, - // so we test what happens if the cache can't be completly + // so we test what happens if the cache can't be completely // refilled. Common::BufferedReadStream srs(&ms, 4); @@ -21,6 +21,10 @@ class BufferedReadStreamTestSuite : public CxxTest::TestSuite { TS_ASSERT_EQUALS( i, b ); } - TS_ASSERT( srs.eos() ); + TS_ASSERT( !srs.eos() ); + + b = srs.readByte(); + + TS_ASSERT ( srs.eos() ); } }; diff --git a/test/common/bufferedseekablereadstream.h b/test/common/bufferedseekablereadstream.h index c3e85c1b66..aa3bd9225c 100644 --- a/test/common/bufferedseekablereadstream.h +++ b/test/common/bufferedseekablereadstream.h @@ -20,6 +20,9 @@ class BufferedSeekableReadStreamTestSuite : public CxxTest::TestSuite { TS_ASSERT_EQUALS( i, b ); } + TS_ASSERT( !ssrs.eos() ); + + TS_ASSERT( 0 == ssrs.read(&b, 1) ); TS_ASSERT( ssrs.eos() ); } @@ -49,9 +52,12 @@ class BufferedSeekableReadStreamTestSuite : public CxxTest::TestSuite { ssrs.seek(0, SEEK_END); TS_ASSERT_EQUALS( ssrs.pos(), (uint32)10 ); + TS_ASSERT( !ssrs.eos() ); + b = ssrs.readByte(); TS_ASSERT( ssrs.eos() ); ssrs.seek(3, SEEK_END); + TS_ASSERT( !ssrs.eos() ); TS_ASSERT_EQUALS( ssrs.pos(), (uint32)7 ); b = ssrs.readByte(); TS_ASSERT_EQUALS( b, 7 ); diff --git a/test/common/seekablesubreadstream.h b/test/common/seekablesubreadstream.h index 4e517093a5..24df380a60 100644 --- a/test/common/seekablesubreadstream.h +++ b/test/common/seekablesubreadstream.h @@ -23,6 +23,8 @@ class SeekableSubReadStreamTestSuite : public CxxTest::TestSuite { TS_ASSERT_EQUALS( i, b ); } + TS_ASSERT( !ssrs.eos() ); + TS_ASSERT( 0 == ssrs.read(&b, 1) ); TS_ASSERT( ssrs.eos() ); } @@ -52,9 +54,12 @@ class SeekableSubReadStreamTestSuite : public CxxTest::TestSuite { ssrs.seek(0, SEEK_END); TS_ASSERT_EQUALS( ssrs.pos(), (uint32)8 ); + TS_ASSERT( !ssrs.eos() ); + b = ssrs.readByte(); TS_ASSERT( ssrs.eos() ); ssrs.seek(3, SEEK_END); + TS_ASSERT( !ssrs.eos() ); TS_ASSERT_EQUALS( ssrs.pos(), (uint32)5 ); b = ssrs.readByte(); TS_ASSERT_EQUALS( b, 6 ); diff --git a/test/common/stream.h b/test/common/stream.h index 99e70d3a50..a605d34a2c 100644 --- a/test/common/stream.h +++ b/test/common/stream.h @@ -19,6 +19,10 @@ class ReadLineStreamTestSuite : public CxxTest::TestSuite { TS_ASSERT(0 != ms.readLine_NEW(buffer, sizeof(buffer))); TS_ASSERT(0 == strcmp(buffer, "c\n")); + TS_ASSERT(!ms.eos()); + + TS_ASSERT(0 == ms.readLine_NEW(buffer, sizeof(buffer))); + TS_ASSERT(ms.eos()); } diff --git a/test/common/subreadstream.h b/test/common/subreadstream.h index 4e14448c06..2ac453576a 100644 --- a/test/common/subreadstream.h +++ b/test/common/subreadstream.h @@ -21,6 +21,8 @@ class SubReadStreamTestSuite : public CxxTest::TestSuite { TS_ASSERT_EQUALS( i, b ); } + TS_ASSERT( !srs.eos() ); + b = srs.readByte(); TS_ASSERT( srs.eos() ); } }; |