~ubuntu-branches/ubuntu/raring/scummvm/raring

« back to all changes in this revision

Viewing changes to common/stream.h

  • Committer: Bazaar Package Importer
  • Author(s): Moritz Muehlenhoff
  • Date: 2011-05-25 19:02:23 UTC
  • mto: (21.1.2 sid)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: james.westby@ubuntu.com-20110525190223-fiqm0oaec714xk31
Tags: upstream-1.3.0
ImportĀ upstreamĀ versionĀ 1.3.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 * along with this program; if not, write to the Free Software
19
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
20
 *
21
 
 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-1-2-1/common/stream.h $
22
 
 * $Id: stream.h 52724 2010-09-14 14:57:30Z Bluddy $
 
21
 * $URL$
 
22
 * $Id$
23
23
 *
24
24
 */
25
25
 
26
26
#ifndef COMMON_STREAM_H
27
27
#define COMMON_STREAM_H
28
28
 
29
 
#include "common/types.h"
30
29
#include "common/endian.h"
 
30
#include "common/scummsys.h"
 
31
#include "common/str.h"
31
32
 
32
33
namespace Common {
33
34
 
34
 
class String;
35
 
class MemoryReadStream;
 
35
class SeekableReadStream;
36
36
 
37
37
/**
38
38
 * Virtual base class for both ReadStream and WriteStream.
301
301
         * the end of the stream was reached. Which can be determined by
302
302
         * calling err() and eos().
303
303
         */
304
 
        MemoryReadStream *readStream(uint32 dataSize);
 
304
        SeekableReadStream *readStream(uint32 dataSize);
305
305
 
306
306
};
307
307
 
389
389
        virtual String readLine();
390
390
};
391
391
 
392
 
 
393
 
/**
394
 
 * SubReadStream provides access to a ReadStream restricted to the range
395
 
 * [currentPosition, currentPosition+end).
396
 
 *
397
 
 * Manipulating the parent stream directly /will/ mess up a substream.
398
 
 * Likewise, manipulating two substreams of a parent stream will cause them to
399
 
 * step on each others toes.
400
 
 */
401
 
class SubReadStream : virtual public ReadStream {
402
 
protected:
403
 
        ReadStream *_parentStream;
404
 
        DisposeAfterUse::Flag _disposeParentStream;
405
 
        uint32 _pos;
406
 
        uint32 _end;
407
 
        bool _eos;
408
 
public:
409
 
        SubReadStream(ReadStream *parentStream, uint32 end, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO)
410
 
                : _parentStream(parentStream),
411
 
                  _disposeParentStream(disposeParentStream),
412
 
                  _pos(0),
413
 
                  _end(end),
414
 
                  _eos(false) {
415
 
                assert(parentStream);
416
 
        }
417
 
        ~SubReadStream() {
418
 
                if (_disposeParentStream)
419
 
                        delete _parentStream;
420
 
        }
421
 
 
422
 
        virtual bool eos() const { return _eos; }
423
 
        virtual bool err() const { return _parentStream->err(); }
424
 
        virtual void clearErr() { _eos = false; _parentStream->clearErr(); }
425
 
        virtual uint32 read(void *dataPtr, uint32 dataSize);
426
 
};
427
 
 
428
 
/*
429
 
 * SeekableSubReadStream provides access to a SeekableReadStream restricted to
430
 
 * the range [begin, end).
431
 
 * The same caveats apply to SeekableSubReadStream as do to SeekableReadStream.
432
 
 *
433
 
 * Manipulating the parent stream directly /will/ mess up a substream.
434
 
 * @see SubReadStream
435
 
 */
436
 
class SeekableSubReadStream : public SubReadStream, public SeekableReadStream {
437
 
protected:
438
 
        SeekableReadStream *_parentStream;
439
 
        uint32 _begin;
440
 
public:
441
 
        SeekableSubReadStream(SeekableReadStream *parentStream, uint32 begin, uint32 end, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO);
442
 
 
443
 
        virtual int32 pos() const { return _pos - _begin; }
444
 
        virtual int32 size() const { return _end - _begin; }
445
 
 
446
 
        virtual bool seek(int32 offset, int whence = SEEK_SET);
447
 
};
448
 
 
449
 
/**
450
 
 * This is a wrapper around SeekableSubReadStream, but it adds non-endian
451
 
 * read methods whose endianness is set on the stream creation.
452
 
 *
453
 
 * Manipulating the parent stream directly /will/ mess up a substream.
454
 
 * @see SubReadStream
455
 
 */
456
 
class SeekableSubReadStreamEndian : public SeekableSubReadStream {
457
 
private:
458
 
        const bool _bigEndian;
459
 
 
460
 
public:
461
 
        SeekableSubReadStreamEndian(SeekableReadStream *parentStream, uint32 begin, uint32 end, bool bigEndian = false, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO)
462
 
                : SeekableSubReadStream(parentStream, begin, end, disposeParentStream), _bigEndian(bigEndian) {
463
 
        }
464
 
 
465
 
        uint16 readUint16() {
466
 
                uint16 val;
467
 
                read(&val, 2);
468
 
                return (_bigEndian) ? TO_BE_16(val) : TO_LE_16(val);
469
 
        }
470
 
 
471
 
        uint32 readUint32() {
472
 
                uint32 val;
473
 
                read(&val, 4);
474
 
                return (_bigEndian) ? TO_BE_32(val) : TO_LE_32(val);
475
 
        }
476
 
 
477
 
        FORCEINLINE int16 readSint16() {
478
 
                return (int16)readUint16();
479
 
        }
480
 
 
481
 
        FORCEINLINE int32 readSint32() {
482
 
                return (int32)readUint32();
483
 
        }
484
 
};
485
 
 
486
 
/**
487
 
 * Wrapper class which adds buffering to any given ReadStream.
488
 
 * Users can specify how big the buffer should be, and whether the
489
 
 * wrapped stream should be disposed when the wrapper is disposed.
490
 
 */
491
 
class BufferedReadStream : virtual public ReadStream {
492
 
protected:
493
 
        ReadStream *_parentStream;
494
 
        DisposeAfterUse::Flag _disposeParentStream;
495
 
        byte *_buf;
496
 
        uint32 _pos;
497
 
        bool _eos; // end of stream
498
 
        uint32 _bufSize;
499
 
        uint32 _realBufSize;
500
 
 
501
 
public:
502
 
        BufferedReadStream(ReadStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO);
503
 
        virtual ~BufferedReadStream();
504
 
 
505
 
        virtual bool eos() const { return _eos; }
506
 
        virtual bool err() const { return _parentStream->err(); }
507
 
        virtual void clearErr() { _eos = false; _parentStream->clearErr(); }
508
 
 
509
 
        virtual uint32 read(void *dataPtr, uint32 dataSize);
510
 
};
511
 
 
512
 
/**
513
 
 * Wrapper class which adds buffering to any given SeekableReadStream.
514
 
 * @see BufferedReadStream
515
 
 */
516
 
class BufferedSeekableReadStream : public BufferedReadStream, public SeekableReadStream {
517
 
protected:
518
 
        SeekableReadStream *_parentStream;
519
 
public:
520
 
        BufferedSeekableReadStream(SeekableReadStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO);
521
 
 
522
 
        virtual int32 pos() const { return _parentStream->pos() - (_bufSize - _pos); }
523
 
        virtual int32 size() const { return _parentStream->size(); }
524
 
 
525
 
        virtual bool seek(int32 offset, int whence = SEEK_SET);
526
 
};
527
 
 
528
 
/**
529
 
 * Wrapper class which adds buffering to any WriteStream.
530
 
 */
531
 
class BufferedWriteStream : public WriteStream {
532
 
protected:
533
 
        WriteStream *_parentStream;
534
 
        DisposeAfterUse::Flag _disposeParentStream;
535
 
        byte *_buf;
536
 
        uint32 _pos;
537
 
        uint32 _bufSize;
538
 
        bool flushBuffer();                                             // write out the data in the buffer
539
 
 
540
 
public:
541
 
        BufferedWriteStream(WriteStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO);
542
 
        virtual ~BufferedWriteStream();
543
 
        
544
 
        virtual uint32 write(const void *dataPtr, uint32 dataSize);
545
 
        virtual bool flush();
546
 
};
547
 
 
548
 
/**
549
 
 * Simple memory based 'stream', which implements the ReadStream interface for
550
 
 * a plain memory block.
551
 
 */
552
 
class MemoryReadStream : public SeekableReadStream {
553
 
private:
554
 
        const byte * const _ptrOrig;
555
 
        const byte *_ptr;
556
 
        const uint32 _size;
557
 
        uint32 _pos;
558
 
        byte _encbyte;
559
 
        DisposeAfterUse::Flag _disposeMemory;
560
 
        bool _eos;
561
 
 
562
 
public:
563
 
 
564
 
        /**
565
 
         * This constructor takes a pointer to a memory buffer and a length, and
566
 
         * wraps it. If disposeMemory is true, the MemoryReadStream takes ownership
567
 
         * of the buffer and hence free's it when destructed.
568
 
         */
569
 
        MemoryReadStream(const byte *dataPtr, uint32 dataSize, DisposeAfterUse::Flag disposeMemory = DisposeAfterUse::NO) :
570
 
                _ptrOrig(dataPtr),
571
 
                _ptr(dataPtr),
572
 
                _size(dataSize),
573
 
                _pos(0),
574
 
                _encbyte(0),
575
 
                _disposeMemory(disposeMemory),
576
 
                _eos(false) {}
577
 
 
578
 
        ~MemoryReadStream() {
579
 
                if (_disposeMemory)
580
 
                        free(const_cast<byte *>(_ptrOrig));
581
 
        }
582
 
 
583
 
        void setEnc(byte value) { _encbyte = value; }
584
 
 
585
 
        uint32 read(void *dataPtr, uint32 dataSize);
586
 
 
587
 
        bool eos() const { return _eos; }
588
 
        void clearErr() { _eos = false; }
589
 
 
590
 
        int32 pos() const { return _pos; }
591
 
        int32 size() const { return _size; }
592
 
 
593
 
        bool seek(int32 offs, int whence = SEEK_SET);
594
 
};
595
 
 
596
 
 
597
 
/**
598
 
 * This is a wrapper around MemoryReadStream, but it adds non-endian
599
 
 * read methods whose endianness is set on the stream creation.
600
 
 */
601
 
class MemoryReadStreamEndian : public Common::MemoryReadStream {
602
 
private:
603
 
        const bool _bigEndian;
604
 
 
605
 
public:
606
 
        MemoryReadStreamEndian(const byte *buf, uint32 len, bool bigEndian = false) : MemoryReadStream(buf, len), _bigEndian(bigEndian) {}
607
 
 
608
 
        uint16 readUint16() {
609
 
                uint16 val;
610
 
                read(&val, 2);
611
 
                return (_bigEndian) ? TO_BE_16(val) : TO_LE_16(val);
612
 
        }
613
 
 
614
 
        uint32 readUint32() {
615
 
                uint32 val;
616
 
                read(&val, 4);
617
 
                return (_bigEndian) ? TO_BE_32(val) : TO_LE_32(val);
618
 
        }
619
 
 
620
 
        FORCEINLINE int16 readSint16() {
621
 
                return (int16)readUint16();
622
 
        }
623
 
 
624
 
        FORCEINLINE int32 readSint32() {
625
 
                return (int32)readUint32();
626
 
        }
627
 
};
628
 
 
629
 
/**
630
 
 * Simple memory based 'stream', which implements the WriteStream interface for
631
 
 * a plain memory block.
632
 
 */
633
 
class MemoryWriteStream : public WriteStream {
634
 
private:
635
 
        byte *_ptr;
636
 
        const uint32 _bufSize;
637
 
        uint32 _pos;
638
 
public:
639
 
        MemoryWriteStream(byte *buf, uint32 len) : _ptr(buf), _bufSize(len), _pos(0) {}
640
 
 
641
 
        uint32 write(const void *dataPtr, uint32 dataSize) {
642
 
                // Write at most as many bytes as are still available...
643
 
                if (dataSize > _bufSize - _pos)
644
 
                        dataSize = _bufSize - _pos;
645
 
                memcpy(_ptr, dataPtr, dataSize);
646
 
                _ptr += dataSize;
647
 
                _pos += dataSize;
648
 
                return dataSize;
649
 
        }
650
 
 
651
 
        uint32 pos() const { return _pos; }
652
 
        uint32 size() const { return _bufSize; }
653
 
};
654
 
 
655
 
/**
656
 
 * A sort of hybrid between MemoryWriteStream and Array classes. A stream
657
 
 * that grows as it's written to.
658
 
 */
659
 
class MemoryWriteStreamDynamic : public Common::WriteStream {
660
 
private:
661
 
        uint32 _capacity;
662
 
        uint32 _size;
663
 
        byte *_ptr;
664
 
        byte *_data;
665
 
        uint32 _pos;
666
 
        DisposeAfterUse::Flag _disposeMemory;
667
 
 
668
 
        void ensureCapacity(uint32 new_len) {
669
 
                if (new_len <= _capacity)
670
 
                        return;
671
 
 
672
 
                byte *old_data = _data;
673
 
 
674
 
                _capacity = new_len + 32;
675
 
                _data = (byte *)malloc(_capacity);
676
 
                _ptr = _data + _pos;
677
 
 
678
 
                if (old_data) {
679
 
                        // Copy old data
680
 
                        memcpy(_data, old_data, _size);
681
 
                        free(old_data);
682
 
                }
683
 
 
684
 
                _size = new_len;
685
 
        }
686
 
public:
687
 
        MemoryWriteStreamDynamic(DisposeAfterUse::Flag disposeMemory = DisposeAfterUse::NO) : _capacity(0), _size(0), _ptr(0), _data(0), _pos(0), _disposeMemory(disposeMemory) {}
688
 
 
689
 
        ~MemoryWriteStreamDynamic() {
690
 
                if (_disposeMemory)
691
 
                        free(_data);
692
 
        }
693
 
 
694
 
        uint32 write(const void *dataPtr, uint32 dataSize) {
695
 
                ensureCapacity(_pos + dataSize);
696
 
                memcpy(_ptr, dataPtr, dataSize);
697
 
                _ptr += dataSize;
698
 
                _pos += dataSize;
699
 
                if (_pos > _size)
700
 
                        _size = _pos;
701
 
                return dataSize;
702
 
        }
703
 
 
704
 
        uint32 pos() const { return _pos; }
705
 
        uint32 size() const { return _size; }
706
 
 
707
 
        byte *getData() { return _data; }
708
 
 
709
 
        bool seek(int32 offset, int whence = SEEK_SET);
710
 
};
 
392
/**
 
393
 * This is a ReadStream mixin subclass which adds non-endian read
 
394
 * methods whose endianness is set during the stream creation.
 
395
 */
 
396
class ReadStreamEndian : virtual public ReadStream {
 
397
private:
 
398
        const bool _bigEndian;
 
399
 
 
400
public:
 
401
        ReadStreamEndian(bool bigEndian) : _bigEndian(bigEndian) {}
 
402
 
 
403
        bool isBE() const { return _bigEndian; }
 
404
 
 
405
        uint16 readUint16() {
 
406
                uint16 val;
 
407
                read(&val, 2);
 
408
                return (_bigEndian) ? TO_BE_16(val) : TO_LE_16(val);
 
409
        }
 
410
 
 
411
        uint32 readUint32() {
 
412
                uint32 val;
 
413
                read(&val, 4);
 
414
                return (_bigEndian) ? TO_BE_32(val) : TO_LE_32(val);
 
415
        }
 
416
 
 
417
        FORCEINLINE int16 readSint16() {
 
418
                return (int16)readUint16();
 
419
        }
 
420
 
 
421
        FORCEINLINE int32 readSint32() {
 
422
                return (int32)readUint32();
 
423
        }
 
424
};
 
425
 
 
426
/**
 
427
 * This is a SeekableReadStream subclass which adds non-endian read
 
428
 * methods whose endianness is set during the stream creation.
 
429
 */
 
430
class SeekableReadStreamEndian : public SeekableReadStream, public ReadStreamEndian {
 
431
public:
 
432
        SeekableReadStreamEndian(bool bigEndian) : ReadStreamEndian(bigEndian) {}
 
433
};
 
434
 
711
435
 
712
436
}       // End of namespace Common
713
437