Exemple #1
0
        private int CopyFromRingBuffer(byte[] buffer, int offset, int count, int distance, int copy, int state)
        {
            var result = copy + state;

            if (count < result)
            {
                DecodedBuffer = new byte[result];
                CopyFromRingBuffer(DecodedBuffer, 0, DecodedBuffer.Length, distance, copy, state);
                return(0);
            }

            var size = copy;

            if (copy > distance)
            {
                size = distance;
                RingBuffer.Seek(-distance);
                var read = RingBuffer.Read(buffer, offset, size);
                if (read == 0)
                {
                    throw new EndOfStreamException();
                }
                Debug.Assert(read == size);
                RingBuffer.Seek(distance - read);
                RingBuffer.Write(buffer, offset, read);
                copy -= read;
                var copies = copy / distance;
                for (int i = 0; i < copies; i++)
                {
                    RingBuffer.Write(buffer, offset, read);
                    Buffer.BlockCopy(buffer, offset, buffer, offset + read, read);
                    offset += read;
                    copy   -= read;
                }
                offset += read;
            }
            while (copy > 0)
            {
                RingBuffer.Seek(-distance);
                if (copy < size)
                {
                    size = copy;
                }
                var read = RingBuffer.Read(buffer, offset, size);
                if (read == 0)
                {
                    throw new EndOfStreamException();
                }
                RingBuffer.Seek(distance - read);
                RingBuffer.Write(buffer, offset, read);
                offset += read;
                copy   -= read;
            }
            if (state > 0)
            {
                Copy(buffer, offset, state);
            }
            State = (LzoState)state;
            return(result);
        }
Exemple #2
0
 private void DecodeFirstByte()
 {
     Instruction = Source.ReadByte();
     if (Instruction == -1)
     {
         throw new EndOfStreamException();
     }
     if (Instruction > 15 && Instruction <= 17)
     {
         throw new Exception();
     }
     if (Instruction >= 18)
     {
         int num_literals = Instruction - 17;
         // Need different decoding
         DecodedBuffer = new byte[num_literals];
         Copy(DecodedBuffer, 0, num_literals);
         if (Instruction <= 21)
         {
             State = (LzoState)(num_literals);
         }
         else
         {
             State = LzoState.LargeCopy;
         }
         Instruction = Source.ReadByte();
         if (Instruction == -1)
         {
             throw new EndOfStreamException();
         }
     }
 }
Exemple #3
0
        private int CopyFromRingBuffer(byte[] buffer, int offset, int count, int distance, int copy, int state)
        {
            Debug.Assert(copy >= 0);
            var result = copy + state;

            State = (LzoState)state;
            if (count >= result)
            {
                var size = copy;
                if (copy > distance)
                {
                    size = distance;
                    RingBuffer.Copy(buffer, offset, distance, size);
                    copy -= size;
                    var copies = copy / distance;
                    for (int i = 0; i < copies; i++)
                    {
                        Buffer.BlockCopy(buffer, offset, buffer, offset + size, size);
                        offset += size;
                        copy   -= size;
                    }
                    if (copies > 0)
                    {
                        var length = size * copies;
                        RingBuffer.Write(buffer, offset - length, length);
                    }
                    offset += size;
                }
                if (copy > 0)
                {
                    if (copy < size)
                    {
                        size = copy;
                    }
                    RingBuffer.Copy(buffer, offset, distance, size);
                    offset += size;
                }
                if (state > 0)
                {
                    Copy(buffer, offset, state);
                }
                return(result);
            }

            if (count <= copy)
            {
                CopyFromRingBuffer(buffer, offset, count, distance, count, 0);
                DecodedBuffer = new byte[result - count];
                CopyFromRingBuffer(DecodedBuffer, 0, DecodedBuffer.Length, distance, copy - count, state);
                return(count);
            }
            CopyFromRingBuffer(buffer, offset, count, distance, copy, 0);
            var remaining = count - copy;

            DecodedBuffer = new byte[state - remaining];
            Copy(buffer, offset + copy, remaining);
            Copy(DecodedBuffer, 0, state - remaining);
            return(count);
        }
 public Snapshot(long outputPosition, long inputPosition, RingBuffer ringBuffer, int instruction, LzoState state)
 {
     _ringBuffer    = ringBuffer.Clone();
     Instruction    = instruction;
     State          = state;
     InputPosition  = inputPosition;
     OutputPosition = outputPosition;
 }
Exemple #5
0
        protected virtual int Decode(byte[] buffer, int offset, int count)
        {
            Debug.Assert(count > 0);
            Debug.Assert(DecodedBuffer == null);
            int read;

            if (Instruction <= 15)
            {
                /*
                 * Depends on the number of literals copied by the last instruction.
                 */
                switch (State)
                {
                case LzoState.ZeroCopy:
                {
                    /*
                     * this encoding will be a copy of 4 or more literal, and must be interpreted
                     * like this :                         *
                     * 0 0 0 0 L L L L  (0..15)  : copy long literal string
                     * length = 3 + (L ?: 15 + (zero_bytes * 255) + non_zero_byte)
                     * state = 4  (no extra literals are copied)
                     */
                    var length = 3;
                    if (Instruction != 0)
                    {
                        length += Instruction;
                    }
                    else
                    {
                        length += 15 + ReadLength();
                    }
                    if (length > count)
                    {
                        Copy(buffer, offset, count);
                        DecodedBuffer = new byte[length - count];
                        Copy(DecodedBuffer, 0, length - count);
                        read = count;
                    }
                    else
                    {
                        Copy(buffer, offset, length);
                        read = length;
                    }
                    State = LzoState.LargeCopy;
                    break;
                }

                case LzoState.SmallCopy1:
                case LzoState.SmallCopy2:
                case LzoState.SmallCopy3:
                    read = SmallCopy(buffer, offset, count);
                    break;

                case LzoState.LargeCopy:
                    read = LargeCopy(buffer, offset, count);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }
            else if (Instruction < 32)
            {
                /*
                 * 0 0 0 1 H L L L  (16..31)
                 * Copy of a block within 16..48kB distance (preferably less than 10B)
                 * length = 2 + (L ?: 7 + (zero_bytes * 255) + non_zero_byte)
                 * Always followed by exactly one LE16 :  D D D D D D D D : D D D D D D S S
                 * distance = 16384 + (H << 14) + D
                 * state = S (copy S literals after this block)
                 * End of stream is reached if distance == 16384
                 */
                int length;
                var l = Instruction & 0x7;
                if (l == 0)
                {
                    length = 2 + 7 + ReadLength();
                }
                else
                {
                    length = 2 + l;
                }
                var s = Source.ReadByte();
                if (s == -1)
                {
                    throw new EndOfStreamException();
                }
                var d = Source.ReadByte();
                if (d == -1)
                {
                    throw new EndOfStreamException();
                }
                d = ((d << 8) | s) >> 2;
                var distance = 16384 + ((Instruction & 0x8) << 11) | d;
                if (distance == 16384)
                {
                    return(-1);
                }

                read = CopyFromRingBuffer(buffer, offset, count, distance, length, s & 0x3);
            }
            else if (Instruction < 64)
            {
                /*
                 * 0 0 1 L L L L L  (32..63)
                 * Copy of small block within 16kB distance (preferably less than 34B)
                 * length = 2 + (L ?: 31 + (zero_bytes * 255) + non_zero_byte)
                 * Always followed by exactly one LE16 :  D D D D D D D D : D D D D D D S S
                 * distance = D + 1
                 * state = S (copy S literals after this block)
                 */
                int length;
                var l = Instruction & 0x1f;
                if (l == 0)
                {
                    length = 2 + 31 + ReadLength();
                }
                else
                {
                    length = 2 + l;
                }
                var s = Source.ReadByte();
                if (s == -1)
                {
                    throw new EndOfStreamException();
                }
                var d = Source.ReadByte();
                if (d == -1)
                {
                    throw new EndOfStreamException();
                }
                d = ((d << 8) | s) >> 2;
                var distance = d + 1;

                read = CopyFromRingBuffer(buffer, offset, count, distance, length, s & 0x3);
            }
            else if (Instruction < 128)
            {
                /*
                 * 0 1 L D D D S S  (64..127)
                 * Copy 3-4 bytes from block within 2kB distance
                 * state = S (copy S literals after this block)
                 * length = 3 + L
                 * Always followed by exactly one byte : H H H H H H H H
                 * distance = (H << 3) + D + 1
                 */
                var length = 3 + ((Instruction >> 5) & 0x1);
                var result = Source.ReadByte();
                if (result == -1)
                {
                    throw new EndOfStreamException();
                }
                var distance = (result << 3) + ((Instruction >> 2) & 0x7) + 1;

                read = CopyFromRingBuffer(buffer, offset, count, distance, length, Instruction & 0x3);
            }
            else
            {
                /*
                 * 1 L L D D D S S  (128..255)
                 * Copy 5-8 bytes from block within 2kB distance
                 * state = S (copy S literals after this block)
                 * length = 5 + L
                 * Always followed by exactly one byte : H H H H H H H H
                 * distance = (H << 3) + D + 1
                 */
                var length = 5 + ((Instruction >> 5) & 0x3);
                var result = Source.ReadByte();
                if (result == -1)
                {
                    throw new EndOfStreamException();
                }
                var distance = (result << 3) + ((Instruction & 0x1c) >> 2) + 1;

                read = CopyFromRingBuffer(buffer, offset, count, distance, length, Instruction & 0x3);
            }

            Instruction = Source.ReadByte();
            if (Instruction == -1)
            {
                throw new EndOfStreamException();
            }
            OutputPosition += read;
            return(read);
        }
Exemple #6
0
        protected virtual int Decode(byte[] buffer, int offset, int count)
        {
            Debug.Assert(DecodedBuffer == null);
            int read;

            if (Instruction <= 15)
            {
                /*
                 * Depends on the number of literals copied by the last instruction.
                 */
                int distance;
                int length;
                switch (State)
                {
                case LzoState.ZeroCopy:
                    /*
                     * this encoding will be a copy of 4 or more literal, and must be interpreted
                     * like this :                         *
                     * 0 0 0 0 L L L L  (0..15)  : copy long literal string
                     * length = 3 + (L ?: 15 + (zero_bytes * 255) + non_zero_byte)
                     * state = 4  (no extra literals are copied)
                     */
                    length = 3;
                    if (Instruction != 0)
                    {
                        length += Instruction;
                    }
                    else
                    {
                        length += 15 + ReadLength();
                    }
                    if (length > count)
                    {
                        DecodedBuffer = new byte[length];
                        Copy(DecodedBuffer, 0, length);
                        read = 0;
                    }
                    else
                    {
                        Copy(buffer, offset, length);
                        read = length;
                    }
                    State = LzoState.LargeCopy;
                    break;

                case LzoState.SmallCopy1:
                case LzoState.SmallCopy2:
                case LzoState.SmallCopy3:
                    /*
                     * the instruction is a copy of a
                     * 2-byte block from the dictionary within a 1kB distance. It is worth
                     * noting that this instruction provides little savings since it uses 2
                     * bytes to encode a copy of 2 other bytes but it encodes the number of
                     * following literals for free. It must be interpreted like this :
                     *
                     * 0 0 0 0 D D S S  (0..15)  : copy 2 bytes from <= 1kB distance
                     * length = 2
                     * state = S (copy S literals after this block)
                     * Always followed by exactly one byte : H H H H H H H H
                     * distance = (H << 2) + D + 1
                     */
                    var h = GetByte();
                    distance = (h << 2) + ((Instruction & 0xc) >> 2) + 1;

                    read = CopyFromRingBuffer(buffer, offset, count, distance, 2, Instruction & 0x3);
                    break;

                case LzoState.LargeCopy:
                    /*
                     * the instruction becomes a copy of a 3-byte block from the
                     * dictionary from a 2..3kB distance, and must be interpreted like this :
                     * 0 0 0 0 D D S S  (0..15)  : copy 3 bytes from 2..3 kB distance
                     * length = 3
                     * state = S (copy S literals after this block)
                     * Always followed by exactly one byte : H H H H H H H H
                     * distance = (H << 2) + D + 2049
                     */
                    distance = (GetByte() << 2) + ((Instruction & 0xc) >> 2) + 2049;

                    read = CopyFromRingBuffer(buffer, offset, count, distance, 3, Instruction & 0x3);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }
            else if (Instruction < 32)
            {
                /*
                 * 0 0 0 1 H L L L  (16..31)
                 * Copy of a block within 16..48kB distance (preferably less than 10B)
                 * length = 2 + (L ?: 7 + (zero_bytes * 255) + non_zero_byte)
                 * Always followed by exactly one LE16 :  D D D D D D D D : D D D D D D S S
                 * distance = 16384 + (H << 14) + D
                 * state = S (copy S literals after this block)
                 * End of stream is reached if distance == 16384
                 */
                int length;
                var l = Instruction & 0x7;
                if (l == 0)
                {
                    length = 2 + 7 + ReadLength();
                }
                else
                {
                    length = 2 + l;
                }
                var s = GetByte();
                var d = GetByte() << 8;
                d = (d | s) >> 2;
                var distance = 16384 + ((Instruction & 0x8) << 11) | d;
                if (distance == 16384)
                {
                    return(-1);
                }

                read = CopyFromRingBuffer(buffer, offset, count, distance, length, s & 0x3);
            }
            else if (Instruction < 64)
            {
                /*
                 * 0 0 1 L L L L L  (32..63)
                 * Copy of small block within 16kB distance (preferably less than 34B)
                 * length = 2 + (L ?: 31 + (zero_bytes * 255) + non_zero_byte)
                 * Always followed by exactly one LE16 :  D D D D D D D D : D D D D D D S S
                 * distance = D + 1
                 * state = S (copy S literals after this block)
                 */
                int length;
                var l = Instruction & 0x1f;
                if (l == 0)
                {
                    length = 2 + 31 + ReadLength();
                }
                else
                {
                    length = 2 + l;
                }
                var s = GetByte();
                var d = GetByte() << 8;
                d = (d | s) >> 2;
                var distance = d + 1;

                read = CopyFromRingBuffer(buffer, offset, count, distance, length, s & 0x3);
            }
            else if (Instruction < 128)
            {
                /*
                 * 0 1 L D D D S S  (64..127)
                 * Copy 3-4 bytes from block within 2kB distance
                 * state = S (copy S literals after this block)
                 * length = 3 + L
                 * Always followed by exactly one byte : H H H H H H H H
                 * distance = (H << 3) + D + 1
                 */
                var length   = 3 + ((Instruction >> 5) & 0x1);
                var distance = (GetByte() << 3) + ((Instruction >> 2) & 0x7) + 1;

                read = CopyFromRingBuffer(buffer, offset, count, distance, length, Instruction & 0x3);
            }
            else
            {
                /*
                 * 1 L L D D D S S  (128..255)
                 * Copy 5-8 bytes from block within 2kB distance
                 * state = S (copy S literals after this block)
                 * length = 5 + L
                 * Always followed by exactly one byte : H H H H H H H H
                 * distance = (H << 3) + D + 1
                 */
                var length   = 5 + ((Instruction >> 5) & 0x3);
                var distance = (GetByte() << 3) + ((Instruction & 0x1c) >> 2) + 1;

                read = CopyFromRingBuffer(buffer, offset, count, distance, length, Instruction & 0x3);
            }

            Instruction     = GetByte();
            OutputPosition += read;
            return(read);
        }