internal const int OPTIMAL_ML = 0x0F + 4 - 1; // match length that doesn't require an additional byte /// <summary> /// Compress <c>bytes[off:off+len]</c> into <paramref name="out"/> using /// at most 16KB of memory. <paramref name="ht"/> shouldn't be shared across threads /// but can safely be reused. /// </summary> public static void Compress(byte[] bytes, int off, int len, DataOutput @out, HashTable ht) { int @base = off; int end = off + len; int anchor = off++; if (len > LAST_LITERALS + MIN_MATCH) { int limit = end - LAST_LITERALS; int matchLimit = limit - MIN_MATCH; ht.Reset(len); int hashLog = ht.hashLog; PackedInt32s.Mutable hashTable = ht.hashTable; while (off <= limit) { // find a match int @ref; while (true) { if (off >= matchLimit) { goto mainBreak; } int v = ReadInt32(bytes, off); int h = Hash(v, hashLog); @ref = @base + (int)hashTable.Get(h); if (Debugging.AssertsEnabled) Debugging.Assert(PackedInt32s.BitsRequired(off - @base) <= hashTable.BitsPerValue); hashTable.Set(h, off - @base); if (off - @ref < MAX_DISTANCE && ReadInt32(bytes, @ref) == v) { break; } ++off; } // compute match length int matchLen = MIN_MATCH + CommonBytes(bytes, @ref + MIN_MATCH, off + MIN_MATCH, limit); EncodeSequence(bytes, anchor, @ref, off, matchLen, @out); off += matchLen; anchor = off; //mainContinue: ; // LUCENENET NOTE: Not Referenced } mainBreak: ; } // last literals int literalLen = end - anchor; if (Debugging.AssertsEnabled) Debugging.Assert(literalLen >= LAST_LITERALS || literalLen == len); EncodeLastLiterals(bytes, anchor, end - anchor, @out); }
internal void Reset(int len) { int bitsPerOffset = PackedInt32s.BitsRequired(len - LAST_LITERALS); int bitsPerOffsetLog = 32 - (bitsPerOffset - 1).LeadingZeroCount(); hashLog = MEMORY_USAGE + 3 - bitsPerOffsetLog; if (hashTable == null || hashTable.Count < 1 << hashLog || hashTable.BitsPerValue < bitsPerOffset) { hashTable = PackedInt32s.GetMutable(1 << hashLog, bitsPerOffset, PackedInt32s.DEFAULT); } else { hashTable.Clear(); } }