Ticket #8581: substreams.diff
File substreams.diff, 6.0 KB (added by , 18 years ago) |
---|
-
common/stream.h
210 210 * @todo We really need better error handling here! 211 211 * Like seek should somehow indicate whether it failed. 212 212 */ 213 class SeekableReadStream : public ReadStream {213 class SeekableReadStream : virtual public ReadStream { 214 214 public: 215 215 216 216 virtual uint32 pos() const = 0; 217 217 virtual uint32 size() const = 0; 218 218 219 219 virtual void seek(int32 offset, int whence = SEEK_SET) = 0; 220 220 221 221 void skip(uint32 offset) { seek(offset, SEEK_CUR); } 222 222 223 223 /** … … 233 233 virtual char *readLine(char *buf, size_t bufSize); 234 234 }; 235 235 236 /** 237 * SubReadStream provides access to a ReadStream restricted to the range 238 * [currentPosition, currentPosition+end). 239 * Manipulating the parent stream directly /will/ mess up a substream. 240 * Likewise, manipulating two substreams of a parent stream will cause them to 241 * step on each others toes. 242 */ 243 class SubReadStream : virtual public ReadStream { 244 protected: 245 ReadStream *_parentStream; 246 uint32 _pos; 247 uint32 _end; 248 public: 249 SubReadStream(ReadStream *parentStream, uint32 end) 250 : _parentStream(parentStream), _pos(0), _end(end) {} 236 251 252 virtual bool eos() const { return _pos == _end; } 253 virtual uint32 read(void *dataPtr, uint32 dataSize); 254 }; 255 256 /* 257 * SeekableSubReadStream provides access to a SeekableReadStream restricted to 258 * the range [begin, end). 259 * The same caveats apply to SeekableSubReadStream as do to SeekableReadStream. 260 */ 261 class SeekableSubReadStream : public SubReadStream, public SeekableReadStream { 262 protected: 263 SeekableReadStream *_parentStream; 264 uint32 _begin; 265 public: 266 SeekableSubReadStream(SeekableReadStream *parentStream, uint32 begin, uint32 end); 267 268 virtual uint32 pos() const { return _pos - _begin; } 269 virtual uint32 size() const { return _end - _begin; } 270 271 virtual void seek(int32 offset, int whence = SEEK_SET); 272 }; 273 237 274 /** 238 275 * XORReadStream is a wrapper around an arbitrary other ReadStream, 239 276 * which 'decrypts' the data being read by XORing all data bytes with the given -
common/stream.cpp
105 105 106 106 c = readByte(); 107 107 } 108 108 109 109 // This should fix a bug while using readLine with Common::File 110 110 // it seems that it sets the eos flag after an invalid read 111 111 // and at the same time the ioFailed flag … … 118 118 return buf; 119 119 } 120 120 121 uint32 SubReadStream::read(void *dataPtr, uint32 dataSize) 122 { 123 dataSize = MIN(dataSize, _end - _pos); 121 124 125 dataSize = _parentStream->read(dataPtr, dataSize); 126 _pos += dataSize; 127 128 return dataSize; 129 } 130 131 SeekableSubReadStream::SeekableSubReadStream(SeekableReadStream *parentStream, uint32 begin, uint32 end) 132 : SubReadStream(parentStream, end), _parentStream(parentStream), _begin(begin) 133 { 134 assert(_begin <= _end); 135 _pos = _begin; 136 _parentStream->seek(_pos); 137 } 138 139 void SeekableSubReadStream::seek(int32 offset, int whence) 140 { 141 assert(_pos >= _begin); 142 assert(_pos <= _end); 143 144 switch(whence) 145 { 146 case SEEK_END: 147 offset = size() - offset; 148 // fallthrough 149 case SEEK_SET: 150 _pos = _begin + offset; 151 break; 152 case SEEK_CUR: 153 _pos += offset; 154 } 155 156 assert(_pos >= _begin); 157 assert(_pos <= _end); 158 159 _parentStream->seek(_pos); 160 } 161 122 162 } // End of namespace Common -
test/common/seekablesubreadstream.h
1 #include <cxxtest/TestSuite.h> 2 3 #include "common/stdafx.h" 4 #include "common/stream.h" 5 6 class SeekableSubReadStreamTestSuite : public CxxTest::TestSuite 7 { 8 public: 9 void test_traverse( void ) 10 { 11 byte contents[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 12 Common::MemoryReadStream ms = Common::MemoryReadStream(contents, 10); 13 14 int start = 2, end = 8; 15 16 Common::SeekableSubReadStream ssrs = Common::SeekableSubReadStream(&ms, start, end); 17 18 int i; 19 byte b; 20 for (i = start; i < end; ++i) 21 { 22 TS_ASSERT( !ssrs.eos() ); 23 24 TS_ASSERT_EQUALS( i - start, ssrs.pos() ); 25 26 ssrs.read(&b, 1); 27 TS_ASSERT_EQUALS( i, b ); 28 } 29 30 TS_ASSERT( ssrs.eos() ); 31 } 32 33 void test_seek( void ) 34 { 35 byte contents[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 36 Common::MemoryReadStream ms = Common::MemoryReadStream(contents, 10); 37 38 Common::SeekableSubReadStream ssrs = Common::SeekableSubReadStream(&ms, 1, 9); 39 byte b; 40 41 TS_ASSERT_EQUALS( ssrs.pos(), 0 ); 42 43 ssrs.seek(1, SEEK_SET); 44 TS_ASSERT_EQUALS( ssrs.pos(), 1 ); 45 b = ssrs.readByte(); 46 TS_ASSERT_EQUALS( b, 2 ); 47 48 ssrs.seek(5, SEEK_CUR); 49 TS_ASSERT_EQUALS( ssrs.pos(), 7 ); 50 b = ssrs.readByte(); 51 TS_ASSERT_EQUALS( b, 8 ); 52 53 ssrs.seek(-3, SEEK_CUR); 54 TS_ASSERT_EQUALS( ssrs.pos(), 5 ); 55 b = ssrs.readByte(); 56 TS_ASSERT_EQUALS( b, 6 ); 57 58 ssrs.seek(0, SEEK_END); 59 TS_ASSERT_EQUALS( ssrs.pos(), 8 ); 60 TS_ASSERT( ssrs.eos() ); 61 62 ssrs.seek(3, SEEK_END); 63 TS_ASSERT_EQUALS( ssrs.pos(), 5 ); 64 b = ssrs.readByte(); 65 TS_ASSERT_EQUALS( b, 6 ); 66 67 ssrs.seek(8, SEEK_END); 68 TS_ASSERT_EQUALS( ssrs.pos(), 0 ); 69 b = ssrs.readByte(); 70 TS_ASSERT_EQUALS( b, 1 ); 71 } 72 }; -
test/common/subreadstream.h
1 #include <cxxtest/TestSuite.h> 2 3 #include "common/stdafx.h" 4 #include "common/stream.h" 5 6 class SubReadStreamTestSuite : public CxxTest::TestSuite 7 { 8 public: 9 void test_traverse( void ) 10 { 11 byte contents[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 12 Common::MemoryReadStream ms = Common::MemoryReadStream(contents, 10); 13 14 int end = 5; 15 16 Common::SubReadStream srs = Common::SubReadStream(&ms, end); 17 18 int i; 19 byte b; 20 for (i = 0; i < end; ++i) 21 { 22 TS_ASSERT( !srs.eos() ); 23 24 srs.read(&b, 1); 25 TS_ASSERT_EQUALS( i, b ); 26 } 27 28 TS_ASSERT( srs.eos() ); 29 } 30 };