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