#region Disclaimer / License // Copyright (C) 2010, Jackie Ng // http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie@gmail.com // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // #endregion using System; using System.Collections.Generic; using System.Text; using System.IO; using OSGeo.MapGuide; namespace OSGeo.MapGuide.Viewer { /// /// A read-only, rewindable stream /// public abstract class ReadOnlyRewindableStream : Stream { /// /// Resets the internal position of the stream /// public abstract void Rewind(); /// /// Gets whether this stream supports reading /// public override bool CanRead { get { return true; } } /// /// Gets whether this stream supports seeking /// public override bool CanSeek { get { return false; } } /// /// Gets whether this stream supports writing /// public override bool CanWrite { get { return false; } } /// /// Gets whether this stream is rewindable. If not, calls to throw a /// /// public abstract bool CanRewind { get; } /// /// Gets or sets the position (not implemented) /// public override long Position { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } /// /// Seeks to the specified offset in the stream (not implemented) /// /// /// /// public override long Seek(long offset, SeekOrigin origin) { throw new NotImplementedException(); } /// /// Sets the length of the stream (not implemented) /// /// public override void SetLength(long value) { throw new NotImplementedException(); } /// /// Writes the specified buffer into the stream (not implemented) /// /// /// /// public override void Write(byte[] buffer, int offset, int count) { throw new NotImplementedException(); } } /// /// Represents a method that returns a instance /// /// public delegate MgByteReader GetByteReaderMethod(); /// /// A read-only adapter for the /// class. /// public class MgReadOnlyStream : ReadOnlyRewindableStream { private MgByteReader _reader; /// /// Creates a new instance /// /// public MgReadOnlyStream(GetByteReaderMethod method) { _reader = method(); } /// /// Initializes a new instance of the class. /// /// The reader. public MgReadOnlyStream(MgByteReader reader) { _reader = reader; } /// /// Releases unmanaged resources and performs other cleanup operations before the /// is reclaimed by garbage collection. /// ~MgReadOnlyStream() { Dispose(false); } /// /// Releases the unmanaged resources used by the and optionally releases the managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected override void Dispose(bool disposing) { if (disposing) { _reader.Dispose(); } base.Dispose(disposing); } /// /// When overridden in a derived class, clears all buffers for this stream and causes any buffered data to be written to the underlying device. /// /// /// An I/O error occurs. /// public override void Flush() { } /// /// When overridden in a derived class, gets the length in bytes of the stream. /// /// /// A long value representing the length of the stream in bytes. /// /// /// /// A class derived from Stream does not support seeking. /// /// /// /// Methods were called after the stream was closed. /// public override long Length { //NOTE: MgByteReader only returns remaining length! Should we //be keeping track of position and adding on this value? get { return _reader.GetLength(); } } /// /// Gets whether this stream is rewindable. If not, calls to throw a /// /// public override bool CanRewind { get { return _reader.IsRewindable(); } } /// /// Resets the internal position of the stream /// public override void Rewind() { if (!CanRewind) throw new InvalidOperationException(Strings.ErrorStreamNotRewindable); _reader.Rewind(); } /// /// When overridden in a derived class, reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read. /// /// An array of bytes. When this method returns, the buffer contains the specified byte array with the values between and ( + - 1) replaced by the bytes read from the current source. /// The zero-based byte offset in at which to begin storing the data read from the current stream. /// The maximum number of bytes to be read from the current stream. /// /// The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached. /// /// /// The sum of and is larger than the buffer length. /// /// /// /// is null. /// /// /// /// or is negative. /// /// /// /// An I/O error occurs. /// /// /// /// The stream does not support reading. /// /// /// /// Methods were called after the stream was closed. /// public override int Read(byte[] buffer, int offset, int count) { int read = 0; //For good times, please always have the offset as 0 if (offset == 0) { read = _reader.Read(buffer, count); } else //So you want to play the hard way eh? Bad performance for you! { byte[] b = new byte[count]; read = _reader.Read(b, count); Array.Copy(b, 0, buffer, offset, read); } return read; } } }