using System; using System.Collections.Generic; using System.Linq; using System.Text; using UniversalEditor.Accessors; using UniversalEditor.IO; namespace UniversalEditor.Compression.Modules.LZRW1 { public class LZRW1CompressionModule : CompressionModule { /// /// Number of bytes used by copy flag /// private const byte FLAG_BYTES = 0x04; private const byte FLAG_COMPRESS = 0x00; private const byte FLAG_COPY = 0x01; public override string Name { get { return "LZRW1"; } } protected override void CompressInternal(System.IO.Stream inputStream, System.IO.Stream outputStream) { throw new NotImplementedException(); } protected override void DecompressInternal(System.IO.Stream inputStream, System.IO.Stream outputStream, int inputLength, int outputLength) { StreamAccessor sao = new StreamAccessor(outputStream); StreamAccessor sai = new StreamAccessor(inputStream); Reader br = new Reader(sai); Writer bw = new Writer(sao); int flag = br.ReadInt32(); if (flag == FLAG_COPY) { // entire stream is uncompressed, so read it all byte[] data = br.ReadToEnd(); bw.WriteBytes(data); } else { // flag is not copy, so we have to decompress ushort controlbits = 0, control = 0; while (!br.EndOfStream) { if (controlbits == 0) { // control bits are 0, so it's time to read a new control ushort // don't use ReadUInt16 here because we need to keep the bytes // for future use control = br.ReadByte(); control |= (ushort)(br.ReadByte() << 8); controlbits = 16; } int k = 1; // 0x8000; // 1 if ((control & k) != 0) { ushort offset, len; offset = (ushort)((br.PeekByte() & 0xF0) << 4); len = (ushort)(1 + (br.ReadByte() & 0xF)); offset += (ushort)(br.ReadByte() & 0xFF); bw.Flush(); sao.Position = sao.Length - offset; byte[] nextdata = sao.Reader.ReadBytes(len); bw.WriteBytes(nextdata); } else { // control bit is 0, so perform a simple copy of the next byte bw.WriteByte(br.ReadByte()); } // pop the latest control bit off the control ushort control >>= 1; controlbits--; } bw.Flush(); } } } }