public byte[] Compress(byte[] input, int windowBits = 26, LZHPerformance mode = LZHPerformance.NORMAL) { switch (mode) { case LZHPerformance.L1_VeryFast: Matcher = new HashTable3(input, windowBits); LazyParse = false; break; case LZHPerformance.L2_VeryFast: Matcher = new HashTable3(input, windowBits); LazyParse = true; break; case LZHPerformance.L3_Fast: Matcher = new MetaHT3HC4(input, windowBits, 4); LazyParse = false; break; case LZHPerformance.L4_Fast: Matcher = new MetaHT3HC4(input, windowBits, 4); LazyParse = true; break; case LZHPerformance.NORMAL: Matcher = new MetaHT3HC4HC8(input, 26, 16); LazyParse = false; break; case LZHPerformance.BETTER: Matcher = new MetaHT3HC4HC8(input, 26, 32); LazyParse = true; break; } int inputSize = input.Length; int inputOffset = 0; Output = new BitWriterFwd(); CachedPosition = -1; CachedMatch = default; SymbolFreqs = new int[NUM_SYMBOLS]; ChunkBuffer = new ushort[Math.Min(inputSize, CHUNK_SIZE)]; MatchEncodes = new Queue <MatchData>(); CalcChunkEnd(inputOffset, inputSize); while (true) { var match = FindBestMatch(inputOffset); bool matchAvailable = match.Benefit > 0; if (matchAvailable && LazyParse) { var nextMatch = PeekNextMatch(inputOffset + 1); if (nextMatch.Benefit > match.Benefit) { matchAvailable = false; } } if (matchAvailable) { if (match.Length > MAX_MATCH) { match.Length = MAX_MATCH; } EmitMatch(match.Length, match.Distance); inputOffset += match.Length; } else // No match available, emit literal { EmitSymbol(input[inputOffset++]); } // Encode chunk if we've reached end of chunk if (inputOffset >= ChunkEnd) { if (ChunkEnd == inputSize) { EmitSymbol(SYM_EOF); } else { EmitSymbol(SYM_NEWTREE); } EncodeChunk(); if (inputOffset >= inputSize) { break; } CalcChunkEnd(inputOffset, inputSize); } } return(Output.GetBuffer()); }
public void Encode(BitWriterFwd writer, int symbol) { var sym = Symbols[symbol]; writer.WriteBits(sym.Code, sym.Length); }