* 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
This commit is contained in:
parent
ca33ec4563
commit
969ef3dac9
12 changed files with 126 additions and 89 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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; }
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
};
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue