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

📄 ulzmaencoder.pas

📁 Pascal lzma 算法实现,可以直接在delphi中使用,Delphi 2007 是用这个东西发包的
💻 PAS
📖 第 1 页 / 共 4 页
字号:
                 optimum.Prev2 := false;
                 end;//if curandlenprice
              end;//none
            end;//if lentest
         end;//if not nextischar and ...

      startLen := 2; // speed optimization

      for repIndex := 0 to ULZMABase.kNumRepDistances -1 do begin
          lenTest := _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes);
          if lenTest < 2 then
             continue;
          lenTestTemp := lenTest;
          repeat
            while lenEnd < cur + lenTest do begin
                  inc(lenEnd);
                  _optimum[lenEnd].Price := kIfinityPrice;
                  end;//while lenEnd
            curAndLenPrice := repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState);
            optimum := _optimum[cur + lenTest];
            if curAndLenPrice < optimum.Price then begin
               optimum.Price := curAndLenPrice;
               optimum.PosPrev := cur;
               optimum.BackPrev := repIndex;
               optimum.Prev1IsChar := false;
               end;//if curandlen
            dec(lenTest);
            until not (lenTest >= 2);
          lenTest := lenTestTemp;

          if repIndex = 0 then
             startLen := lenTest + 1;

          // if (_maxMode)
          if lenTest < numAvailableBytesFull then begin
             t := min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
             lenTest2 := _matchFinder.GetMatchLen(lenTest, reps[repIndex], t);
             if lenTest2 >= 2 then begin
                state2 := ULZMABase.StateUpdateRep(state);

                posStateNext := (position + lenTest) and _posStateMask;
                curAndLenCharPrice :=
                   repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) +
                   RangeEncoder.GetPrice0(_isMatch[(state2 shl ULZMABase.kNumPosStatesBitsMax) + posStateNext]) +
                   _literalEncoder.GetSubCoder(position + lenTest,
                   _matchFinder.GetIndexByte(lenTest - 1 - 1)).GetPrice(true,
                   _matchFinder.GetIndexByte(lenTest - 1 - (reps[repIndex] + 1)),
                   _matchFinder.GetIndexByte(lenTest - 1));
                state2 := ULZMABase.StateUpdateChar(state2);
                posStateNext := (position + lenTest + 1) and _posStateMask;
                nextMatchPrice := curAndLenCharPrice + RangeEncoder.GetPrice1(_isMatch[(state2 shl ULZMABase.kNumPosStatesBitsMax) + posStateNext]);
                nextRepMatchPrice := nextMatchPrice + RangeEncoder.GetPrice1(_isRep[state2]);

                // for(; lenTest2 >= 2; lenTest2--)
                begin
                  offset := lenTest + 1 + lenTest2;
                  while lenEnd < cur + offset do begin
                        inc(lenEnd);
                        _optimum[lenEnd].Price := kIfinityPrice;
                        end;//while lenEnd
                  curAndLenPrice := nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
                  optimum := _optimum[cur + offset];
                  if curAndLenPrice < optimum.Price then begin
                     optimum.Price := curAndLenPrice;
                     optimum.PosPrev := cur + lenTest + 1;
                     optimum.BackPrev := 0;
                     optimum.Prev1IsChar := true;
                     optimum.Prev2 := true;
                     optimum.PosPrev2 := cur;
                     optimum.BackPrev2 := repIndex;
                     end;//if curAndLenPrice < optimum.Price
                  end;//none
                end;//if lenTest2 >= 2
             end;//if lenTest < numAvailableBytesFull
          end;//for repIndex

      if newLen > numAvailableBytes then begin
         newLen := numAvailableBytes;
         numDistancePairs := 0;
         while newLen > _matchDistances[numDistancePairs] do
               numDistancePairs := numDistancePairs + 2;
         _matchDistances[numDistancePairs] := newLen;
         numDistancePairs := numDistancePairs + 2;
         end;//if newLen > numAvailableBytes
      if newLen >= startLen then begin
         normalMatchPrice := matchPrice + RangeEncoder.GetPrice0(_isRep[state]);
         while lenEnd < cur + newLen do begin
               inc(lenEnd);
               _optimum[lenEnd].Price := kIfinityPrice;
               end;//while lenEnd

         offs := 0;
         while startLen > _matchDistances[offs] do
               offs := offs + 2;

         lenTest := startLen;
         while (true) do begin
               curBack := _matchDistances[offs + 1];
               curAndLenPrice := normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState);
               optimum := _optimum[cur + lenTest];
               if curAndLenPrice < optimum.Price then begin
                  optimum.Price := curAndLenPrice;
                  optimum.PosPrev := cur;
                  optimum.BackPrev := curBack + ULZMABase.kNumRepDistances;
                  optimum.Prev1IsChar := false;
                  end;//if curAndLenPrice < optimum.Price

               if lenTest = _matchDistances[offs] then begin
                  if lenTest < numAvailableBytesFull then begin
                     t := min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
                     lenTest2 := _matchFinder.GetMatchLen(lenTest, curBack, t);
                     if lenTest2 >= 2 then begin
                        state2 := ULZMABase.StateUpdateMatch(state);

                        posStateNext := (position + lenTest) and _posStateMask;
                        curAndLenCharPrice := curAndLenPrice +
                           RangeEncoder.GetPrice0(_isMatch[(state2 shl ULZMABase.kNumPosStatesBitsMax) + posStateNext]) +
                           _literalEncoder.GetSubCoder(position + lenTest,
                           _matchFinder.GetIndexByte(lenTest - 1 - 1)).
                           GetPrice(true,
                           _matchFinder.GetIndexByte(lenTest - (curBack + 1) - 1),
                           _matchFinder.GetIndexByte(lenTest - 1));
                        state2 := ULZMABase.StateUpdateChar(state2);
                        posStateNext := (position + lenTest + 1) and _posStateMask;
                        nextMatchPrice := curAndLenCharPrice + RangeEncoder.GetPrice1(_isMatch[(state2 shl ULZMABase.kNumPosStatesBitsMax) + posStateNext]);
                        nextRepMatchPrice := nextMatchPrice + RangeEncoder.GetPrice1(_isRep[state2]);

                        offset := lenTest + 1 + lenTest2;
                        while lenEnd < cur + offset do begin
                              inc(lenEnd);
                              _optimum[lenEnd].Price := kIfinityPrice;
                              end;//while lenEnd
                        curAndLenPrice := nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
                        optimum := _optimum[cur + offset];
                        if curAndLenPrice < optimum.Price then begin
                           optimum.Price := curAndLenPrice;
                           optimum.PosPrev := cur + lenTest + 1;
                           optimum.BackPrev := 0;
                           optimum.Prev1IsChar := true;
                           optimum.Prev2 := true;
                           optimum.PosPrev2 := cur;
                           optimum.BackPrev2 := curBack + ULZMABase.kNumRepDistances;
                           end;//if curAndLenPrice < optimum.Price
                        end;//if lenTest2 >= 2
                     end;//lenTest < numAvailableBytesFull
                  offs :=offs + 2;
                  if offs = numDistancePairs then
                     break;
                  end;//if lenTest = _matchDistances[offs]
               inc(lenTest);
               end;//while(true)
         end;//if newLen >= startLen
      end;//while (true)
end;

function TLZMAEncoder.ChangePair(const smallDist, bigDist:integer):boolean;
var kDif:integer;
begin
kDif := 7;
result:= (smallDist < (1 shl (32 - kDif))) and (bigDist >= (smallDist shl kDif));
end;

procedure TLZMAEncoder.WriteEndMarker(const posState:integer);
var len,posSlot,lenToPosState,footerBits,posReduced:integer;
begin
if not _writeEndMark then
   exit;

_rangeEncoder.Encode(_isMatch, (_state shl ULZMABase.kNumPosStatesBitsMax) + posState, 1);
_rangeEncoder.Encode(_isRep, _state, 0);
_state := ULZMABase.StateUpdateMatch(_state);
len := ULZMABase.kMatchMinLen;
_lenEncoder.Encode(_rangeEncoder, len - ULZMABase.kMatchMinLen, posState);
posSlot := (1 shl ULZMABase.kNumPosSlotBits) - 1;
lenToPosState := ULZMABase.GetLenToPosState(len);
_posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
footerBits := 30;
posReduced := (1 shl footerBits) - 1;
_rangeEncoder.EncodeDirectBits(posReduced shr ULZMABase.kNumAlignBits, footerBits - ULZMABase.kNumAlignBits);
_posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced and ULZMABase.kAlignMask);
end;

procedure TLZMAEncoder.Flush(const nowPos:integer);
begin
ReleaseMFStream;
WriteEndMarker(nowPos and _posStateMask);
_rangeEncoder.FlushData();
_rangeEncoder.FlushStream();
end;

procedure TLZMAEncoder.CodeOneBlock(var inSize,outSize:int64;var finished:boolean);
var progressPosValuePrev:int64;
    posState,len,pos,complexState,distance,i,posSlot,lenToPosState:integer;
    footerBits,baseVal,posReduced:integer;
    curByte,matchByte:byte;
    subcoder:TLZMAEncoder2;
begin
inSize := 0;
outSize := 0;
finished := true;

if _inStream <>nil then begin
   _matchFinder.SetStream(_inStream);
   _matchFinder.Init;
   _needReleaseMFStream := true;
   _inStream := nil;
   end;

if _finished then
   exit;
_finished := true;

progressPosValuePrev := nowPos64;
if nowPos64 = 0 then begin
   if _matchFinder.GetNumAvailableBytes = 0 then begin
      Flush(nowPos64);
      exit;
      end;

   ReadMatchDistances;
   posState := integer(nowPos64) and _posStateMask;
   _rangeEncoder.Encode(_isMatch, (_state shl ULZMABase.kNumPosStatesBitsMax) + posState, 0);
   _state := ULZMABase.StateUpdateChar(_state);
   curByte := _matchFinder.GetIndexByte(0 - _additionalOffset);
   _literalEncoder.GetSubCoder(integer(nowPos64), _previousByte).Encode(_rangeEncoder, curByte);
   _previousByte := curByte;
   dec(_additionalOffset);
   inc(nowPos64);
   end;
if _matchFinder.GetNumAvailableBytes = 0 then begin
   Flush(integer(nowPos64));
   exit;
   end;
while true do begin
      len := GetOptimum(integer(nowPos64));
      pos := backRes;
      posState := integer(nowPos64) and _posStateMask;
      complexState := (_state shl ULZMABase.kNumPosStatesBitsMax) + posState;
      if (len = 1) and (pos = -1) then begin
         _rangeEncoder.Encode(_isMatch, complexState, 0);
         curByte := _matchFinder.GetIndexByte(0 - _additionalOffset);
         subCoder := _literalEncoder.GetSubCoder(integer(nowPos64), _previousByte);
         if not ULZMABase.StateIsCharState(_state) then begin
            matchByte := _matchFinder.GetIndexByte(0 - _repDistances[0] - 1 - _additionalOffset);
            subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte);
            end else subCoder.Encode(_rangeEncoder, curByte);
         _previousByte := curByte;
         _state := ULZMABase.StateUpdateChar(_state);
         end else begin
             _rangeEncoder.Encode(_isMatch, complexState, 1);
             if pos < ULZMABase.kNumRepDistances then begin
                _rangeEncoder.Encode(_isRep, _state, 1);
                if pos = 0 then begin
                   _rangeEncoder.Encode(_isRepG0, _state, 0);
                   if len = 1 then
                      _rangeEncoder.Encode(_isRep0Long, complexState, 0)
                      else _rangeEncoder.Encode(_isRep0Long, complexState, 1);
                   end else begin
                       _rangeEncoder.Encode(_isRepG0, _state, 1);
                       if pos = 1 then
                          _rangeEncoder.Encode(_isRepG1, _state, 0)
                          else begin
                               _rangeEncoder.Encode(_isRepG1, _state, 1);
                               _rangeEncoder.Encode(_isRepG2, _state, pos - 2);
                               end;
                       end;
                if len = 1 then
                   _state := ULZMABase.StateUpdateShortRep(_state)
                   else begin
                        _repMatchLenEncoder.Encode(_rangeEncoder, len - ULZMABase.kMatchMinLen, posState);
                        _state := ULZMABase.StateUpdateRep(_state);
                        end;
                distance := _repDistances[pos];
                if pos <> 0 then begin
                   for i := pos downto 1 do
                       _repDistances[i] := _repDistances[i - 1];
                   _repDistances[0] := distance;
                   end;
                end else begin
                    _rangeEncoder.Encode(_isRep, _state, 0);
                    _state := ULZMABase.StateUpdateMatch(_state);
                    _lenEncoder.Encode(_rangeEncoder, len - ULZMABase.kMatchMinLen, posState);
                    pos := pos - ULZMABase.kNumRepDistances;
                    posSlot := GetPosSlot(pos);
                    lenToPosState := ULZMABase.GetLenToPosState(len);
                    _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);

                    if posSlot >= ULZMABase.kStartPosModelIndex then begin
                       footerBits := integer((posSlot shr 1) - 1);
                       baseVal := ((2 or (posSlot and 1)) shl footerBits);
                       posReduced := pos - baseVal;

                       if posSlot < ULZMABase.kEndPosModelIndex then
                          UBitTreeEncoder.ReverseEncode(_posEncoders,
                              baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced)
                          else begin
                               _rangeEncoder.EncodeDirectBits(posReduced shr ULZMABase.kNumAlignBits, footerBits - ULZMABase.kNumAlignBits);
                               _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced and ULZMABase.kAlignMask);
                               inc(_alignPriceCount);
                               end;
                       end;
                    distance := pos;
                    for i := ULZMABase.kNumRepDistances - 1 downto 1 do
                        _repDistances[i] := _repDistances[i - 1];
                    _repDistances[0] := distance;
                    inc(_matchPriceCount);
                    end;
             _previousByte := _matchFinder.GetIndexByte(len - 1 - _additionalOffset);
      end;
_additionalOffset := _additionalOffset - len;
nowPos64 := nowPos64 + len;
if _additionalOffset = 0 then begin
   // if (!_fastMode)
   if _matchPriceCount >= (1 shl 7) then
      FillDistancesPrices;
   if _alignPriceCount >= ULZMABase.kAlignTableSize then
      FillAlignPrices;
   inSize := nowPos64;
   outSize := _rangeEncoder.GetProcessedSizeAdd;
   if _matchFinder.GetNumAvailableBytes = 0 then begin
      Flush(integer(nowPos64));
      exit;
      end;

if (nowPos64 - progressPosValuePrev >= (1 shl 12)) then begin
   _finished := false;
   finished := false;
   exit;
   end;
end;
end;
end;

procedure TLZMAEncoder.ReleaseMFStream;
begin
if (_matchFinder <>nil) and _needReleaseMFStream then begin
   _matchFinder.ReleaseStream;
   _needReleaseMFStream := false;
   end;
end;

procedure TLZMAEncoder.SetOutStream(const outStream:TStream);
begin
_rangeEncoder.SetStream(outStream);
end;

procedure TLZMAEncoder.ReleaseOutStream;
begin
_rangeEncoder.ReleaseStream;
end;

procedure TLZMAEncoder.ReleaseStreams;
begin
ReleaseMFStream;
ReleaseOutStream;
end;

procedure TLZMAEncoder.SetStreams(const inStream, outStream:TStream;const inSize, outSize:int64);
begin
_inStream := inStream;
_finished := false;
_Create();
SetOutStream(outStream);
Init();

// if (!_fastMode)
FillDistancesPrices;
FillAlignPrices;

_lenEncoder.SetTableSize(_numFastBytes + 1 - ULZMABase.kMatchMinLen);
_lenEncoder.UpdateTables(1 shl _posStateBits);
_repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - ULZMABase.kMatchMinLen);
_repMatchLenEncoder.UpdateTables(1 shl _posStateBits);

nowPos64 := 0;
end;

procedure TLZMAEncoder.Code(const inStream, outStream:TStream;const inSize, outSize:int64);
var lpos:int64;
    progint:int64;

⌨️ 快捷键说明

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