aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/file.cpp14
-rw-r--r--common/file.h7
-rw-r--r--common/iff_container.h16
-rw-r--r--common/stream.cpp70
-rw-r--r--common/stream.h82
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; }