[fpc-pascal] LZMA Algorithm fails on 64bit

Matthias Klumpp matthias at nlinux.org
Mon Jan 25 14:27:00 CET 2010


> The stream is compressed with 32 bits version ? Or are the 64 bits
> compressed files the ones that fail to be decompressed in 64 bits also
> ?
I cpmpressed a stream with the 64bits version. I can uncompress it
successfully on 32bit, but not on 64bit.
I haven't tried to decompress 32bit compressed files under 64bit, but
decompressing files compressed under 64bit does not work under 64bit, but
on 32bit.

> So the question a 32 bits compressed LZMA can be decompressed with 32
> bits "decode", and the same stream decompressed with the 64 bits
> version ?
I'll try, but I think it won't work.

I included the Decoder function at the end of this file...

##################################################

function TLZMADecoder.Code(const
inStream,outStream:TStream;outSize:int64):boolean;
var state,rep0,rep1,rep2,rep3:Int64;
    nowPos64:Int64;
    prevByte:byte;
    posState:int64;
    decoder2:TLZMADecoder2;
    len,distance,posSlot,numDirectBits:Int64;
    lpos:int64;
    progint:int64;
begin
DoProgress(LPAMax,outSize);
m_RangeDecoder.SetStream(inStream);
m_OutWindow.SetStream(outStream);
self.Init;

state := ULZMABase.StateInit;
rep0 := 0; rep1 := 0; rep2 := 0; rep3 := 0;

nowPos64 := 0;
prevByte := 0;
progint:=outsize div CodeProgressInterval;
lpos:=progint;
while (outSize < 0) or (nowPos64 < outSize) do
begin
      if (nowPos64 >=lpos) then begin
         DoProgress(LPAPos,nowPos64);
         lpos:=lpos+progint;
         end;
      posState := nowPos64 and m_PosStateMask;
      if (m_RangeDecoder.DecodeBit(m_IsMatchDecoders, (state shl
ULZMABase.kNumPosStatesBitsMax) + posState) = 0) then
      begin
         decoder2 := m_LiteralDecoder.GetDecoder(nowPos64, prevByte);
         if not ULZMABase.StateIsCharState(state) then
            prevByte := decoder2.DecodeWithMatchByte(m_RangeDecoder,
m_OutWindow.GetByte(rep0))
            else prevByte := decoder2.DecodeNormal(m_RangeDecoder);
         m_OutWindow.PutByte(prevByte);
         state := ULZMABase.StateUpdateChar(state);
         inc(nowPos64);
         end else
         begin
             if (m_RangeDecoder.DecodeBit(m_IsRepDecoders, state) = 1) then
begin
                len := 0;
                if (m_RangeDecoder.DecodeBit(m_IsRepG0Decoders, state) = 0)
then begin
                   if (m_RangeDecoder.DecodeBit(m_IsRep0LongDecoders,
(state shl ULZMABase.kNumPosStatesBitsMax) + posState) = 0) then
                   begin
                      state := ULZMABase.StateUpdateShortRep(state);
                      len := 1;
                   end;
                   end else
                   begin
                       if m_RangeDecoder.DecodeBit(m_IsRepG1Decoders,
state) = 0 then
                          distance := rep1
                       else
                       begin
                            if (m_RangeDecoder.DecodeBit(m_IsRepG2Decoders,
state) = 0) then
                               distance := rep2
                            else
                            begin
                                 distance := rep3;
                                 rep3 := rep2;
                            end;
                            rep2 := rep1;
                       end;
                       rep1 := rep0;
                       rep0 := distance;
                       end;
                if len = 0 then begin
                   len := m_RepLenDecoder.Decode(m_RangeDecoder, posState)
+ ULZMABase.kMatchMinLen;
                   state := ULZMABase.StateUpdateRep(state);
                   end;
                end else begin
                    rep3 := rep2;
                    rep2 := rep1;
                    rep1 := rep0;
                    len := ULZMABase.kMatchMinLen +
m_LenDecoder.Decode(m_RangeDecoder, posState);
                    state := ULZMABase.StateUpdateMatch(state);
                    posSlot :=
m_PosSlotDecoder[ULZMABase.GetLenToPosState(len)].Decode(m_RangeDecoder);
                    if posSlot >= ULZMABase.kStartPosModelIndex then begin
                       numDirectBits := (posSlot shr 1) - 1;
                       rep0 := ((2 or (posSlot and 1)) shl numDirectBits);
                       if posSlot < ULZMABase.kEndPosModelIndex then
                          rep0 := rep0 +
UBitTreeDecoder.ReverseDecode(m_PosDecoders,
                                   rep0 - posSlot - 1, m_RangeDecoder,
numDirectBits)
                          else
                          begin
                               rep0 := rep0 +
(m_RangeDecoder.DecodeDirectBits(
                                        numDirectBits -
ULZMABase.kNumAlignBits) shl ULZMABase.kNumAlignBits);
                               rep0 := rep0 +
m_PosAlignDecoder.ReverseDecode(m_RangeDecoder);
                               if rep0 < 0 then
                               begin
                                  if rep0 = -1 then
                                     break;
                                  result:=false;
                                  exit;
                               end;
                          end;
                       end else rep0 := posSlot;
                    end;
      if (rep0 >= nowPos64) or (rep0 >= m_DictionarySizeCheck) then
      begin
         m_OutWindow.Flush();
         result:=false;
         exit;
      end;
      m_OutWindow.CopyBlock(rep0, len);
      nowPos64 := nowPos64 + len;
      prevByte := m_OutWindow.GetByte(0);
      end;
end;
m_OutWindow.Flush();
m_OutWindow.ReleaseStream();
m_RangeDecoder.ReleaseStream();
DoProgress(LPAPos,nowPos64);
result:=true;
end;



More information about the fpc-pascal mailing list