diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/file.cpp | 14 | ||||
-rw-r--r-- | common/file.h | 7 | ||||
-rw-r--r-- | common/iff_container.h | 16 | ||||
-rw-r--r-- | common/stream.cpp | 70 | ||||
-rw-r--r-- | common/stream.h | 82 |
5 files changed, 125 insertions, 64 deletions
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; } |