/* Copyright (C) 2014-2019 de4dot@gmail.com This file is part of dnSpy dnSpy is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. dnSpy 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 General Public License for more details. You should have received a copy of the GNU General Public License along with dnSpy. If not, see . */ using System; namespace dnSpy.Contracts.Hex { /// /// A stream used by a /// public abstract class HexBufferStream : IDisposable { /// /// Constructor /// protected HexBufferStream() { } /// /// true if the content can change at any time /// public abstract bool IsVolatile { get; } /// /// true if it's a read-only stream /// public abstract bool IsReadOnly { get; } /// /// Gets the span /// public abstract HexSpan Span { get; } /// /// Gets the name. This could be the filename if the data was read from a file /// public abstract string Name { get; } /// /// Raised when a span of data got modified by other code /// public abstract event EventHandler? BufferStreamSpanInvalidated; /// /// Clears the cache if it uses a cache /// public virtual void ClearCache() { } /// /// Gets information about a position in the stream /// /// Position /// public abstract HexSpanInfo GetSpanInfo(HexPosition position); /// /// Gets information about a position in the stream /// /// Position /// Span of all valid data /// protected HexSpanInfo GetSpanInfo(HexPosition position, HexSpan validSpan) { if (position >= HexPosition.MaxEndPosition) throw new ArgumentOutOfRangeException(nameof(position)); if (position >= validSpan.End) return new HexSpanInfo(HexSpan.FromBounds(validSpan.End, HexPosition.MaxEndPosition), HexSpanInfoFlags.None); else if (position < validSpan.Start) return new HexSpanInfo(HexSpan.FromBounds(HexPosition.Zero, validSpan.Start), HexSpanInfoFlags.None); else return new HexSpanInfo(validSpan, HexSpanInfoFlags.HasData); } /// /// Tries to read a . If there's no data, a value less than 0 is returned. /// /// Position /// public abstract int TryReadByte(HexPosition position); /// /// Reads a /// /// Position /// public abstract byte ReadByte(HexPosition position); /// /// Reads a /// /// Position /// public abstract sbyte ReadSByte(HexPosition position); /// /// Reads a /// /// Position /// public abstract short ReadInt16(HexPosition position); /// /// Reads a /// /// Position /// public abstract ushort ReadUInt16(HexPosition position); /// /// Reads a /// /// Position /// public abstract int ReadInt32(HexPosition position); /// /// Reads a /// /// Position /// public abstract uint ReadUInt32(HexPosition position); /// /// Reads a /// /// Position /// public abstract long ReadInt64(HexPosition position); /// /// Reads a /// /// Position /// public abstract ulong ReadUInt64(HexPosition position); /// /// Reads a /// /// Position /// public abstract float ReadSingle(HexPosition position); /// /// Reads a /// /// Position /// public abstract double ReadDouble(HexPosition position); /// /// Reads a /// /// Position /// public abstract short ReadInt16BigEndian(HexPosition position); /// /// Reads a /// /// Position /// public abstract ushort ReadUInt16BigEndian(HexPosition position); /// /// Reads a /// /// Position /// public abstract int ReadInt32BigEndian(HexPosition position); /// /// Reads a /// /// Position /// public abstract uint ReadUInt32BigEndian(HexPosition position); /// /// Reads a /// /// Position /// public abstract long ReadInt64BigEndian(HexPosition position); /// /// Reads a /// /// Position /// public abstract ulong ReadUInt64BigEndian(HexPosition position); /// /// Reads a /// /// Position /// public abstract float ReadSingleBigEndian(HexPosition position); /// /// Reads a /// /// Position /// public abstract double ReadDoubleBigEndian(HexPosition position); /// /// Reads bytes /// /// Position /// Number of bytes to read /// public abstract byte[] ReadBytes(HexPosition position, long length); /// /// Reads bytes /// /// Position /// Destination array /// Index /// Length public abstract void ReadBytes(HexPosition position, byte[] destination, long destinationIndex, long length); /// /// Reads bytes /// /// Position /// Length /// public abstract HexBytes ReadHexBytes(HexPosition position, long length); /// /// Writes bytes /// /// Position /// Data public void Write(HexPosition position, byte[] source) { if (source is null) throw new ArgumentNullException(nameof(source)); Write(position, source, 0, source.LongLength); } /// /// Writes bytes /// /// Position /// Data /// Index /// Length public abstract void Write(HexPosition position, byte[] source, long sourceIndex, long length); /// /// Raised after it is disposed /// public event EventHandler? Disposed; /// /// true if the instance has been disposed /// public bool IsDisposed { get; private set; } /// /// Disposes this instance /// public void Dispose() { if (IsDisposed) return; IsDisposed = true; DisposeCore(); Disposed?.Invoke(this, EventArgs.Empty); } /// /// Disposes this instance /// protected virtual void DisposeCore() { } } /// /// Invalidated span event args /// public sealed class HexBufferStreamSpanInvalidatedEventArgs : EventArgs { /// /// Gets the span /// public HexSpan Span { get; } /// /// Constructor /// /// Span public HexBufferStreamSpanInvalidatedEventArgs(HexSpan span) => Span = span; } }