1 /* ScummVM - Graphic Adventure Engine 2 * 3 * ScummVM is the legal property of its developers, whose names 4 * are too numerous to list here. Please refer to the COPYRIGHT 5 * file distributed with this source distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 */ 22 23 #ifndef COMMON_SUBSTREAM_H 24 #define COMMON_SUBSTREAM_H 25 26 #include "common/ptr.h" 27 #include "common/stream.h" 28 #include "common/types.h" 29 30 namespace Common { 31 32 /** 33 * @defgroup common_substream Substreams 34 * @ingroup common_stream 35 * 36 * @brief API for managing readable data substreams. 37 * 38 * @{ 39 */ 40 41 /** 42 * SubReadStream provides access to a ReadStream restricted to the range 43 * [currentPosition, currentPosition+end). 44 * 45 * Manipulating the parent stream directly /will/ mess up a substream. 46 * Likewise, manipulating two substreams of a parent stream will cause them to 47 * step on each others toes. 48 */ 49 class SubReadStream : virtual public ReadStream { 50 protected: 51 DisposablePtr<ReadStream> _parentStream; 52 uint32 _pos; 53 uint32 _end; 54 bool _eos; 55 public: 56 SubReadStream(ReadStream *parentStream, uint32 end, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO) _parentStream(parentStream,disposeParentStream)57 : _parentStream(parentStream, disposeParentStream), 58 _pos(0), 59 _end(end), 60 _eos(false) { 61 assert(parentStream); 62 } 63 eos()64 virtual bool eos() const { return _eos | _parentStream->eos(); } err()65 virtual bool err() const { return _parentStream->err(); } clearErr()66 virtual void clearErr() { _eos = false; _parentStream->clearErr(); } 67 virtual uint32 read(void *dataPtr, uint32 dataSize); 68 }; 69 70 /* 71 * SeekableSubReadStream provides access to a SeekableReadStream restricted to 72 * the range [begin, end). 73 * The same caveats apply to SeekableSubReadStream as do to SeekableReadStream. 74 * 75 * Manipulating the parent stream directly /will/ mess up a substream. 76 * @see SubReadStream 77 */ 78 class SeekableSubReadStream : public SubReadStream, virtual public SeekableReadStream { 79 protected: 80 SeekableReadStream *_parentStream; 81 uint32 _begin; 82 public: 83 SeekableSubReadStream(SeekableReadStream *parentStream, uint32 begin, uint32 end, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO); 84 pos()85 virtual int64 pos() const { return _pos - _begin; } size()86 virtual int64 size() const { return _end - _begin; } 87 88 virtual bool seek(int64 offset, int whence = SEEK_SET); 89 }; 90 91 /** 92 * This is a SeekableSubReadStream subclass which adds non-endian 93 * read methods whose endianness is set on the stream creation. 94 * 95 * Manipulating the parent stream directly /will/ mess up a substream. 96 * @see SubReadStream 97 */ 98 class SeekableSubReadStreamEndian : virtual public SeekableSubReadStream, virtual public SeekableReadStreamEndian { 99 public: 100 SeekableSubReadStreamEndian(SeekableReadStream *parentStream, uint32 begin, uint32 end, bool bigEndian, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO) SeekableSubReadStream(parentStream,begin,end,disposeParentStream)101 : SeekableSubReadStream(parentStream, begin, end, disposeParentStream), 102 SeekableReadStreamEndian(bigEndian), 103 ReadStreamEndian(bigEndian) { 104 } 105 pos()106 virtual int64 pos() const override { return SeekableSubReadStream::pos(); } size()107 virtual int64 size() const override { return SeekableSubReadStream::size(); } 108 109 virtual bool seek(int64 offset, int whence = SEEK_SET) override { return SeekableSubReadStream::seek(offset, whence); } 110 void hexdump(int len, int bytesPerLine = 16, int startOffset = 0) { SeekableSubReadStream::hexdump(len, bytesPerLine, startOffset); } skip(uint32 offset)111 bool skip(uint32 offset) override { return SeekableSubReadStream::seek(offset, SEEK_CUR); } 112 }; 113 114 /** 115 * A seekable substream that removes the exclusivity demand required by the 116 * normal SeekableSubReadStream, at the cost of seek()ing the parent stream 117 * before each read(). 118 * 119 * More than one SafeSeekableSubReadStream to the same parent stream can be used 120 * at the same time; they won't mess up each other. They will, however, 121 * reposition the parent stream, so don't depend on its position to be 122 * the same after a read() or seek() on one of its SafeSeekableSubReadStream. 123 * 124 * Note that this stream is *not* threading safe. Calling read from the audio 125 * thread and from the main thread might mess up the data retrieved. 126 */ 127 class SafeSeekableSubReadStream : public SeekableSubReadStream { 128 public: 129 SafeSeekableSubReadStream(SeekableReadStream *parentStream, uint32 begin, uint32 end, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO) SeekableSubReadStream(parentStream,begin,end,disposeParentStream)130 : SeekableSubReadStream(parentStream, begin, end, disposeParentStream) { 131 } 132 133 virtual uint32 read(void *dataPtr, uint32 dataSize); 134 }; 135 136 /** @} */ 137 138 } // End of namespace Common 139 140 #endif 141