⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lzmaencoder.cs

📁 LZMA 是 7-Zip 程序中 7z 格式 的默认压缩算法。LZMA 能提供给用户极高的压缩比及较快的压缩速度
💻 CS
📖 第 1 页 / 共 4 页
字号:
				ReadMatchDistances(out newLen);
				if (newLen >= _numFastBytes)
				{
					_longestMatchLength = newLen;
					_longestMatchWasFound = true;
					return Backward(out backRes, cur);
				}
				UInt32 curPrice = _optimum[cur].Price;

				currentByte = _matchFinder.GetIndexByte(0 - 1);
				matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1));

				posState = (position & _posStateMask);

				UInt32 curAnd1Price = curPrice +
					_isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() +
					_literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)).
					GetPrice(!state.IsCharState(), matchByte, currentByte);

				Optimal nextOptimum = _optimum[cur + 1];

				bool nextIsChar = false;
				if (curAnd1Price < nextOptimum.Price)
				{
					nextOptimum.Price = curAnd1Price;
					nextOptimum.PosPrev = cur;
					nextOptimum.MakeAsChar();
					nextIsChar = true;
				}

				matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();
				repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1();

				if (matchByte == currentByte &&
					!(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0))
				{
					UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState);
					if (shortRepPrice <= nextOptimum.Price)
					{
						nextOptimum.Price = shortRepPrice;
						nextOptimum.PosPrev = cur;
						nextOptimum.MakeAsShortRep();
						// nextIsChar = false;
					}
				}
				/*
				if(newLen == 2 && _matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ?
					continue;
				*/

				UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1;
				numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull);
				UInt32 numAvailableBytes = numAvailableBytesFull;

				if (numAvailableBytes < 2)
					continue;
				if (numAvailableBytes > _numFastBytes)
					numAvailableBytes = _numFastBytes;
				if (numAvailableBytes >= 3 && !nextIsChar)
				{
					UInt32 backOffset = reps[0] + 1;
					UInt32 temp;
					for (temp = 1; temp < numAvailableBytes; temp++)
						// if (data[temp] != data[(size_t)temp - backOffset])
						if (_matchFinder.GetIndexByte((Int32)temp - 1) != _matchFinder.GetIndexByte((Int32)temp - (Int32)backOffset - 1))
							break;
					UInt32 lenTest2 = temp - 1;
					if (lenTest2 >= 2)
					{
						Base.State state2 = state;
						state2.UpdateChar();
						UInt32 posStateNext = (position + 1) & _posStateMask;
						UInt32 nextRepMatchPrice = curAnd1Price +
							_isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() +
							_isRep[state2.Index].GetPrice1();
						// for (; lenTest2 >= 2; lenTest2--)
						{
							while (lenEnd < cur + 1 + lenTest2)
								_optimum[++lenEnd].Price = kIfinityPrice;
							UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
								0, lenTest2, state2, posStateNext);
							Optimal optimum = _optimum[cur + 1 + lenTest2];
							if (curAndLenPrice < optimum.Price)
							{
								optimum.Price = curAndLenPrice;
								optimum.PosPrev = cur + 1;
								optimum.BackPrev = 0;
								optimum.Prev1IsChar = true;
								optimum.Prev2 = false;
							}
						}
					}
				}
				for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++)
				{
					// UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it;
					UInt32 backOffset = reps[repIndex] + 1;
					if (_matchFinder.GetIndexByte(-1) != 
						  _matchFinder.GetIndexByte((Int32)(-1 - (Int32)backOffset)) ||
							_matchFinder.GetIndexByte(0) != 
							_matchFinder.GetIndexByte((Int32)(0 - (Int32)backOffset)))
						continue;
					UInt32 lenTest;
					for (lenTest = 2; lenTest < numAvailableBytes; lenTest++)
						if (_matchFinder.GetIndexByte((Int32)lenTest - 1) != 
						    _matchFinder.GetIndexByte((Int32)lenTest - 1 - (Int32)backOffset))
							break;
					UInt32 lenTestTemp = lenTest;
				  do
					{
						while (lenEnd < cur + lenTest)
							_optimum[++lenEnd].Price = kIfinityPrice;
						UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState);
						Optimal optimum = _optimum[cur + lenTest];
						if (curAndLenPrice < optimum.Price)
						{
							optimum.Price = curAndLenPrice;
							optimum.PosPrev = cur;
							optimum.BackPrev = repIndex;
							optimum.Prev1IsChar = false;
						}
					}
					while(--lenTest >= 2);
					lenTest = lenTestTemp;

					if (_maxMode)
					{
						UInt32 lenTest2 = lenTest + 1;
						UInt32 limit = Math.Min(numAvailableBytesFull, lenTest2 + _numFastBytes);
						for (; lenTest2 < limit; lenTest2++)
							if (_matchFinder.GetIndexByte((Int32)((Int32)lenTest2 - 1)) !=
									_matchFinder.GetIndexByte((Int32)((Int32)lenTest2 - 1 - (Int32)backOffset)))
								break;
						lenTest2 -= lenTest + 1;
						if (lenTest2 >= 2)
						{
							Base.State state2 = state;
							state2.UpdateRep();
							UInt32 posStateNext = (position + lenTest) & _posStateMask;
							UInt32 curAndLenCharPrice = 
									repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + 
									_isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() +
									_literalEncoder.GetSubCoder(position + lenTest, 
											_matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true,
											_matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)backOffset)), 
											_matchFinder.GetIndexByte((Int32)lenTest - 1));
							state2.UpdateChar();
							posStateNext = (position + lenTest + 1) & _posStateMask;
							UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1();
							UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();
	            
							// for(; lenTest2 >= 2; lenTest2--)
							{
								UInt32 offset = lenTest + 1 + lenTest2;
								while(lenEnd < cur + offset)
									_optimum[++lenEnd].Price = kIfinityPrice;
								UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
								Optimal optimum = _optimum[cur + offset];
								if (curAndLenPrice < optimum.Price) 
								{
									optimum.Price = curAndLenPrice;
									optimum.PosPrev = cur + lenTest + 1;
									optimum.BackPrev = 0;
									optimum.Prev1IsChar = true;
									optimum.Prev2 = true;
									optimum.PosPrev2 = cur;
									optimum.BackPrev2 = repIndex;
								}
							}
						}
					}
				}

				//    for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++)
				if (newLen > numAvailableBytes)
					newLen = numAvailableBytes;
				if (newLen >= 2)
				{
					if (newLen == 2 && _matchDistances[2] >= 0x80)
						continue;
					normalMatchPrice = matchPrice +
						_isRep[state.Index].GetPrice0();
					while (lenEnd < cur + newLen)
						_optimum[++lenEnd].Price = kIfinityPrice;

					for (UInt32 lenTest = newLen; lenTest >= 2; lenTest--)
					{
						UInt32 curBack = _matchDistances[lenTest];
						UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState);
						Optimal optimum = _optimum[cur + lenTest];
						if (curAndLenPrice < optimum.Price)
						{
							optimum.Price = curAndLenPrice;
							optimum.PosPrev = cur;
							optimum.BackPrev = curBack + Base.kNumRepDistances;
							optimum.Prev1IsChar = false;
						}

						if (_maxMode && (lenTest == newLen || curBack != _matchDistances[lenTest + 1]))
						{
							UInt32 backOffset = curBack + 1;
							UInt32 lenTest2 = lenTest + 1;
							UInt32 limit = Math.Min(numAvailableBytesFull, lenTest2 + _numFastBytes);
							for (; lenTest2 < limit; lenTest2++)
								if (_matchFinder.GetIndexByte((Int32)lenTest2 - 1) != _matchFinder.GetIndexByte((Int32)lenTest2 - (Int32)backOffset - 1))
									break;
							lenTest2 -= lenTest + 1;
							if (lenTest2 >= 2)
							{
								Base.State state2 = state;
								state2.UpdateMatch();
								UInt32 posStateNext = (position + lenTest) & _posStateMask;
								UInt32 curAndLenCharPrice = curAndLenPrice +
									_isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() +
									_literalEncoder.GetSubCoder(position + lenTest,
									// data[(size_t)lenTest - 1], 
									_matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).
									GetPrice(true,
									// data[(size_t)lenTest - backOffset], data[lenTest]
									_matchFinder.GetIndexByte((Int32)lenTest - (Int32)backOffset - 1),
									_matchFinder.GetIndexByte((Int32)lenTest - 1)
									);
								state2.UpdateChar();
								posStateNext = (position + lenTest + 1) & _posStateMask;
								UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1();
								UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();

								// for(; lenTest2 >= 2; lenTest2--)
								{
									UInt32 offset = lenTest + 1 + lenTest2;
									while (lenEnd < cur + offset)
										_optimum[++lenEnd].Price = kIfinityPrice;
									curAndLenPrice = nextRepMatchPrice + GetRepPrice(
										0, lenTest2, state2, posStateNext);
									optimum = _optimum[cur + offset];
									if (curAndLenPrice < optimum.Price)
									{
										optimum.Price = curAndLenPrice;
										optimum.PosPrev = cur + lenTest + 1;
										optimum.BackPrev = 0;
										optimum.Prev1IsChar = true;
										optimum.Prev2 = true;
										optimum.PosPrev2 = cur;
										optimum.BackPrev2 = curBack + Base.kNumRepDistances;
									}
								}
							}
						}
					}
				}
			}
		}

		bool ChangePair(UInt32 smallDist, UInt32 bigDist)
		{
			const int kDif = 7;
			return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif));
		}

		UInt32 GetOptimumFast(UInt32 position, out UInt32 backRes)
		{
			UInt32 lenMain;
			if (!_longestMatchWasFound)
			{
				ReadMatchDistances(out lenMain);
			}
			else
			{
				lenMain = _longestMatchLength;
				_longestMatchWasFound = false;
			}
			UInt32 repMaxIndex = 0;
			for (UInt32 i = 0; i < Base.kNumRepDistances; i++)
			{
				repLens[i] = _matchFinder.GetMatchLen(0 - 1, _repDistances[i], Base.kMatchMaxLen);
				if (i == 0 || repLens[i] > repLens[repMaxIndex])
					repMaxIndex = i;
			}
			if (repLens[repMaxIndex] >= _numFastBytes)
			{
				backRes = repMaxIndex;
				UInt32 lenRes = repLens[repMaxIndex];
				MovePos(lenRes - 1);
				return lenRes;
			}
			if (lenMain >= _numFastBytes)
			{
				backRes = _matchDistances[_numFastBytes] + Base.kNumRepDistances;
				MovePos(lenMain - 1);
				return lenMain;
			}
			while (lenMain > 2)
			{
				if (!ChangePair(_matchDistances[lenMain - 1], _matchDistances[lenMain]))
					break;
				lenMain--;
			}
			if (lenMain == 2 && _matchDistances[2] >= 0x80)
				lenMain = 1;

			UInt32 backMain = _matchDistances[lenMain];
			if (repLens[repMaxIndex] >= 2)
			{
				if (repLens[repMaxIndex] + 1 >= lenMain ||
					repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 12)))
				{
					backRes = repMaxIndex;
					UInt32 lenRes = repLens[repMaxIndex];
					MovePos(lenRes - 1);
					return lenRes;
				}
			}

			if (lenMain >= 2)
			{
				ReadMatchDistances(out _longestMatchLength);
				if (_longestMatchLength >= 2 &&
					(
					(_longestMatchLength >= lenMain &&
					_matchDistances[lenMain] < backMain) ||
					_longestMatchLength == lenMain + 1 &&
					!ChangePair(backMain, _matchDistances[_longestMatchLength]) ||
					_longestMatchLength > lenMain + 1 ||
					_longestMatchLength + 1 >= lenMain && lenMain >= 3 &&
					ChangePair(_matchDistances[lenMain - 1], backMain)
					)
					)
				{
					_longestMatchWasFound = true;
					backRes = 0xFFFFFFFF;
					return 1;
				}
				for (UInt32 i = 0; i < Base.kNumRepDistances; i++)
				{
					UInt32 repLen = _matchFinder.GetMatchLen(0 - 1, _repDistances[i], Base.kMatchMaxLen);
					if (repLen >= 2 && repLen + 1 >= lenMain)
					{
						_longestMatchWasFound = true;
						backRes = 0xFFFFFFFF;
						return 1;
					}
				}
				backRes = backMain + Base.kNumRepDistances;
				MovePos(lenMain - 2);
				return lenMain;
			}
			backRes = 0xFFFFFFFF;
			return 1;
		}

		void InitMatchFinder(LZ.IMatchFinder matchFinder)
		{
			_matchFinder = matchFinder;
		}

		void WriteEndMarker(UInt32 posState)
		{
			if (!_writeEndMark)
				return;

			_isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1);
			_isRep[_state.Index].Encode(_rangeEncoder, 0);
			_state.UpdateMatch();
			UInt32 len = Base.kMatchMinLen; // kMatchMaxLen;
			_lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
			UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1;
			UInt32 lenToPosState = Base.GetLenToPosState(len);
			_posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
			int footerBits = 30;
			UInt32 posReduced = (((UInt32)1) << footerBits) - 1;
			_rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);
			_posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);
		}

		void Flush(UInt32 nowPos)
		{
			ReleaseMFStream();
			WriteEndMarker(nowPos & _posStateMask);
			_rangeEncoder.FlushData();
			_rangeEncoder.FlushStream();
		}

		public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished)
		{
			inSize = 0;
			outSize = 0;
			finished = true;

			if (_inStream != null)
			{
				_matchFinder.Init(_inStream);
				_needReleaseMFStream = true;
				_inStream = null;
			}

			if (_finished)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -