public static void EnsureNoEOF(this OrigDecoderErrorCode errorCode) { if (errorCode == OrigDecoderErrorCode.UnexpectedEndOfStream) { errorCode.ThrowExceptionForErrorCode(); } }
public byte ReadByte(Stream inputStream) { OrigDecoderErrorCode errorCode = this.ReadByteUnsafe(inputStream, out byte result); errorCode.EnsureNoError(); return(result); }
public static void EnsureNoError(this OrigDecoderErrorCode errorCode) { if (errorCode != OrigDecoderErrorCode.NoError) { ThrowExceptionForErrorCode(errorCode); } }
public int ReceiveExtend(int t, ref InputProcessor inputProcessor) { OrigDecoderErrorCode errorCode = this.ReceiveExtendUnsafe(t, ref inputProcessor, out int x); errorCode.EnsureNoError(); return(x); }
/// <summary> /// Reads exactly length bytes into data. It does not care about byte stuffing. /// Does not throw on errors, returns <see cref="OrigJpegDecoderCore"/> instead! /// </summary> /// <param name="data">The data to write to.</param> /// <param name="offset">The offset in the source buffer</param> /// <param name="length">The number of bytes to read</param> /// <returns>The <see cref="OrigDecoderErrorCode"/></returns> public OrigDecoderErrorCode ReadFullUnsafe(byte[] data, int offset, int length) { // Unread the overshot bytes, if any. if (this.Bytes.UnreadableBytes != 0) { if (this.Bits.UnreadBits >= 8) { this.UnreadByteStuffedByte(); } this.Bytes.UnreadableBytes = 0; } this.LastErrorCode = OrigDecoderErrorCode.NoError; while (length > 0 && this.LastErrorCode == OrigDecoderErrorCode.NoError) { if (this.Bytes.J - this.Bytes.I >= length) { Array.Copy(this.Bytes.Buffer, this.Bytes.I, data, offset, length); this.Bytes.I += length; length -= length; } else { Array.Copy(this.Bytes.Buffer, this.Bytes.I, data, offset, this.Bytes.J - this.Bytes.I); offset += this.Bytes.J - this.Bytes.I; length -= this.Bytes.J - this.Bytes.I; this.Bytes.I += this.Bytes.J - this.Bytes.I; this.LastErrorCode = this.Bytes.FillUnsafe(this.InputStream); } } return(this.LastErrorCode); }
/// <summary> /// Receive extend /// </summary> /// <param name="t">Byte</param> /// <param name="inputProcessor">The <see cref="InputProcessor"/></param> /// <param name="x">Read bits value</param> /// <returns>The <see cref="OrigDecoderErrorCode"/></returns> public OrigDecoderErrorCode ReceiveExtendUnsafe(int t, ref InputProcessor inputProcessor, out int x) { if (this.UnreadBits < t) { OrigDecoderErrorCode errorCode = this.EnsureNBitsUnsafe(t, ref inputProcessor); if (errorCode != OrigDecoderErrorCode.NoError) { x = int.MaxValue; return(errorCode); } } this.UnreadBits -= t; this.Mask >>= t; int s = 1 << t; x = (this.Accumulator >> this.UnreadBits) & (s - 1); if (x < (s >> 1)) { x += ((-1) << t) + 1; } return(OrigDecoderErrorCode.NoError); }
/// <summary> /// ReadByteStuffedByte is like ReadByte but is for byte-stuffed Huffman data. /// </summary> /// <param name="inputStream">Input stream</param> /// <param name="x">The result byte as <see cref="int"/></param> /// <returns>The <see cref="OrigDecoderErrorCode"/></returns> public OrigDecoderErrorCode ReadByteStuffedByteUnsafe(Stream inputStream, out int x) { // Take the fast path if bytes.buf contains at least two bytes. if (this.I + 2 <= this.J) { x = this.BufferAsInt[this.I]; this.I++; this.UnreadableBytes = 1; if (x != OrigJpegConstants.Markers.XFFInt) { return(OrigDecoderErrorCode.NoError); } if (this.BufferAsInt[this.I] != 0x00) { return(OrigDecoderErrorCode.MissingFF00); } this.I++; this.UnreadableBytes = 2; x = OrigJpegConstants.Markers.XFF; return(OrigDecoderErrorCode.NoError); } this.UnreadableBytes = 0; OrigDecoderErrorCode errorCode = this.ReadByteAsIntUnsafe(inputStream, out x); this.UnreadableBytes = 1; if (errorCode != OrigDecoderErrorCode.NoError) { return(errorCode); } if (x != OrigJpegConstants.Markers.XFF) { return(OrigDecoderErrorCode.NoError); } errorCode = this.ReadByteAsIntUnsafe(inputStream, out x); this.UnreadableBytes = 2; if (errorCode != OrigDecoderErrorCode.NoError) { return(errorCode); } if (x != 0x00) { return(OrigDecoderErrorCode.MissingFF00); } x = OrigJpegConstants.Markers.XFF; return(OrigDecoderErrorCode.NoError); }
/// <summary> /// Reads bytes from the byte buffer to ensure that bits.UnreadBits is at /// least n. For best performance (avoiding function calls inside hot loops), /// the caller is the one responsible for first checking that bits.UnreadBits < n. /// This method does not throw. Returns <see cref="OrigDecoderErrorCode"/> instead. /// </summary> /// <param name="n">The number of bits to ensure.</param> /// <param name="inputProcessor">The <see cref="InputProcessor"/></param> /// <returns>Error code</returns> public OrigDecoderErrorCode EnsureNBitsUnsafe(int n, ref InputProcessor inputProcessor) { while (true) { OrigDecoderErrorCode errorCode = this.EnsureBitsStepImpl(ref inputProcessor); if (errorCode != OrigDecoderErrorCode.NoError || this.UnreadBits >= n) { return(errorCode); } } }
public static void ThrowExceptionForErrorCode(this OrigDecoderErrorCode errorCode) { switch (errorCode) { case OrigDecoderErrorCode.NoError: throw new ArgumentException("ThrowExceptionForErrorCode() called with NoError!", nameof(errorCode)); case OrigDecoderErrorCode.MissingFF00: throw new MissingFF00Exception(); case OrigDecoderErrorCode.UnexpectedEndOfStream: throw new EOFException(); default: throw new ArgumentOutOfRangeException(nameof(errorCode), errorCode, null); } }
/// <summary> /// Decodes a single bit /// TODO: This method (and also the usages) could be optimized by batching! /// </summary> /// <param name="result">The decoded bit as a <see cref="bool"/></param> /// <returns>The <see cref="OrigDecoderErrorCode" /></returns> public OrigDecoderErrorCode DecodeBitUnsafe(out bool result) { if (this.Bits.UnreadBits == 0) { this.LastErrorCode = this.Bits.Ensure1BitUnsafe(ref this); if (this.LastErrorCode != OrigDecoderErrorCode.NoError) { result = false; return(this.LastErrorCode); } } result = (this.Bits.Accumulator & this.Bits.Mask) != 0; this.Bits.UnreadBits--; this.Bits.Mask >>= 1; return(this.LastErrorCode = OrigDecoderErrorCode.NoError); }
/// <summary> /// Decodes the given number of bits /// </summary> /// <param name="count">The number of bits to decode.</param> /// <param name="result">The <see cref="uint" /> result</param> /// <returns>The <see cref="OrigDecoderErrorCode"/></returns> public OrigDecoderErrorCode DecodeBitsUnsafe(int count, out int result) { if (this.Bits.UnreadBits < count) { this.LastErrorCode = this.Bits.EnsureNBitsUnsafe(count, ref this); if (this.LastErrorCode != OrigDecoderErrorCode.NoError) { result = 0; return(this.LastErrorCode); } } result = this.Bits.Accumulator >> (this.Bits.UnreadBits - count); result = result & ((1 << count) - 1); this.Bits.UnreadBits -= count; this.Bits.Mask >>= count; return(this.LastErrorCode = OrigDecoderErrorCode.NoError); }
public OrigDecoderErrorCode ReadByteAsIntUnsafe(Stream inputStream, out int result) { OrigDecoderErrorCode errorCode = OrigDecoderErrorCode.NoError; while (this.I == this.J) { errorCode = this.FillUnsafe(inputStream); if (errorCode != OrigDecoderErrorCode.NoError) { result = 0; return(errorCode); } } result = this.BufferAsInt[this.I]; this.I++; this.UnreadableBytes = 0; return(errorCode); }
public static void ThrowExceptionForErrorCode(this OrigDecoderErrorCode errorCode) { // REMARK: If this method throws for an image that is expected to be decodable, // consider using the ***Unsafe variant of the parsing method that asks for ThrowExceptionForErrorCode() // then verify the error code + implement fallback logic manually! switch (errorCode) { case OrigDecoderErrorCode.NoError: throw new ArgumentException("ThrowExceptionForErrorCode() called with NoError!", nameof(errorCode)); case OrigDecoderErrorCode.MissingFF00: throw new MissingFF00Exception(); case OrigDecoderErrorCode.UnexpectedEndOfStream: throw new EOFException(); default: throw new ArgumentOutOfRangeException(nameof(errorCode), errorCode, null); } }
private OrigDecoderErrorCode EnsureBitsStepImpl(ref InputProcessor inputProcessor) { OrigDecoderErrorCode errorCode = inputProcessor.Bytes.ReadByteStuffedByteUnsafe(inputProcessor.InputStream, out int c); if (errorCode != OrigDecoderErrorCode.NoError) { return(errorCode); } this.Accumulator = (this.Accumulator << 8) | c; this.UnreadBits += 8; if (this.Mask == 0) { this.Mask = 1 << 7; } else { this.Mask <<= 8; } return(errorCode); }
/// <summary> /// Skips the next n bytes. /// Does not throw, returns <see cref="OrigDecoderErrorCode"/> instead! /// </summary> /// <param name="count">The number of bytes to ignore.</param> /// <returns>The <see cref="OrigDecoderErrorCode"/></returns> public OrigDecoderErrorCode SkipUnsafe(int count) { // Unread the overshot bytes, if any. if (this.Bytes.UnreadableBytes != 0) { if (this.Bits.UnreadBits >= 8) { this.UnreadByteStuffedByte(); } this.Bytes.UnreadableBytes = 0; } while (true) { int m = this.Bytes.J - this.Bytes.I; if (m > count) { m = count; } this.Bytes.I += m; count -= m; if (count == 0) { break; } this.LastErrorCode = this.Bytes.FillUnsafe(this.InputStream); if (this.LastErrorCode != OrigDecoderErrorCode.NoError) { return(this.LastErrorCode); } } return(this.LastErrorCode = OrigDecoderErrorCode.NoError); }
public void ResetErrorState() => this.LastErrorCode = OrigDecoderErrorCode.NoError;
/// <summary> /// Receive extend /// </summary> /// <param name="t">Byte</param> /// <param name="x">Read bits value</param> /// <returns>The <see cref="OrigDecoderErrorCode"/></returns> public OrigDecoderErrorCode ReceiveExtendUnsafe(int t, out int x) { this.LastErrorCode = this.Bits.ReceiveExtendUnsafe(t, ref this, out x); return(this.LastErrorCode); }
public void ReadFull(byte[] data, int offset, int length) { this.LastErrorCode = this.ReadFullUnsafe(data, offset, length); this.LastErrorCode.EnsureNoError(); }
public void Skip(int count) { this.LastErrorCode = this.SkipUnsafe(count); this.LastErrorCode.EnsureNoError(); }
/// <summary> /// Extracts the next Huffman-coded value from the bit-stream into result, decoded according to the given value. /// </summary> /// <param name="huffmanTree">The huffman value</param> /// <param name="result">The decoded <see cref="byte" /></param> /// <returns>The <see cref="OrigDecoderErrorCode"/></returns> public OrigDecoderErrorCode DecodeHuffmanUnsafe(ref OrigHuffmanTree huffmanTree, out int result) { result = 0; if (huffmanTree.Length == 0) { DecoderThrowHelper.ThrowImageFormatException.UninitializedHuffmanTable(); } if (this.Bits.UnreadBits < 8) { this.LastErrorCode = this.Bits.Ensure8BitsUnsafe(ref this); if (this.LastErrorCode == OrigDecoderErrorCode.NoError) { int lutIndex = (this.Bits.Accumulator >> (this.Bits.UnreadBits - OrigHuffmanTree.LutSizeLog2)) & 0xFF; int v = huffmanTree.Lut[lutIndex]; if (v != 0) { int n = (v & 0xFF) - 1; this.Bits.UnreadBits -= n; this.Bits.Mask >>= n; result = v >> 8; return(this.LastErrorCode); } } else { this.UnreadByteStuffedByte(); return(this.LastErrorCode); } } int code = 0; for (int i = 0; i < OrigHuffmanTree.MaxCodeLength; i++) { if (this.Bits.UnreadBits == 0) { this.LastErrorCode = this.Bits.EnsureNBitsUnsafe(1, ref this); if (this.HasError) { return(this.LastErrorCode); } } if ((this.Bits.Accumulator & this.Bits.Mask) != 0) { code |= 1; } this.Bits.UnreadBits--; this.Bits.Mask >>= 1; if (code <= huffmanTree.MaxCodes[i]) { result = huffmanTree.GetValue(code, i); return(this.LastErrorCode = OrigDecoderErrorCode.NoError); } code <<= 1; } // Unrecoverable error, throwing: DecoderThrowHelper.ThrowImageFormatException.BadHuffmanCode(); // DUMMY RETURN! C# doesn't know we have thrown an exception! return(OrigDecoderErrorCode.NoError); }
public OrigDecoderErrorCode ReadByteUnsafe(out byte result) { this.LastErrorCode = this.Bytes.ReadByteUnsafe(this.InputStream, out result); return(this.LastErrorCode); }
public void Fill(Stream inputStream) { OrigDecoderErrorCode errorCode = this.FillUnsafe(inputStream); errorCode.EnsureNoError(); }
public void EnsureNBits(int n, ref InputProcessor inputProcessor) { OrigDecoderErrorCode errorCode = this.EnsureNBitsUnsafe(n, ref inputProcessor); errorCode.EnsureNoError(); }