📄 deflaterengine.cs
字号:
throw new InvalidOperationException("future match"); } if (window[curMatch + best_len] != scan_end || window[curMatch + best_len - 1] != scan_end1 || window[curMatch] != window[scan] || window[curMatch + 1] != window[scan + 1]) { continue; } match = curMatch + 2; scan += 2; /* We check for insufficient lookahead only every 8th comparison; * the 256th check will be made at strstart+258. */ while (window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && scan < strend) ; if (scan > best_end) { // if (DeflaterConstants.DEBUGGING && ins_h == 0) // System.err.println("Found match: "+curMatch+"-"+(scan-strstart)); matchStart = curMatch; best_end = scan; best_len = scan - strstart; if (best_len >= niceLength) { break; } scan_end1 = window[best_end - 1]; scan_end = window[best_end]; } scan = strstart; } while ((curMatch = (prev[curMatch & WMASK] & 0xffff)) > limit && --chainLength != 0); matchLen = Math.Min(best_len, lookahead); return matchLen >= MIN_MATCH; } public void SetDictionary(byte[] buffer, int offset, int length) { if (DeflaterConstants.DEBUGGING && strstart != 1) { throw new InvalidOperationException("strstart not 1"); } adler.Update(buffer, offset, length); if (length < MIN_MATCH) { return; } if (length > MAX_DIST) { offset += length - MAX_DIST; length = MAX_DIST; } System.Array.Copy(buffer, offset, window, strstart, length); UpdateHash(); --length; while (--length > 0) { InsertString(); strstart++; } strstart += 2; blockStart = strstart; } private bool DeflateStored(bool flush, bool finish) { if (!flush && lookahead == 0) { return false; } strstart += lookahead; lookahead = 0; int storedLen = strstart - blockStart; if ((storedLen >= DeflaterConstants.MAX_BLOCK_SIZE) || /* Block is full */ (blockStart < WSIZE && storedLen >= MAX_DIST) || /* Block may move out of window */ flush) { bool lastBlock = finish; if (storedLen > DeflaterConstants.MAX_BLOCK_SIZE) { storedLen = DeflaterConstants.MAX_BLOCK_SIZE; lastBlock = false; } // if (DeflaterConstants.DEBUGGING) { // //Console.WriteLine("storedBlock["+storedLen+","+lastBlock+"]"); // } huffman.FlushStoredBlock(window, blockStart, storedLen, lastBlock); blockStart += storedLen; return !lastBlock; } return true; } private bool DeflateFast(bool flush, bool finish) { if (lookahead < MIN_LOOKAHEAD && !flush) { return false; } while (lookahead >= MIN_LOOKAHEAD || flush) { if (lookahead == 0) { /* We are flushing everything */ huffman.FlushBlock(window, blockStart, strstart - blockStart, finish); blockStart = strstart; return false; } if (strstart > 2 * WSIZE - MIN_LOOKAHEAD) { /* slide window, as findLongestMatch need this. * This should only happen when flushing and the window * is almost full. */ SlideWindow(); } int hashHead; if (lookahead >= MIN_MATCH && (hashHead = InsertString()) != 0 && strategy != DeflateStrategy.HuffmanOnly && strstart - hashHead <= MAX_DIST && FindLongestMatch(hashHead)) { /* longestMatch sets matchStart and matchLen */ // if (DeflaterConstants.DEBUGGING) { // for (int i = 0 ; i < matchLen; i++) { // if (window[strstart+i] != window[matchStart + i]) { // throw new Exception(); // } // } // } huffman.TallyDist(strstart - matchStart, matchLen); lookahead -= matchLen; if (matchLen <= max_lazy && lookahead >= MIN_MATCH) { while (--matchLen > 0) { ++strstart; InsertString(); } ++strstart; } else { strstart += matchLen; if (lookahead >= MIN_MATCH - 1) { UpdateHash(); } } matchLen = MIN_MATCH - 1; continue; } else { /* No match found */ huffman.TallyLit(window[strstart] & 0xff); ++strstart; --lookahead; } if (huffman.IsFull()) { bool lastBlock = finish && lookahead == 0; huffman.FlushBlock(window, blockStart, strstart - blockStart, lastBlock); blockStart = strstart; return !lastBlock; } } return true; } private bool DeflateSlow(bool flush, bool finish) { if (lookahead < MIN_LOOKAHEAD && !flush) { return false; } while (lookahead >= MIN_LOOKAHEAD || flush) { if (lookahead == 0) { if (prevAvailable) { huffman.TallyLit(window[strstart-1] & 0xff); } prevAvailable = false; /* We are flushing everything */ if (DeflaterConstants.DEBUGGING && !flush) { throw new Exception("Not flushing, but no lookahead"); } huffman.FlushBlock(window, blockStart, strstart - blockStart, finish); blockStart = strstart; return false; } if (strstart >= 2 * WSIZE - MIN_LOOKAHEAD) { /* slide window, as findLongestMatch need this. * This should only happen when flushing and the window * is almost full. */ SlideWindow(); } int prevMatch = matchStart; int prevLen = matchLen; if (lookahead >= MIN_MATCH) { int hashHead = InsertString(); if (strategy != DeflateStrategy.HuffmanOnly && hashHead != 0 && strstart - hashHead <= MAX_DIST && FindLongestMatch(hashHead)) { /* longestMatch sets matchStart and matchLen */ /* Discard match if too small and too far away */ if (matchLen <= 5 && (strategy == DeflateStrategy.Filtered || (matchLen == MIN_MATCH && strstart - matchStart > TOO_FAR))) { matchLen = MIN_MATCH - 1; } } } /* previous match was better */ if (prevLen >= MIN_MATCH && matchLen <= prevLen) { // if (DeflaterConstants.DEBUGGING) { // for (int i = 0 ; i < matchLen; i++) { // if (window[strstart-1+i] != window[prevMatch + i]) // throw new Exception(); // } // } huffman.TallyDist(strstart - 1 - prevMatch, prevLen); prevLen -= 2; do { strstart++; lookahead--; if (lookahead >= MIN_MATCH) { InsertString(); } } while (--prevLen > 0); strstart ++; lookahead--; prevAvailable = false; matchLen = MIN_MATCH - 1; } else { if (prevAvailable) { huffman.TallyLit(window[strstart-1] & 0xff); } prevAvailable = true; strstart++; lookahead--; } if (huffman.IsFull()) { int len = strstart - blockStart; if (prevAvailable) { len--; } bool lastBlock = (finish && lookahead == 0 && !prevAvailable); huffman.FlushBlock(window, blockStart, len, lastBlock); blockStart += len; return !lastBlock; } } return true; } public bool Deflate(bool flush, bool finish) { bool progress; do { FillWindow(); bool canFlush = flush && inputOff == inputEnd; // if (DeflaterConstants.DEBUGGING) { // //Console.WriteLine("window: ["+blockStart+","+strstart+"," // +lookahead+"], "+comprFunc+","+canFlush); // } switch (comprFunc) { case DEFLATE_STORED: progress = DeflateStored(canFlush, finish); break; case DEFLATE_FAST: progress = DeflateFast(canFlush, finish); break; case DEFLATE_SLOW: progress = DeflateSlow(canFlush, finish); break; default: throw new InvalidOperationException("unknown comprFunc"); } } while (pending.IsFlushed && progress); /* repeat while we have no pending output and progress was made */ return progress; } public void SetInput(byte[] buf, int off, int len) { if (inputOff < inputEnd) { throw new InvalidOperationException("Old input was not completely processed"); } int end = off + len; /* We want to throw an ArrayIndexOutOfBoundsException early. The * check is very tricky: it also handles integer wrap around. */ if (0 > off || off > end || end > buf.Length) { throw new ArgumentOutOfRangeException(); } inputBuf = buf; inputOff = off; inputEnd = end; } public bool NeedsInput() { return inputEnd == inputOff; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -