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); }
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(); } } }
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; }
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); }
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); }