123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- using System;
- using System.IO;
- using SharpCompress.Converters;
- namespace SharpCompress.IO
- {
- internal class MarkingBinaryReader : BinaryReader
- {
- public MarkingBinaryReader(Stream stream)
- : base(stream)
- {
- }
- public virtual long CurrentReadByteCount { get; protected set; }
- public virtual void Mark()
- {
- CurrentReadByteCount = 0;
- }
- public override int Read()
- {
- throw new NotSupportedException();
- }
- public override int Read(byte[] buffer, int index, int count)
- {
- throw new NotSupportedException();
- }
- public override int Read(char[] buffer, int index, int count)
- {
- throw new NotSupportedException();
- }
- public override bool ReadBoolean()
- {
- return ReadByte() != 0;
- }
- // NOTE: there is a somewhat fragile dependency on the internals of this class
- // with RarCrcBinaryReader and RarCryptoBinaryReader.
- //
- // RarCrcBinaryReader/RarCryptoBinaryReader need to override any specific methods
- // that call directly to the base BinaryReader and do not delegate to other methods
- // in this class so that it can track the each byte being read.
- //
- // if altering this class in a way that changes the implementation be sure to
- // update RarCrcBinaryReader/RarCryptoBinaryReader.
- public override byte ReadByte()
- {
- CurrentReadByteCount++;
- return base.ReadByte();
- }
- public override byte[] ReadBytes(int count)
- {
- CurrentReadByteCount += count;
- var bytes = base.ReadBytes(count);
- if (bytes.Length != count)
- {
- throw new EndOfStreamException(string.Format("Could not read the requested amount of bytes. End of stream reached. Requested: {0} Read: {1}", count, bytes.Length));
- }
- return bytes;
- }
- public override char ReadChar()
- {
- throw new NotSupportedException();
- }
- public override char[] ReadChars(int count)
- {
- throw new NotSupportedException();
- }
- #if !SILVERLIGHT
- public override decimal ReadDecimal()
- {
- throw new NotSupportedException();
- }
- #endif
- public override double ReadDouble()
- {
- throw new NotSupportedException();
- }
- public override short ReadInt16()
- {
- return DataConverter.LittleEndian.GetInt16(ReadBytes(2), 0);
- }
- public override int ReadInt32()
- {
- return DataConverter.LittleEndian.GetInt32(ReadBytes(4), 0);
- }
- public override long ReadInt64()
- {
- return DataConverter.LittleEndian.GetInt64(ReadBytes(8), 0);
- }
- public override sbyte ReadSByte()
- {
- return (sbyte)ReadByte();
- }
- public override float ReadSingle()
- {
- throw new NotSupportedException();
- }
- public override string ReadString()
- {
- throw new NotSupportedException();
- }
- public override ushort ReadUInt16()
- {
- return DataConverter.LittleEndian.GetUInt16(ReadBytes(2), 0);
- }
- public override uint ReadUInt32()
- {
- return DataConverter.LittleEndian.GetUInt32(ReadBytes(4), 0);
- }
- public override ulong ReadUInt64()
- {
- return DataConverter.LittleEndian.GetUInt64(ReadBytes(8), 0);
- }
- // RAR5 style variable length encoded value
- // maximum value of 0xffffffffffffffff (64 bits)
- // technote: "implies max 10 bytes consumed" -- but not really because we could extend indefinitely using 0x80 0x80 ... 0x80 00
- //
- // Variable length integer. Can include one or more bytes, where lower 7 bits of every byte contain integer data
- // and highest bit in every byte is the continuation flag. If highest bit is 0, this is the last byte in sequence.
- // So first byte contains 7 least significant bits of integer and continuation flag. Second byte, if present,
- // contains next 7 bits and so on.
- public ulong ReadRarVInt(int maxBytes = 10) {
- // hopefully this gets inlined
- return DoReadRarVInt((maxBytes - 1) * 7);
- }
- private ulong DoReadRarVInt(int maxShift) {
- int shift = 0;
- ulong result = 0;
- do {
- byte b0 = ReadByte();
- uint b1 = ((uint)b0) & 0x7f;
- ulong n = b1;
- ulong shifted = n << shift;
- if (n != shifted >> shift) {
- // overflow
- break;
- }
- result |= shifted;
- if (b0 == b1) {
- return result;
- }
- shift += 7;
- } while (shift <= maxShift);
- throw new FormatException("malformed vint");
- }
- public uint ReadRarVIntUInt32(int maxBytes = 5) {
- // hopefully this gets inlined
- return DoReadRarVIntUInt32((maxBytes - 1) * 7);
- }
- public ushort ReadRarVIntUInt16(int maxBytes = 3) {
- // hopefully this gets inlined
- return checked((ushort)DoReadRarVIntUInt32((maxBytes - 1) * 7));
- }
- public byte ReadRarVIntByte(int maxBytes = 2) {
- // hopefully this gets inlined
- return checked((byte)DoReadRarVIntUInt32((maxBytes - 1) * 7));
- }
- private uint DoReadRarVIntUInt32(int maxShift) {
- int shift = 0;
- uint result = 0;
- do {
- byte b0 = ReadByte();
- uint b1 = ((uint)b0) & 0x7f;
- uint n = b1;
- uint shifted = n << shift;
- if (n != shifted >> shift) {
- // overflow
- break;
- }
- result |= shifted;
- if (b0 == b1) {
- return result;
- }
- shift += 7;
- } while (shift <= maxShift);
- throw new FormatException("malformed vint");
- }
- }
- }
|