aboutsummaryrefslogtreecommitdiff
path: root/common/stream.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/stream.cpp')
-rw-r--r--common/stream.cpp134
1 files changed, 134 insertions, 0 deletions
diff --git a/common/stream.cpp b/common/stream.cpp
index ab9804d7b6..e06cc28415 100644
--- a/common/stream.cpp
+++ b/common/stream.cpp
@@ -148,6 +148,61 @@ char *SeekableReadStream::readLine(char *buf, size_t bufSize) {
return buf;
}
+char *SeekableReadStream::readLine_NEW(char *buf, size_t bufSize) {
+ assert(buf != 0 && bufSize > 1);
+ char *p = buf;
+ size_t len = 0;
+ char c = 0;
+
+ // If end-of-file occurs before any characters are read, return NULL
+ // and the buffer contents remain unchanged.
+ if (eos() || ioFailed()) {
+ 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) {
+ c = readByte();
+
+ // If end-of-file occurs before any characters are read, return
+ // NULL and the buffer contents remain unchanged. If an error
+ /// occurs, return NULL and the buffer contents are indeterminate.
+ if (ioFailed() || (len == 0 && eos()))
+ return 0;
+
+ // Check for CR or CR/LF
+ // * DOS and Windows use CRLF line breaks
+ // * Unix and OS X use LF line breaks
+ // * Macintosh before OS X used CR line breaks
+ if (c == CR) {
+ // Look at the next char -- is it LF? If not, seek back
+ c = readByte();
+ if (c != LF && !eos())
+ seek(-1, SEEK_CUR);
+ // Treat CR & CR/LF as plain LF
+ c = LF;
+ }
+
+ *p++ = c;
+ 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;
+}
+
+
uint32 SubReadStream::read(void *dataPtr, uint32 dataSize) {
dataSize = MIN(dataSize, _end - _pos);
@@ -187,4 +242,83 @@ void SeekableSubReadStream::seek(int32 offset, int whence) {
_parentStream->seek(_pos);
}
+BufferedReadStream::BufferedReadStream(ReadStream *parentStream, uint32 bufSize, bool disposeParentStream)
+ : _parentStream(parentStream),
+ _disposeParentStream(disposeParentStream),
+ _pos(0),
+ _bufSize(0),
+ _realBufSize(bufSize) {
+
+ assert(parentStream);
+ _buf = new byte[bufSize];
+ assert(_buf);
+}
+
+BufferedReadStream::~BufferedReadStream() {
+ if (_disposeParentStream)
+ delete _parentStream;
+ delete _buf;
+}
+
+uint32 BufferedReadStream::read(void *dataPtr, uint32 dataSize) {
+ uint32 alreadyRead = 0;
+ const uint32 bufBytesLeft = _bufSize - _pos;
+
+ // Check whether the data left in the buffer suffices....
+ if (dataSize > bufBytesLeft) {
+ // Nope, we need to read more data
+
+ // First, flush the buffer, if it is non-empty
+ if (0 < bufBytesLeft) {
+ memcpy(dataPtr, _buf + _pos, bufBytesLeft);
+ _pos = _bufSize;
+ alreadyRead += bufBytesLeft;
+ dataPtr = (byte *)dataPtr + bufBytesLeft;
+ dataSize -= bufBytesLeft;
+ }
+
+ // At this point the buffer is empty. Now if the read request
+ // exceeds the buffer size, just satisfy it directly.
+ if (dataSize > _bufSize)
+ return alreadyRead + _parentStream->read(dataPtr, dataSize);
+
+ // Refill the buffer.
+ // If we didn't read as many bytes as requested, the reason
+ // is EOF or an error. In that case we truncate the buffer
+ // size, as well as the number of bytes we are going to
+ // return to the caller.
+ _bufSize = _parentStream->read(_buf, _realBufSize);
+ _pos = 0;
+ if (dataSize > _bufSize)
+ dataSize = _bufSize;
+ }
+
+ // Satisfy the request from the buffer
+ memcpy(dataPtr, _buf + _pos, dataSize);
+ _pos += dataSize;
+ return alreadyRead + dataSize;
+}
+
+BufferedSeekableReadStream::BufferedSeekableReadStream(SeekableReadStream *parentStream, uint32 bufSize, bool disposeParentStream)
+ : BufferedReadStream(parentStream, bufSize, disposeParentStream),
+ _parentStream(parentStream) {
+}
+
+void BufferedSeekableReadStream::seek(int32 offset, int whence) {
+ // If it is a "local" seek, we may get away with "seeking" around
+ // in the buffer only.
+ // Note: We could try to handle SEEK_END and SEEK_SET, too, but
+ // since they are rarely used, it seems not worth the effort.
+ if (whence == SEEK_CUR && (int)_pos + offset >= 0 && _pos + offset <= _bufSize) {
+ _pos += offset;
+ } else {
+ // Seek was not local enough, so we reset the buffer and
+ // just seeks normally in the parent stream.
+ if (whence == SEEK_CUR)
+ offset -= (_bufSize - _pos);
+ _pos = _bufSize;
+ _parentStream->seek(offset, whence);
+ }
+}
+
} // End of namespace Common