diff options
author | Max Horn | 2005-04-22 17:40:09 +0000 |
---|---|---|
committer | Max Horn | 2005-04-22 17:40:09 +0000 |
commit | 969ef3dac93a21d981e4cc2a8c81c0f03a834417 (patch) | |
tree | 9240363f92815c7e92e53b0b42e8d553d4a478c3 | |
parent | ca33ec4563e05b0940e44de78e0f52bbbf6bfe41 (diff) | |
download | scummvm-rg350-969ef3dac93a21d981e4cc2a8c81c0f03a834417.tar.gz scummvm-rg350-969ef3dac93a21d981e4cc2a8c81c0f03a834417.tar.bz2 scummvm-rg350-969ef3dac93a21d981e4cc2a8c81c0f03a834417.zip |
* Added new virtual base class 'Stream', ReadStream and
WriteStream are now subclasses of it.
* Added new methods eos(), ioFailed(), clearIOFailed() to
all streams. This allows better error checking.
* SaveFile classes take advantage of these new standard
stream APIS
* Removed File::gets()
* Added SeekableReadStream::readLine() (replaces File::gets)
* Added WriteStream::writeString, for convenience
svn-id: r17752
-rw-r--r-- | common/file.cpp | 65 | ||||
-rw-r--r-- | common/file.h | 2 | ||||
-rw-r--r-- | common/savefile.cpp | 12 | ||||
-rw-r--r-- | common/savefile.h | 5 | ||||
-rw-r--r-- | common/stream.cpp | 61 | ||||
-rw-r--r-- | common/stream.h | 55 | ||||
-rw-r--r-- | kyra/script.cpp | 5 | ||||
-rw-r--r-- | saga/sprite.cpp | 2 | ||||
-rw-r--r-- | scumm/util.h | 2 | ||||
-rw-r--r-- | simon/saveload.cpp | 2 | ||||
-rw-r--r-- | sound/softsynth/mt32.cpp | 2 | ||||
-rw-r--r-- | sword2/function.cpp | 2 |
12 files changed, 126 insertions, 89 deletions
diff --git a/common/file.cpp b/common/file.cpp index f3241cdf6e..85cd75fd51 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -278,68 +278,3 @@ uint32 File::write(const void *ptr, uint32 len) { return len; } - -#define LF 0x0A -#define CR 0x0D - -char *File::gets(void *ptr, uint32 len) { - char *ptr2 = (char *)ptr; - char *res = ptr2; - uint32 read_chars = 1; - - if (_handle == NULL) { - error("File::gets: File is not open!"); - return 0; - } - - if (len == 0 || !ptr) - return NULL; - - // We don't include the newline character(s) in the buffer, and we - // always terminate it - we never read more than len-1 characters. - - // EOF is treated as a line break, unless it was the first character - // that was read. - - // 0 is treated as a line break, even though it should never occur in - // a text file. - - // DOS and Windows use CRLF line breaks - // Unix and OS X use LF line breaks - // Macintosh before OS X uses CR line breaks - - bool first = true; - - while (read_chars < len) { - int c = getc(_handle); - - if (c == EOF) { - if (first) - return NULL; - break; - } - - first = false; - - if (c == 0) - break; - - if (c == LF) - break; - - if (c == CR) { - c = getc(_handle); - // Don't use ungetc() here. It might be slightly more - // elegant, but PalmOS doesn't have it. - if (c != LF && c != EOF) - fseek(_handle, -1, SEEK_CUR); - break; - } - - *ptr2++ = (char) c; - read_chars++; - } - - *ptr2 = 0; - return res; -} diff --git a/common/file.h b/common/file.h index 803d0d5905..cda98bac10 100644 --- a/common/file.h +++ b/common/file.h @@ -66,6 +66,7 @@ public: bool isOpen() const; bool ioFailed() const; void clearIOFailed(); + bool eos() const { return eof(); } bool eof() const; uint32 pos() const; uint32 size() const; @@ -73,7 +74,6 @@ public: void seek(int32 offs, int whence = SEEK_SET); uint32 read(void *ptr, uint32 size); uint32 write(const void *ptr, uint32 size); - char *gets(void *ptr, uint32 size); }; #endif diff --git a/common/savefile.cpp b/common/savefile.cpp index 02234a9a78..aa6e54b9f1 100644 --- a/common/savefile.cpp +++ b/common/savefile.cpp @@ -73,8 +73,10 @@ public: ::fclose(fh); } - bool readingFailed() const { return ferror(fh) != 0; } - bool writingFailed() const { return ferror(fh) != 0; } + bool eos() const { return feof(fh) != 0; } + bool ioFailed() const { return ferror(fh) != 0; } + void clearIOFailed() { clearerr(fh); } + bool isOpen() const { return fh != 0; } uint32 read(void *buf, uint32 cnt) { @@ -101,8 +103,10 @@ public: ::gzclose(fh); } - bool readingFailed() const { return _ioError; } - bool writingFailed() const { return _ioError; } + bool eos() const { return gzeof(fh) != 0; } + bool ioFailed() const { return _ioError; } + void clearIOFailed() { _ioError = false; } + bool isOpen() const { return fh != 0; } uint32 read(void *buf, uint32 cnt) { diff --git a/common/savefile.h b/common/savefile.h index 2431dba53a..4b4771daa9 100644 --- a/common/savefile.h +++ b/common/savefile.h @@ -40,9 +40,6 @@ class InSaveFile : public Common::ReadStream { public: virtual ~InSaveFile() {} - - virtual bool readingFailed() const { return false; } - //bool eof() const; }; /** @@ -55,8 +52,6 @@ public: class OutSaveFile : public Common::WriteStream { public: virtual ~OutSaveFile() {} - - virtual bool writingFailed() const { return false; } }; /** diff --git a/common/stream.cpp b/common/stream.cpp index 62b045fd0d..a9d5793be3 100644 --- a/common/stream.cpp +++ b/common/stream.cpp @@ -21,9 +21,13 @@ #include "stdafx.h" #include "common/stream.h" +#include "common/str.h" namespace Common { +void WriteStream::writeString(const String &str) { + write(str.c_str(), str.size()); +} void MemoryReadStream::seek(int32 offs, int whence) { // Pre-Condition @@ -48,5 +52,62 @@ void MemoryReadStream::seek(int32 offs, int whence) { assert(_pos <= _bufSize); } +#define LF 0x0A +#define CR 0x0D + +char *SeekableReadStream::readLine(char *buf, size_t bufSize) { + assert(buf && bufSize > 0); + char *p = buf; + size_t len = 0; + char c; + + if (buf == 0 || bufSize == 0 || eos()) { + return 0; + } + + // We don't include the newline character(s) in the buffer, and we + // always terminate it - we never read more than len-1 characters. + + // EOF is treated as a line break, unless it was the first character + // that was read. + + // 0 is treated as a line break, even though it should never occur in + // a text file. + + // DOS and Windows use CRLF line breaks + // Unix and OS X use LF line breaks + // Macintosh before OS X uses CR line breaks + + + c = readByte(); + if (eos() || ioFailed()) { + return 0; + } + + while (!eos() && len + 1 < bufSize) { + + if (ioFailed()) + return 0; + + if (c == 0 || c == LF) + break; + + if (c == CR) { + c = readByte(); + if (c != LF && !eos()) + seek(-1, SEEK_CUR); + break; + } + + *p++ = c; + len++; + + c = readByte(); + } + + *p = 0; + return buf; +} + } // End of namespace Common diff --git a/common/stream.h b/common/stream.h index ac0fa18296..7079d8472b 100644 --- a/common/stream.h +++ b/common/stream.h @@ -28,10 +28,38 @@ namespace Common { +class String; + +/** + * Virtual base class for both ReadStream and WriteStream. + */ +class Stream { +public: + /** + * Returns true if the end of the stream has been reached. + */ + virtual bool eos() const = 0; + + /** + * Returns true if any I/O failure occured. + * 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. + */ + virtual bool ioFailed() const { return false; } + + /** + * Reset the I/O error status. + */ + virtual void clearIOFailed() {} +}; + /** * Generic interface for a writable data stream. */ -class WriteStream { +class WriteStream : virtual public Stream { public: /** * Write data into the stream. Subclasses must implement this @@ -90,13 +118,15 @@ public: void writeSint32BE(int32 value) { writeUint32BE((uint32)value); } + + void writeString(const String &str); }; /** * Generic interface for a readable data stream. */ -class ReadStream { +class ReadStream : virtual public Stream { public: /** * Read data from the stream. Subclasses must implement this @@ -175,11 +205,22 @@ public: class SeekableReadStream : public ReadStream { public: - virtual bool eof() const = 0; virtual uint32 pos() const = 0; virtual uint32 size() const = 0; virtual void seek(int32 offs, int whence = SEEK_SET) = 0; + + /** + * Read one line of text from a CR or CR/LF terminated plain text file. + * This method is a rough analog of the (f)gets function. + * + * @param buf the buffer to store into + * @param size the size of the buffer + * @return a pointer to the read string, or NULL if an error occured + * @note The line terminator (CR or CR/LF) is stripped and not inserted + * into the buffer. + */ + virtual char *readLine(char *buf, size_t bufSize); }; @@ -200,6 +241,10 @@ public: void setStream(ReadStream *in) { _realStream = in; } void setEnc(byte value) { _encbyte = value; } + virtual bool eos() const { return _realStream->eos(); } + virtual bool ioFailed() const { return _realStream->ioFailed(); } + virtual void clearIOFailed() { _realStream->clearIOFailed(); } + uint32 read(void *ptr, uint32 size) { assert(_realStream); uint32 len = _realStream->read(ptr, size); @@ -249,7 +294,7 @@ public: return len; } - bool eof() const { return _pos == _bufSize; } + bool eos() const { return _pos == _bufSize; } uint32 pos() const { return _pos; } uint32 size() const { return _bufSize; } @@ -279,7 +324,7 @@ public: return len; } - bool eof() const { return _pos == _bufSize; } + bool eos() const { return _pos == _bufSize; } uint32 pos() const { return _pos; } uint32 size() const { return _bufSize; } }; diff --git a/kyra/script.cpp b/kyra/script.cpp index ed071df14c..755ca58925 100644 --- a/kyra/script.cpp +++ b/kyra/script.cpp @@ -413,10 +413,7 @@ void VMContext::loadScript(const char* file) { uint8 chunkName[sizeof("EMC2ORDR") + 1]; // so lets look for our chunks :) - while(true) { - if (script.eof()) { - break; - } + while (!script.eos()) { // lets read only the first 4 chars script.read(chunkName, sizeof(uint8) * 4); chunkName[4] = '\0'; diff --git a/saga/sprite.cpp b/saga/sprite.cpp index 36ed2cefc3..038e6ba001 100644 --- a/saga/sprite.cpp +++ b/saga/sprite.cpp @@ -402,7 +402,7 @@ void Sprite::decodeRLEBuffer(const byte *inputBuffer, size_t inLength, size_t ou MemoryReadStream readS(inputBuffer, inLength); - while (!readS.eof() && (outPointer < outPointerEnd)) { + while (!readS.eos() && (outPointer < outPointerEnd)) { bg_runcount = readS.readByte(); fg_runcount = readS.readByte(); diff --git a/scumm/util.h b/scumm/util.h index 48821755b1..4bef2ebe81 100644 --- a/scumm/util.h +++ b/scumm/util.h @@ -100,7 +100,7 @@ public: bool openSubFile(const char *filename); void close(); - bool eof() { return _stream->eof(); } + bool eof() { return _stream->eos(); } uint32 pos() { return _stream->pos(); } uint32 size() { return _stream->size(); } void seek(int32 offs, int whence = SEEK_SET) { _stream->seek(offs, whence); } diff --git a/simon/saveload.cpp b/simon/saveload.cpp index 7892da4f46..658b4c5c6b 100644 --- a/simon/saveload.cpp +++ b/simon/saveload.cpp @@ -590,7 +590,7 @@ bool SimonEngine::load_game(uint slot) { for (i = 0; i != 32; i++) _bit_array[i] = f->readUint16BE(); - if (f->readingFailed()) { + if (f->ioFailed()) { error("load failed"); } diff --git a/sound/softsynth/mt32.cpp b/sound/softsynth/mt32.cpp index 13502ed4df..75abaabbcc 100644 --- a/sound/softsynth/mt32.cpp +++ b/sound/softsynth/mt32.cpp @@ -90,7 +90,7 @@ public: return file.read(in, size); } bool readLine(char *in, size_t size) { - return file.gets(in, size) != NULL; + return file.readLine(in, size) != NULL; } bool readBit8u(MT32Emu::Bit8u *in) { byte b = file.readByte(); diff --git a/sword2/function.cpp b/sword2/function.cpp index 7e241ba094..a80ffa7f0b 100644 --- a/sword2/function.cpp +++ b/sword2/function.cpp @@ -3032,7 +3032,7 @@ int32 Logic::fnPlayCredits(int32 *params) { } char buffer[80]; - char *line = f.gets(buffer, sizeof(buffer)); + char *line = f.readLine(buffer, sizeof(buffer)); if (!line || *line == 0) { if (!hasCenterMark) { |