Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/CPP/7zip
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2018-01-30 03:15:34 +0300
committerKornel <kornel@geekhood.net>2018-01-30 03:35:06 +0300
commit866a06f5a0c0ede11979504a318e150030aa7a11 (patch)
treebb8a2795afb445aa46167232254384ed82caf518 /CPP/7zip
parentda28077952faf9e716ed7987b842d31617a10125 (diff)
18.0118.01
Diffstat (limited to 'CPP/7zip')
-rw-r--r--CPP/7zip/Archive/DmgHandler.cpp34
-rw-r--r--CPP/7zip/Archive/PeHandler.cpp26
-rw-r--r--CPP/7zip/Archive/Zip/ZipHandlerOut.cpp28
-rw-r--r--CPP/7zip/Archive/Zip/ZipHeader.h1
-rw-r--r--CPP/7zip/Archive/Zip/ZipIn.h5
-rw-r--r--CPP/7zip/Archive/Zip/ZipItem.cpp6
-rw-r--r--CPP/7zip/Archive/Zip/ZipItem.h7
-rw-r--r--CPP/7zip/Archive/Zip/ZipUpdate.cpp26
-rw-r--r--CPP/7zip/Archive/Zip/ZipUpdate.h10
-rw-r--r--CPP/7zip/Bundles/Format7zF/Arc.mak1
-rw-r--r--CPP/7zip/Bundles/Format7zF/Format7z.dsp18
-rw-r--r--CPP/7zip/Common/InBuffer.cpp28
-rw-r--r--CPP/7zip/Compress/LzOutWindow.h33
-rw-r--r--CPP/7zip/Compress/LzfseDecoder.cpp925
-rw-r--r--CPP/7zip/Compress/LzfseDecoder.h58
-rw-r--r--CPP/7zip/UI/Agent/Agent.cpp9
-rw-r--r--CPP/7zip/UI/Agent/Agent.h6
-rw-r--r--CPP/7zip/UI/Common/ArchiveExtractCallback.cpp100
-rw-r--r--CPP/7zip/UI/Common/ArchiveExtractCallback.h25
-rw-r--r--CPP/7zip/UI/Common/OpenArchive.cpp2
-rw-r--r--CPP/7zip/UI/Common/OpenArchive.h19
-rw-r--r--CPP/7zip/UI/Common/Update.cpp61
22 files changed, 1329 insertions, 99 deletions
diff --git a/CPP/7zip/Archive/DmgHandler.cpp b/CPP/7zip/Archive/DmgHandler.cpp
index 8acbcea6..608ad4c4 100644
--- a/CPP/7zip/Archive/DmgHandler.cpp
+++ b/CPP/7zip/Archive/DmgHandler.cpp
@@ -19,6 +19,7 @@
#include "../Compress/BZip2Decoder.h"
#include "../Compress/CopyCoder.h"
+#include "../Compress/LzfseDecoder.h"
#include "../Compress/ZlibDecoder.h"
#include "Common/OutStreamWithCRC.h"
@@ -121,6 +122,7 @@ enum
METHOD_ADC = 0x80000004,
METHOD_ZLIB = 0x80000005,
METHOD_BZIP2 = 0x80000006,
+ METHOD_LZFSE = 0x80000007,
METHOD_COMMENT = 0x7FFFFFFE, // is used to comment "+beg" and "+end" in extra field.
METHOD_END = 0xFFFFFFFF
};
@@ -276,6 +278,7 @@ void CMethods::GetString(AString &res) const
case METHOD_ADC: s = "ADC"; break;
case METHOD_ZLIB: s = "ZLIB"; break;
case METHOD_BZIP2: s = "BZip2"; break;
+ case METHOD_LZFSE: s = "LZFSE"; break;
default: ConvertUInt32ToString(type, buf); s = buf;
}
res.Add_OptSpaced(s);
@@ -307,6 +310,10 @@ static const CAppleName k_Names[] =
{ true, "hfs", "Apple_HFS" },
{ true, "hfsx", "Apple_HFSX" },
{ true, "ufs", "Apple_UFS" },
+
+ // efi_sys partition is FAT32, but it's not main file. So we use (IsFs = false)
+ { false, "efi_sys", "C12A7328-F81F-11D2-BA4B-00A0C93EC93B" },
+
{ false, "free", "Apple_Free" },
{ false, "ddm", "DDM" },
{ false, NULL, "Apple_partition_map" },
@@ -1247,6 +1254,11 @@ STDMETHODIMP CAdcDecoder::Code(ISequentialInStream *inStream,
}
+
+
+
+
+
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
{
@@ -1292,6 +1304,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CAdcDecoder *adcCoderSpec = new CAdcDecoder();
CMyComPtr<ICompressCoder> adcCoder = adcCoderSpec;
+ NCompress::NLzfse::CDecoder *lzfseCoderSpec = new NCompress::NLzfse::CDecoder();
+ CMyComPtr<ICompressCoder> lzfseCoder = lzfseCoderSpec;
+
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false);
@@ -1419,6 +1434,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
opRes = NExtract::NOperationResult::kDataError;
break;
}
+
+ case METHOD_LZFSE:
+ {
+ res = lzfseCoder->Code(inStream, outStream, &block.PackSize, &block.UnpSize, progress);
+ break;
+ }
default:
opRes = NExtract::NOperationResult::kUnsupportedMethod;
@@ -1490,6 +1511,9 @@ class CInStream:
CAdcDecoder *adcCoderSpec;
CMyComPtr<ICompressCoder> adcCoder;
+ NCompress::NLzfse::CDecoder *lzfseCoderSpec;
+ CMyComPtr<ICompressCoder> lzfseCoder;
+
CBufPtrSeqOutStream *outStreamSpec;
CMyComPtr<ISequentialOutStream> outStream;
@@ -1651,6 +1675,15 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
if (res == S_OK && bzip2CoderSpec->GetInputProcessedSize() != block.PackSize)
res = S_FALSE;
break;
+
+ case METHOD_LZFSE:
+ if (!lzfseCoder)
+ {
+ lzfseCoderSpec = new NCompress::NLzfse::CDecoder();
+ lzfseCoder = lzfseCoderSpec;
+ }
+ res = lzfseCoder->Code(inStream, outStream, &block.PackSize, &block.UnpSize, NULL);
+ break;
default:
return E_FAIL;
@@ -1738,6 +1771,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
case METHOD_ADC:
case METHOD_ZLIB:
case METHOD_BZIP2:
+ case METHOD_LZFSE:
case METHOD_END:
break;
default:
diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp
index 4edaa918..cb0836cc 100644
--- a/CPP/7zip/Archive/PeHandler.cpp
+++ b/CPP/7zip/Archive/PeHandler.cpp
@@ -387,6 +387,10 @@ void CSection::Parse(const Byte *p)
G32(36, Flags);
}
+
+
+// IMAGE_FILE_*
+
static const CUInt32PCharPair g_HeaderCharacts[] =
{
{ 1, "Executable" },
@@ -406,9 +410,7 @@ static const CUInt32PCharPair g_HeaderCharacts[] =
{ 15, "Big-Endian" }
};
-
-
-// IMAGE_DLLCHARACTERISTICS_* constants
+// IMAGE_DLLCHARACTERISTICS_*
static const char * const g_DllCharacts[] =
{
@@ -930,7 +932,9 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidExtension:
if (_header.IsDll())
- prop = _optHeader.IsSybSystem_EFI() ? "efi" : "dll";
+ prop = "dll";
+ else if (_optHeader.IsSybSystem_EFI())
+ prop = "efi";
break;
case kpidBit64: if (_optHeader.Is64Bit()) prop = true; break;
@@ -1137,8 +1141,17 @@ HRESULT CHandler::LoadDebugSections(IInStream *stream, bool &thereIsSection)
return S_OK;
const unsigned kEntrySize = 28;
UInt32 numItems = debugLink.Size / kEntrySize;
- if (numItems * kEntrySize != debugLink.Size || numItems > 16)
+ if (numItems > 16)
return S_FALSE;
+
+ // MAC's EFI file: numItems can be incorrect. Only first CDebugEntry entry is correct.
+ // debugLink.Size = kEntrySize + some_data, pointed by entry[0].
+ if (numItems * kEntrySize != debugLink.Size)
+ {
+ // return S_FALSE;
+ if (numItems > 1)
+ numItems = 1;
+ }
UInt64 pa = 0;
unsigned i;
@@ -2191,6 +2204,9 @@ bool CHeader::ParseCoff(const Byte *p)
for (unsigned i = 0; i < ARRAY_SIZE(g_MachinePairs); i++)
if (Machine == g_MachinePairs[i].Value)
return true;
+ if (Machine == 0)
+ return true;
+
return false;
}
diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
index 8ecf7942..5acbb6d4 100644
--- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
+++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
@@ -136,6 +136,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
thereAreAesUpdates = true;
if (!IntToBool(newProps))
ui.IsDir = inputItem.IsDir();
+ // ui.IsAltStream = inputItem.IsAltStream();
}
if (IntToBool(newProps))
@@ -175,6 +176,33 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
ui.IsDir = (prop.boolVal != VARIANT_FALSE);
}
+ /*
+ {
+ bool isAltStream = false;
+ {
+ NCOM::CPropVariant prop;
+ RINOK(callback->GetProperty(i, kpidIsAltStream, &prop));
+ if (prop.vt == VT_BOOL)
+ isAltStream = (prop.boolVal != VARIANT_FALSE);
+ else if (prop.vt != VT_EMPTY)
+ return E_INVALIDARG;
+ }
+
+ if (isAltStream)
+ {
+ if (ui.IsDir)
+ return E_INVALIDARG;
+ int delim = name.ReverseFind(L':');
+ if (delim >= 0)
+ {
+ name.Delete(delim, 1);
+ name.Insert(delim, UString(k_SpecName_NTFS_STREAM));
+ ui.IsAltStream = true;
+ }
+ }
+ }
+ */
+
{
CPropVariant prop;
RINOK(callback->GetProperty(i, kpidTimeType, &prop));
diff --git a/CPP/7zip/Archive/Zip/ZipHeader.h b/CPP/7zip/Archive/Zip/ZipHeader.h
index 61b4ea4b..5e6f00e4 100644
--- a/CPP/7zip/Archive/Zip/ZipHeader.h
+++ b/CPP/7zip/Archive/Zip/ZipHeader.h
@@ -131,6 +131,7 @@ namespace NFileHeader
const unsigned kDescriptorUsedMask = 1 << 3;
const unsigned kStrongEncrypted = 1 << 6;
const unsigned kUtf8 = 1 << 11;
+ const unsigned kAltStream = 1 << 14;
const unsigned kImplodeDictionarySizeMask = 1 << 1;
const unsigned kImplodeLiteralsOnMask = 1 << 2;
diff --git a/CPP/7zip/Archive/Zip/ZipIn.h b/CPP/7zip/Archive/Zip/ZipIn.h
index a312c36a..e67bce42 100644
--- a/CPP/7zip/Archive/Zip/ZipIn.h
+++ b/CPP/7zip/Archive/Zip/ZipIn.h
@@ -20,10 +20,13 @@ class CItemEx: public CItem
{
public:
UInt32 LocalFullHeaderSize; // including Name and Extra
+ // int ParentOfAltStream; // -1, if not AltStream
bool DescriptorWasRead;
- CItemEx(): DescriptorWasRead(false) {}
+ CItemEx():
+ // ParentOfAltStream(-1),
+ DescriptorWasRead(false) {}
UInt64 GetLocalFullSize() const
{ return LocalFullHeaderSize + GetPackSizeWithDescriptor(); }
diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp
index 885a43cd..5cff1735 100644
--- a/CPP/7zip/Archive/Zip/ZipItem.cpp
+++ b/CPP/7zip/Archive/Zip/ZipItem.cpp
@@ -20,6 +20,12 @@ namespace NZip {
using namespace NFileHeader;
+
+/*
+const char *k_SpecName_NTFS_STREAM = "@@NTFS@STREAM@";
+const char *k_SpecName_MAC_RESOURCE_FORK = "@@MAC@RESOURCE-FORK@";
+*/
+
static const CUInt32PCharPair g_ExtraTypes[] =
{
{ NExtraID::kZip64, "Zip64" },
diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h
index 0cf9bd09..78e3e01c 100644
--- a/CPP/7zip/Archive/Zip/ZipItem.h
+++ b/CPP/7zip/Archive/Zip/ZipItem.h
@@ -14,6 +14,11 @@
namespace NArchive {
namespace NZip {
+/*
+extern const char *k_SpecName_NTFS_STREAM;
+extern const char *k_SpecName_MAC_RESOURCE_FORK;
+*/
+
struct CVersion
{
Byte Version;
@@ -233,6 +238,7 @@ public:
bool IsAesEncrypted() const { return IsEncrypted() && (IsStrongEncrypted() || Method == NFileHeader::NCompressionMethod::kWzAES); }
bool IsLzmaEOS() const { return (Flags & NFileHeader::NFlags::kLzmaEOS) != 0; }
bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; }
+ // bool IsAltStream() const { return (Flags & NFileHeader::NFlags::kAltStream) != 0; }
unsigned GetDeflateLevel() const { return (Flags >> 1) & 3; }
@@ -264,6 +270,7 @@ public:
void ClearFlags() { Flags = 0; }
void SetEncrypted(bool encrypted) { SetFlag(NFileHeader::NFlags::kEncrypted, encrypted); }
void SetUtf8(bool isUtf8) { SetFlag(NFileHeader::NFlags::kUtf8, isUtf8); }
+ // void SetFlag_AltStream(bool isAltStream) { SetFlag(NFileHeader::NFlags::kAltStream, isAltStream); }
void SetDescriptorMode(bool useDescriptor) { SetFlag(NFileHeader::NFlags::kDescriptorUsedMask, useDescriptor); }
UINT GetCodePage() const { return CP_OEMCP; }
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
index 606f7829..2289203b 100644
--- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp
+++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
@@ -75,6 +75,7 @@ static void SetFileHeader(
item.Name = ui.Name;
item.Comment = ui.Comment;
item.SetUtf8(ui.IsUtf8);
+ // item.SetFlag_AltStream(ui.IsAltStream);
item.ExternalAttrib = ui.Attrib;
item.Time = ui.Time;
item.Ntfs_MTime = ui.Ntfs_MTime;
@@ -280,6 +281,7 @@ public:
MY_UNKNOWN_IMP
void Create(IProgress *progress, bool inSizeIsMain);
void SetProgressOffset(UInt64 progressOffset);
+ void SetProgressOffset_NoLock(UInt64 progressOffset);
HRESULT SetRatioInfo(unsigned index, const UInt64 *inSize, const UInt64 *outSize);
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
};
@@ -292,11 +294,16 @@ void CMtProgressMixer2::Create(IProgress *progress, bool inSizeIsMain)
ProgressOffset = InSizes[0] = InSizes[1] = OutSizes[0] = OutSizes[1] = 0;
}
-void CMtProgressMixer2::SetProgressOffset(UInt64 progressOffset)
+void CMtProgressMixer2::SetProgressOffset_NoLock(UInt64 progressOffset)
{
- CriticalSection.Enter();
InSizes[1] = OutSizes[1] = 0;
ProgressOffset = progressOffset;
+}
+
+void CMtProgressMixer2::SetProgressOffset(UInt64 progressOffset)
+{
+ CriticalSection.Enter();
+ SetProgressOffset_NoLock(progressOffset);
CriticalSection.Leave();
}
@@ -384,6 +391,7 @@ static HRESULT UpdateItemOldData(
item.Comment = ui.Comment;
item.Name = ui.Name;
item.SetUtf8(ui.IsUtf8);
+ // item.SetFlag_AltStream(ui.IsAltStream);
item.Time = ui.Time;
item.Ntfs_MTime = ui.Ntfs_MTime;
item.Ntfs_ATime = ui.Ntfs_ATime;
@@ -602,8 +610,11 @@ static HRESULT Update2St(
lps->InSize = unpackSizeTotal;
lps->OutSize = packSizeTotal;
RINOK(lps->SetCur());
+
archive.WriteCentralDir(items, comment);
- return S_OK;
+
+ lps->ProgressOffset += kCentralHeaderSize * updateItems.Size() + 1;
+ return lps->SetCur();
}
@@ -897,7 +908,7 @@ static HRESULT Update2(
{
complexity += ui.Size;
complexity += kLocalHeaderSize;
- mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity);
+ mtProgressMixerSpec->Mixer2->SetProgressOffset_NoLock(complexity);
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
memRef2.Skip = true;
continue;
@@ -1107,8 +1118,13 @@ static HRESULT Update2(
}
RINOK(mtCompressProgressMixer.SetRatioInfo(0, NULL, NULL));
+
archive.WriteCentralDir(items, comment);
- return S_OK;
+
+ complexity += kCentralHeaderSize * updateItems.Size() + 1;
+ mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity);
+ return mtCompressProgressMixer.SetRatioInfo(0, NULL, NULL);
+
#endif
}
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.h b/CPP/7zip/Archive/Zip/ZipUpdate.h
index d5fda855..8785ae60 100644
--- a/CPP/7zip/Archive/Zip/ZipUpdate.h
+++ b/CPP/7zip/Archive/Zip/ZipUpdate.h
@@ -32,6 +32,7 @@ struct CUpdateItem
bool IsDir;
bool NtfsTimeIsDefined;
bool IsUtf8;
+ // bool IsAltStream;
int IndexInArc;
int IndexInClient;
UInt32 Attrib;
@@ -50,12 +51,19 @@ struct CUpdateItem
IsDir = false;
NtfsTimeIsDefined = false;
IsUtf8 = false;
+ // IsAltStream = false;
Size = 0;
Name.Empty();
Comment.Free();
}
- CUpdateItem(): NtfsTimeIsDefined(false), IsUtf8(false), Size(0) {}
+ CUpdateItem():
+ IsDir(false),
+ NtfsTimeIsDefined(false),
+ IsUtf8(false),
+ // IsAltStream(false),
+ Size(0)
+ {}
};
HRESULT Update(
diff --git a/CPP/7zip/Bundles/Format7zF/Arc.mak b/CPP/7zip/Bundles/Format7zF/Arc.mak
index 97f6596e..28dce218 100644
--- a/CPP/7zip/Bundles/Format7zF/Arc.mak
+++ b/CPP/7zip/Bundles/Format7zF/Arc.mak
@@ -198,6 +198,7 @@ COMPRESS_OBJS = \
$O\DeflateRegister.obj \
$O\DeltaFilter.obj \
$O\ImplodeDecoder.obj \
+ $O\LzfseDecoder.obj \
$O\LzhDecoder.obj \
$O\Lzma2Decoder.obj \
$O\Lzma2Encoder.obj \
diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsp b/CPP/7zip/Bundles/Format7zF/Format7z.dsp
index f2a8fcc8..7b1b233e 100644
--- a/CPP/7zip/Bundles/Format7zF/Format7z.dsp
+++ b/CPP/7zip/Bundles/Format7zF/Format7z.dsp
@@ -961,6 +961,24 @@ SOURCE=..\..\Compress\HuffmanDecoder.h
# End Source File
# Begin Source File
+SOURCE=..\..\Compress\LzfseDecoder.cpp
+
+!IF "$(CFG)" == "7z - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "7z - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LzfseDecoder.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Compress\LzhDecoder.cpp
# End Source File
# Begin Source File
diff --git a/CPP/7zip/Common/InBuffer.cpp b/CPP/7zip/Common/InBuffer.cpp
index 133d95b3..d1bc9b9a 100644
--- a/CPP/7zip/Common/InBuffer.cpp
+++ b/CPP/7zip/Common/InBuffer.cpp
@@ -97,6 +97,33 @@ Byte CInBufferBase::ReadByte_FromNewBlock()
size_t CInBufferBase::ReadBytes(Byte *buf, size_t size)
{
+ size_t num = 0;
+ for (;;)
+ {
+ const size_t rem = _bufLim - _buf;
+ if (size <= rem)
+ {
+ if (size != 0)
+ {
+ memcpy(buf, _buf, size);
+ _buf += size;
+ num += size;
+ }
+ return num;
+ }
+ if (rem != 0)
+ {
+ memcpy(buf, _buf, rem);
+ _buf += rem;
+ buf += rem;
+ num += rem;
+ size -= rem;
+ }
+ if (!ReadBlock())
+ return num;
+ }
+
+ /*
if ((size_t)(_bufLim - _buf) >= size)
{
const Byte *src = _buf;
@@ -113,6 +140,7 @@ size_t CInBufferBase::ReadBytes(Byte *buf, size_t size)
buf[i] = *_buf++;
}
return size;
+ */
}
size_t CInBufferBase::Skip(size_t size)
diff --git a/CPP/7zip/Compress/LzOutWindow.h b/CPP/7zip/Compress/LzOutWindow.h
index 5591744d..30ac334f 100644
--- a/CPP/7zip/Compress/LzOutWindow.h
+++ b/CPP/7zip/Compress/LzOutWindow.h
@@ -56,6 +56,39 @@ public:
if (pos == _limitPos)
FlushWithCheck();
}
+
+ void PutBytes(const Byte *data, UInt32 size)
+ {
+ if (size == 0)
+ return;
+ UInt32 pos = _pos;
+ Byte *buf = _buf;
+ buf[pos++] = *data++;
+ size--;
+ for (;;)
+ {
+ UInt32 limitPos = _limitPos;
+ UInt32 rem = limitPos - pos;
+ if (rem == 0)
+ {
+ _pos = pos;
+ FlushWithCheck();
+ pos = _pos;
+ continue;
+ }
+
+ if (size == 0)
+ break;
+
+ if (rem > size)
+ rem = size;
+ size -= rem;
+ do
+ buf[pos++] = *data++;
+ while (--rem);
+ }
+ _pos = pos;
+ }
Byte GetByte(UInt32 distance) const
{
diff --git a/CPP/7zip/Compress/LzfseDecoder.cpp b/CPP/7zip/Compress/LzfseDecoder.cpp
new file mode 100644
index 00000000..41c7445a
--- /dev/null
+++ b/CPP/7zip/Compress/LzfseDecoder.cpp
@@ -0,0 +1,925 @@
+// LzfseDecoder.cpp
+
+/*
+This code implements LZFSE data decompressing.
+The code from "LZFSE compression library" was used.
+
+2018 : Igor Pavlov : BSD 3-clause License : the code in this file
+2015-2017 : Apple Inc : BSD 3-clause License : original "LZFSE compression library" code
+
+The code in the "LZFSE compression library" is licensed under the "BSD 3-clause License":
+----
+Copyright (c) 2015-2016, Apple Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+----
+*/
+
+#include "StdAfx.h"
+
+// #define SHOW_DEBUG_INFO
+
+#ifdef SHOW_DEBUG_INFO
+#include <stdio.h>
+#endif
+
+#ifdef SHOW_DEBUG_INFO
+#define PRF(x) x
+#else
+#define PRF(x)
+#endif
+
+#include "../../../C/CpuArch.h"
+
+#include "LzfseDecoder.h"
+
+namespace NCompress {
+namespace NLzfse {
+
+static const Byte kSignature_LZFSE_V1 = 0x31; // '1'
+static const Byte kSignature_LZFSE_V2 = 0x32; // '2'
+
+
+HRESULT CDecoder::GetUInt32(UInt32 &val)
+{
+ Byte b[4];
+ for (unsigned i = 0; i < 4; i++)
+ if (!m_InStream.ReadByte(b[i]))
+ return S_FALSE;
+ val = GetUi32(b);
+ return S_OK;
+}
+
+
+
+HRESULT CDecoder::DecodeUncompressed(UInt32 unpackSize)
+{
+ PRF(printf("\nUncompressed %7u\n", unpackSize));
+
+ const unsigned kBufSize = 1 << 8;
+ Byte buf[kBufSize];
+ for (;;)
+ {
+ if (unpackSize == 0)
+ return S_OK;
+ UInt32 cur = unpackSize;
+ if (cur > kBufSize)
+ cur = kBufSize;
+ UInt32 cur2 = (UInt32)m_InStream.ReadBytes(buf, cur);
+ m_OutWindowStream.PutBytes(buf, cur2);
+ if (cur != cur2)
+ return S_FALSE;
+ }
+}
+
+
+
+HRESULT CDecoder::DecodeLzvn(UInt32 unpackSize)
+{
+ UInt32 packSize;
+ RINOK(GetUInt32(packSize));
+
+ PRF(printf("\nLZVN %7u %7u", unpackSize, packSize));
+
+ UInt32 D = 0;
+
+ for (;;)
+ {
+ if (packSize == 0)
+ return S_FALSE;
+ Byte b;
+ if (!m_InStream.ReadByte(b))
+ return S_FALSE;
+ packSize--;
+
+ UInt32 M;
+ UInt32 L;
+
+ if (b >= 0xE0)
+ {
+ /*
+ large L - 11100000 LLLLLLLL <LITERALS>
+ small L - 1110LLLL <LITERALS>
+
+ large Rep - 11110000 MMMMMMMM
+ small Rep - 1111MMMM
+ */
+
+ M = b & 0xF;
+ if (M == 0)
+ {
+ if (packSize == 0)
+ return S_FALSE;
+ Byte b1;
+ if (!m_InStream.ReadByte(b1))
+ return S_FALSE;
+ packSize--;
+ M = (UInt32)b1 + 16;
+ }
+ L = 0;
+ if ((b & 0x10) == 0)
+ {
+ // Literals only
+ L = M;
+ M = 0;
+ }
+ }
+
+ // ERROR codes
+ else if ((b & 0xF0) == 0x70) // 0111xxxx
+ return S_FALSE;
+ else if ((b & 0xF0) == 0xD0) // 1101xxxx
+ return S_FALSE;
+
+ else
+ {
+ if ((b & 0xE0) == 0xA0)
+ {
+ // medium - 101LLMMM DDDDDDMM DDDDDDDD <LITERALS>
+ if (packSize < 2)
+ return S_FALSE;
+ Byte b1;
+ if (!m_InStream.ReadByte(b1))
+ return S_FALSE;
+ packSize--;
+
+ Byte b2;
+ if (!m_InStream.ReadByte(b2))
+ return S_FALSE;
+ packSize--;
+ L = (((UInt32)b >> 3) & 3);
+ M = (((UInt32)b & 7) << 2) + (b1 & 3);
+ D = ((UInt32)b1 >> 2) + ((UInt32)b2 << 6);
+ }
+ else
+ {
+ L = (UInt32)b >> 6;
+ M = ((UInt32)b >> 3) & 7;
+ if ((b & 0x7) == 6)
+ {
+ // REP - LLMMM110 <LITERALS>
+ if (L == 0)
+ {
+ // spec
+ if (M == 0)
+ break; // EOS
+ if (M <= 2)
+ continue; // NOP
+ return S_FALSE; // UNDEFINED
+ }
+ }
+ else
+ {
+ if (packSize == 0)
+ return S_FALSE;
+ Byte b1;
+ if (!m_InStream.ReadByte(b1))
+ return S_FALSE;
+ packSize--;
+
+ // large - LLMMM111 DDDDDDDD DDDDDDDD <LITERALS>
+ // small - LLMMMDDD DDDDDDDD <LITERALS>
+ D = ((UInt32)b & 7);
+ if (D == 7)
+ {
+ if (packSize == 0)
+ return S_FALSE;
+ Byte b2;
+ if (!m_InStream.ReadByte(b2))
+ return S_FALSE;
+ packSize--;
+ D = b2;
+ }
+ D = (D << 8) + b1;
+ }
+ }
+
+ M += 3;
+ }
+ {
+ for (unsigned i = 0; i < L; i++)
+ {
+ if (packSize == 0 || unpackSize == 0)
+ return S_FALSE;
+ Byte b1;
+ if (!m_InStream.ReadByte(b1))
+ return S_FALSE;
+ packSize--;
+ m_OutWindowStream.PutByte(b1);
+ unpackSize--;
+ }
+ }
+
+ if (M != 0)
+ {
+ if (unpackSize == 0 || D == 0)
+ return S_FALSE;
+ unsigned cur = M;
+ if (cur > unpackSize)
+ cur = (unsigned)unpackSize;
+ if (!m_OutWindowStream.CopyBlock(D - 1, cur))
+ return S_FALSE;
+ unpackSize -= cur;
+ if (cur != M)
+ return S_FALSE;
+ }
+ }
+
+ if (unpackSize != 0)
+ return S_FALSE;
+
+ // LZVN encoder writes 7 additional zero bytes
+ if (packSize != 7)
+ return S_FALSE;
+ do
+ {
+ Byte b;
+ if (!m_InStream.ReadByte(b))
+ return S_FALSE;
+ packSize--;
+ if (b != 0)
+ return S_FALSE;
+ }
+ while (packSize != 0);
+
+ return S_OK;
+}
+
+
+
+// ---------- LZFSE ----------
+
+#define MATCHES_PER_BLOCK 10000
+#define LITERALS_PER_BLOCK (4 * MATCHES_PER_BLOCK)
+
+#define NUM_L_SYMBOLS 20
+#define NUM_M_SYMBOLS 20
+#define NUM_D_SYMBOLS 64
+#define NUM_LIT_SYMBOLS 256
+
+#define NUM_SYMBOLS ( \
+ NUM_L_SYMBOLS + \
+ NUM_M_SYMBOLS + \
+ NUM_D_SYMBOLS + \
+ NUM_LIT_SYMBOLS)
+
+#define NUM_L_STATES (1 << 6)
+#define NUM_M_STATES (1 << 6)
+#define NUM_D_STATES (1 << 8)
+#define NUM_LIT_STATES (1 << 10)
+
+
+typedef UInt32 CFseState;
+
+
+static UInt32 SumFreqs(const UInt16 *freqs, unsigned num)
+{
+ UInt32 sum = 0;
+ for (unsigned i = 0; i < num; i++)
+ sum += (UInt32)freqs[i];
+ return sum;
+}
+
+
+static MY_FORCE_INLINE unsigned CountZeroBits(UInt32 val, UInt32 mask)
+{
+ for (unsigned i = 0;;)
+ {
+ if (val & mask)
+ return i;
+ i++;
+ mask >>= 1;
+ }
+}
+
+
+static MY_FORCE_INLINE void InitLitTable(const UInt16 *freqs, UInt32 *table)
+{
+ for (unsigned i = 0; i < NUM_LIT_SYMBOLS; i++)
+ {
+ unsigned f = freqs[i];
+ if (f == 0)
+ continue;
+
+ // 0 < f <= numStates
+ // 0 <= k <= numStatesLog
+ // numStates <= (f<<k) < numStates * 2
+ // 0 < j0 <= f
+ // (f + j0) = next_power_of_2 for f
+ unsigned k = CountZeroBits(f, NUM_LIT_STATES);
+ unsigned j0 = (((unsigned)NUM_LIT_STATES * 2) >> k) - f;
+
+ /*
+ CEntry
+ {
+ Byte k;
+ Byte symbol;
+ UInt16 delta;
+ };
+ */
+
+ UInt32 e = ((UInt32)i << 8) + k;
+ k += 16;
+ UInt32 d = e + ((UInt32)f << k) - ((UInt32)NUM_LIT_STATES << 16);
+ UInt32 step = (UInt32)1 << k;
+
+ unsigned j = 0;
+ do
+ {
+ *table++ = d;
+ d += step;
+ }
+ while (++j < j0);
+
+ e--;
+ step >>= 1;
+
+ for (j = j0; j < f; j++)
+ {
+ *table++ = e;
+ e += step;
+ }
+ }
+}
+
+
+typedef struct
+{
+ Byte totalBits;
+ Byte extraBits;
+ UInt16 delta;
+ UInt32 vbase;
+} CExtraEntry;
+
+
+static void InitExtraDecoderTable(unsigned numStates,
+ unsigned numSymbols,
+ const UInt16 *freqs,
+ const Byte *vbits,
+ CExtraEntry *table)
+{
+ UInt32 vbase = 0;
+
+ for (unsigned i = 0; i < numSymbols; i++)
+ {
+ unsigned f = freqs[i];
+ unsigned extraBits = vbits[i];
+
+ if (f != 0)
+ {
+ unsigned k = CountZeroBits(f, numStates);
+ unsigned j0 = ((2 * numStates) >> k) - f;
+
+ unsigned j = 0;
+ do
+ {
+ CExtraEntry *e = table++;
+ e->totalBits = (Byte)(k + extraBits);
+ e->extraBits = (Byte)extraBits;
+ e->delta = (UInt16)(((f + j) << k) - numStates);
+ e->vbase = vbase;
+ }
+ while (++j < j0);
+
+ f -= j0;
+ k--;
+
+ for (j = 0; j < f; j++)
+ {
+ CExtraEntry *e = table++;
+ e->totalBits = (Byte)(k + extraBits);
+ e->extraBits = (Byte)extraBits;
+ e->delta = (UInt16)(j << k);
+ e->vbase = vbase;
+ }
+ }
+
+ vbase += ((UInt32)1 << extraBits);
+ }
+}
+
+
+static const Byte k_L_extra[NUM_L_SYMBOLS] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 5, 8
+};
+
+static const Byte k_M_extra[NUM_M_SYMBOLS] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11
+};
+
+static const Byte k_D_extra[NUM_D_SYMBOLS] =
+{
+ 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
+ 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11,
+ 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15
+};
+
+
+
+// ---------- CBitStream ----------
+
+typedef struct
+{
+ UInt32 accum;
+ unsigned numBits; // [0, 31] - Number of valid bits in (accum), other bits are 0
+} CBitStream;
+
+
+static MY_FORCE_INLINE int FseInStream_Init(CBitStream *s,
+ int n, // [-7, 0], (-n == number_of_unused_bits) in last byte
+ const Byte **pbuf)
+{
+ *pbuf -= 4;
+ s->accum = GetUi32(*pbuf);
+ if (n)
+ {
+ s->numBits = n + 32;
+ if ((s->accum >> s->numBits) != 0)
+ return -1; // ERROR, encoder should have zeroed the upper bits
+ }
+ else
+ {
+ *pbuf += 1;
+ s->accum >>= 8;
+ s->numBits = 24;
+ }
+ return 0; // OK
+}
+
+
+// 0 <= numBits < 32
+#define mask31(x, numBits) ((x) & (((UInt32)1 << (numBits)) - 1))
+
+#define FseInStream_FLUSH \
+ { unsigned nbits = (31 - in.numBits) & -8; \
+ if (nbits) { \
+ buf -= (nbits >> 3); \
+ if (buf < buf_check) return S_FALSE; \
+ UInt32 v = GetUi32(buf); \
+ in.accum = (in.accum << nbits) | mask31(v, nbits); \
+ in.numBits += nbits; }}
+
+
+
+static MY_FORCE_INLINE UInt32 BitStream_Pull(CBitStream *s, unsigned numBits)
+{
+ s->numBits -= numBits;
+ UInt32 v = s->accum >> s->numBits;
+ s->accum = mask31(s->accum, s->numBits);
+ return v;
+}
+
+
+#define DECODE_LIT(dest, pstate) { \
+ UInt32 e = lit_decoder[pstate]; \
+ pstate = (CFseState)((e >> 16) + BitStream_Pull(&in, e & 0xff)); \
+ dest = (Byte)(e >> 8); }
+
+
+static MY_FORCE_INLINE UInt32 FseDecodeExtra(CFseState *pstate,
+ const CExtraEntry *table,
+ CBitStream *s)
+{
+ const CExtraEntry *e = &table[*pstate];
+ UInt32 v = BitStream_Pull(s, e->totalBits);
+ unsigned extraBits = e->extraBits;
+ *pstate = (CFseState)(e->delta + (v >> extraBits));
+ return e->vbase + mask31(v, extraBits);
+}
+
+
+#define freqs_L (freqs)
+#define freqs_M (freqs_L + NUM_L_SYMBOLS)
+#define freqs_D (freqs_M + NUM_M_SYMBOLS)
+#define freqs_LIT (freqs_D + NUM_D_SYMBOLS)
+
+#define GET_BITS_64(v, offset, num, dest) dest = (UInt32) ((v >> (offset)) & ((1 << (num)) - 1));
+#define GET_BITS_32(v, offset, num, dest) dest = (CFseState)((v >> (offset)) & ((1 << (num)) - 1));
+
+
+HRESULT CDecoder::DecodeLzfse(UInt32 unpackSize, Byte version)
+{
+ PRF(printf("\nLZFSE-%d %7u", version - '0', unpackSize));
+
+ UInt32 numLiterals;
+ UInt32 litPayloadSize;
+ Int32 literal_bits;
+
+ UInt32 lit_state_0;
+ UInt32 lit_state_1;
+ UInt32 lit_state_2;
+ UInt32 lit_state_3;
+
+ UInt32 numMatches;
+ UInt32 lmdPayloadSize;
+ Int32 lmd_bits;
+
+ CFseState l_state;
+ CFseState m_state;
+ CFseState d_state;
+
+ UInt16 freqs[NUM_SYMBOLS];
+
+ if (version == kSignature_LZFSE_V1)
+ {
+ return E_NOTIMPL;
+ // we need examples to test LZFSE-V1 code
+ /*
+ const unsigned k_v1_SubHeaderSize = 7 * 4 + 7 * 2;
+ const unsigned k_v1_HeaderSize = k_v1_SubHeaderSize + NUM_SYMBOLS * 2;
+ _buffer.AllocAtLeast(k_v1_HeaderSize);
+ if (m_InStream.ReadBytes(_buffer, k_v1_HeaderSize) != k_v1_HeaderSize)
+ return S_FALSE;
+
+ const Byte *buf = _buffer;
+ #define GET_32(offs, dest) dest = GetUi32(buf + offs)
+ #define GET_16(offs, dest) dest = GetUi16(buf + offs)
+
+ UInt32 payload_bytes;
+ GET_32(0, payload_bytes);
+ GET_32(4, numLiterals);
+ GET_32(8, numMatches);
+ GET_32(12, litPayloadSize);
+ GET_32(16, lmdPayloadSize);
+ if (litPayloadSize > (1 << 20) || lmdPayloadSize > (1 << 20))
+ return S_FALSE;
+ GET_32(20, literal_bits);
+ if (literal_bits < -7 || literal_bits > 0)
+ return S_FALSE;
+
+ GET_16(24, lit_state_0);
+ GET_16(26, lit_state_1);
+ GET_16(28, lit_state_2);
+ GET_16(30, lit_state_3);
+
+ GET_32(32, lmd_bits);
+ if (lmd_bits < -7 || lmd_bits > 0)
+ return S_FALSE;
+
+ GET_16(36, l_state);
+ GET_16(38, m_state);
+ GET_16(40, d_state);
+
+ for (unsigned i = 0; i < NUM_SYMBOLS; i++)
+ freqs[i] = GetUi16(buf + k_v1_SubHeaderSize + i * 2);
+ */
+ }
+ else
+ {
+ UInt32 headerSize;
+ {
+ const unsigned kPreHeaderSize = 4 * 2; // signature and upackSize
+ const unsigned kHeaderSize = 8 * 3;
+ Byte temp[kHeaderSize];
+ if (m_InStream.ReadBytes(temp, kHeaderSize) != kHeaderSize)
+ return S_FALSE;
+
+ UInt64 v;
+
+ v = GetUi64(temp);
+ GET_BITS_64(v, 0, 20, numLiterals);
+ GET_BITS_64(v, 20, 20, litPayloadSize);
+ GET_BITS_64(v, 40, 20, numMatches);
+ GET_BITS_64(v, 60, 3 + 1, literal_bits); // (NumberOfUsedBits - 1)
+ literal_bits -= 7; // (-NumberOfUnusedBits)
+ if (literal_bits > 0)
+ return S_FALSE;
+ // GET_BITS_64(v, 63, 1, unused);
+
+ v = GetUi64(temp + 8);
+ GET_BITS_64(v, 0, 10, lit_state_0);
+ GET_BITS_64(v, 10, 10, lit_state_1);
+ GET_BITS_64(v, 20, 10, lit_state_2);
+ GET_BITS_64(v, 30, 10, lit_state_3);
+ GET_BITS_64(v, 40, 20, lmdPayloadSize);
+ GET_BITS_64(v, 60, 3 + 1, lmd_bits);
+ lmd_bits -= 7;
+ if (lmd_bits > 0)
+ return S_FALSE;
+ // GET_BITS_64(v, 63, 1, unused)
+
+ UInt32 v32 = GetUi32(temp + 20);
+ // (total header size in bytes; this does not
+ // correspond to a field in the uncompressed header version,
+ // but is required; we wouldn't know the size of the
+ // compresssed header otherwise.
+ GET_BITS_32(v32, 0, 10, l_state);
+ GET_BITS_32(v32, 10, 10, m_state);
+ GET_BITS_32(v32, 20, 10 + 2, d_state);
+ // GET_BITS_64(v, 62, 2, unused);
+
+ headerSize = GetUi32(temp + 16);
+ if (headerSize <= kPreHeaderSize + kHeaderSize)
+ return S_FALSE;
+ headerSize -= kPreHeaderSize + kHeaderSize;
+ }
+
+ // no freqs case is not allowed ?
+ // memset(freqs, 0, sizeof(freqs));
+ // if (headerSize != 0)
+ {
+ static const Byte numBitsTable[32] =
+ {
+ 2, 3, 2, 5, 2, 3, 2, 8, 2, 3, 2, 5, 2, 3, 2, 14,
+ 2, 3, 2, 5, 2, 3, 2, 8, 2, 3, 2, 5, 2, 3, 2, 14
+ };
+
+ static const Byte valueTable[32] =
+ {
+ 0, 2, 1, 4, 0, 3, 1, 8, 0, 2, 1, 5, 0, 3, 1, 24,
+ 0, 2, 1, 6, 0, 3, 1, 8, 0, 2, 1, 7, 0, 3, 1, 24
+ };
+
+ UInt32 accum = 0;
+ unsigned numBits = 0;
+
+ for (unsigned i = 0; i < NUM_SYMBOLS; i++)
+ {
+ while (numBits <= 14 && headerSize != 0)
+ {
+ Byte b;
+ if (!m_InStream.ReadByte(b))
+ return S_FALSE;
+ accum |= (UInt32)b << numBits;
+ numBits += 8;
+ headerSize--;
+ }
+
+ unsigned b = (unsigned)accum & 31;
+ unsigned n = numBitsTable[b];
+ if (numBits < n)
+ return S_FALSE;
+ numBits -= n;
+ UInt32 f = valueTable[b];
+ if (n >= 8)
+ f += ((accum >> 4) & (0x3ff >> (14 - n)));
+ accum >>= n;
+ freqs[i] = (UInt16)f;
+ }
+
+ if (numBits >= 8 || headerSize != 0)
+ return S_FALSE;
+ }
+ }
+
+ PRF(printf(" Literals=%6u Matches=%6u", numLiterals, numMatches));
+
+ if (numLiterals > LITERALS_PER_BLOCK
+ || (numLiterals & 3) != 0
+ || numMatches > MATCHES_PER_BLOCK
+ || lit_state_0 >= NUM_LIT_STATES
+ || lit_state_1 >= NUM_LIT_STATES
+ || lit_state_2 >= NUM_LIT_STATES
+ || lit_state_3 >= NUM_LIT_STATES
+ || l_state >= NUM_L_STATES
+ || m_state >= NUM_M_STATES
+ || d_state >= NUM_D_STATES)
+ return S_FALSE;
+
+ // only full table is allowed ?
+ if ( SumFreqs(freqs_L, NUM_L_SYMBOLS) != NUM_L_STATES
+ || SumFreqs(freqs_M, NUM_M_SYMBOLS) != NUM_M_STATES
+ || SumFreqs(freqs_D, NUM_D_SYMBOLS) != NUM_D_STATES
+ || SumFreqs(freqs_LIT, NUM_LIT_SYMBOLS) != NUM_LIT_STATES)
+ return S_FALSE;
+
+
+ const unsigned kPad = 16;
+
+ // ---------- Decode literals ----------
+
+ {
+ _literals.AllocAtLeast(LITERALS_PER_BLOCK + 16);
+ _buffer.AllocAtLeast(kPad + litPayloadSize);
+ memset(_buffer, 0, kPad);
+
+ if (m_InStream.ReadBytes(_buffer + kPad, litPayloadSize) != litPayloadSize)
+ return S_FALSE;
+
+ UInt32 lit_decoder[NUM_LIT_STATES];
+ InitLitTable(freqs_LIT, lit_decoder);
+
+ const Byte *buf_start = _buffer + kPad;
+ const Byte *buf_check = buf_start - 4;
+ const Byte *buf = buf_start + litPayloadSize;
+ CBitStream in;
+ if (FseInStream_Init(&in, literal_bits, &buf) != 0)
+ return S_FALSE;
+
+ Byte *lit = _literals;
+ const Byte *lit_limit = lit + numLiterals;
+ for (; lit < lit_limit; lit += 4)
+ {
+ FseInStream_FLUSH
+ DECODE_LIT (lit[0], lit_state_0);
+ DECODE_LIT (lit[1], lit_state_1);
+ FseInStream_FLUSH
+ DECODE_LIT (lit[2], lit_state_2);
+ DECODE_LIT (lit[3], lit_state_3);
+ }
+
+ if ((buf_start - buf) * 8 != (int)in.numBits)
+ return S_FALSE;
+ }
+
+
+ // ---------- Decode LMD ----------
+
+ _buffer.AllocAtLeast(kPad + lmdPayloadSize);
+ memset(_buffer, 0, kPad);
+ if (m_InStream.ReadBytes(_buffer + kPad, lmdPayloadSize) != lmdPayloadSize)
+ return S_FALSE;
+
+ CExtraEntry l_decoder[NUM_L_STATES];
+ CExtraEntry m_decoder[NUM_M_STATES];
+ CExtraEntry d_decoder[NUM_D_STATES];
+
+ InitExtraDecoderTable(NUM_L_STATES, NUM_L_SYMBOLS, freqs_L, k_L_extra, l_decoder);
+ InitExtraDecoderTable(NUM_M_STATES, NUM_M_SYMBOLS, freqs_M, k_M_extra, m_decoder);
+ InitExtraDecoderTable(NUM_D_STATES, NUM_D_SYMBOLS, freqs_D, k_D_extra, d_decoder);
+
+ const Byte *buf_start = _buffer + kPad;
+ const Byte *buf_check = buf_start - 4;
+ const Byte *buf = buf_start + lmdPayloadSize;
+ CBitStream in;
+ if (FseInStream_Init(&in, lmd_bits, &buf))
+ return S_FALSE;
+
+ const Byte *lit = _literals;
+ const Byte *lit_limit = lit + numLiterals;
+
+ UInt32 D = 0;
+
+ for (;;)
+ {
+ if (numMatches == 0)
+ break;
+ numMatches--;
+
+ FseInStream_FLUSH
+
+ unsigned L = (unsigned)FseDecodeExtra(&l_state, l_decoder, &in);
+
+ FseInStream_FLUSH
+
+ unsigned M = (unsigned)FseDecodeExtra(&m_state, m_decoder, &in);
+
+ FseInStream_FLUSH
+
+ {
+ UInt32 new_D = FseDecodeExtra(&d_state, d_decoder, &in);
+ if (new_D)
+ D = new_D;
+ }
+
+ if (L != 0)
+ {
+ if (L > (size_t)(lit_limit - lit))
+ return S_FALSE;
+ unsigned cur = L;
+ if (cur > unpackSize)
+ cur = (unsigned)unpackSize;
+ m_OutWindowStream.PutBytes(lit, cur);
+ unpackSize -= cur;
+ lit += cur;
+ if (cur != L)
+ return S_FALSE;
+ }
+
+ if (M != 0)
+ {
+ if (unpackSize == 0 || D == 0)
+ return S_FALSE;
+ unsigned cur = M;
+ if (cur > unpackSize)
+ cur = (unsigned)unpackSize;
+ if (!m_OutWindowStream.CopyBlock(D - 1, cur))
+ return S_FALSE;
+ unpackSize -= cur;
+ if (cur != M)
+ return S_FALSE;
+ }
+ }
+
+ if (unpackSize != 0)
+ return S_FALSE;
+
+ // LZFSE encoder writes 8 additional zero bytes before LMD payload
+ // We test it:
+ if ((buf - buf_start) * 8 + in.numBits != 64)
+ return S_FALSE;
+ if (GetUi64(buf_start) != 0)
+ return S_FALSE;
+
+ return S_OK;
+}
+
+
+STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
+{
+ PRF(printf("\n\nLzfseDecoder %7u %7u\n", (unsigned)*outSize, (unsigned)*inSize));
+
+ const UInt32 kLzfseDictSize = 1 << 18;
+ if (!m_OutWindowStream.Create(kLzfseDictSize))
+ return E_OUTOFMEMORY;
+ if (!m_InStream.Create(1 << 18))
+ return E_OUTOFMEMORY;
+
+ m_OutWindowStream.SetStream(outStream);
+ m_OutWindowStream.Init(false);
+ m_InStream.SetStream(inStream);
+ m_InStream.Init();
+
+ CCoderReleaser coderReleaser(this);
+
+ UInt64 prevOut = 0;
+ UInt64 prevIn = 0;
+
+ for (;;)
+ {
+ const UInt64 pos = m_OutWindowStream.GetProcessedSize();
+ const UInt64 packPos = m_InStream.GetProcessedSize();
+
+ if (progress && ((pos - prevOut) >= (1 << 22) || (packPos - prevIn) >= (1 << 22)))
+ {
+ RINOK(progress->SetRatioInfo(&packPos, &pos));
+ prevIn = packPos;
+ prevOut = pos;
+ }
+
+ const UInt64 rem = *outSize - pos;
+ UInt32 v;
+ RINOK(GetUInt32(v))
+ if ((v & 0xFFFFFF) != 0x787662) // bvx
+ return S_FALSE;
+ v >>= 24;
+
+ if (v == 0x24) // '$', end of stream
+ break;
+
+ UInt32 unpackSize;
+ RINOK(GetUInt32(unpackSize));
+
+ UInt32 cur = unpackSize;
+ if (cur > rem)
+ cur = (UInt32)rem;
+
+ unpackSize -= cur;
+
+ HRESULT res;
+ if (v == kSignature_LZFSE_V1 || v == kSignature_LZFSE_V2)
+ res = DecodeLzfse(cur, (Byte)v);
+ else if (v == 0x6E) // 'n'
+ res = DecodeLzvn(cur);
+ else if (v == 0x2D) // '-'
+ res = DecodeUncompressed(cur);
+ else
+ return E_NOTIMPL;
+
+ if (res != S_OK)
+ return res;
+
+ if (unpackSize != 0)
+ return S_FALSE;
+ }
+
+ coderReleaser.NeedFlush = false;
+ HRESULT res = m_OutWindowStream.Flush();
+ if (res == S_OK)
+ if (*inSize != m_InStream.GetProcessedSize()
+ || *outSize != m_OutWindowStream.GetProcessedSize())
+ res = S_FALSE;
+ return res;
+}
+
+
+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
+{
+ try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
+ catch(const CInBufferException &e) { return e.ErrorCode; }
+ catch(const CLzOutWindowException &e) { return e.ErrorCode; }
+ catch(...) { return E_OUTOFMEMORY; }
+ // catch(...) { return S_FALSE; }
+}
+
+}}
diff --git a/CPP/7zip/Compress/LzfseDecoder.h b/CPP/7zip/Compress/LzfseDecoder.h
new file mode 100644
index 00000000..0156a087
--- /dev/null
+++ b/CPP/7zip/Compress/LzfseDecoder.h
@@ -0,0 +1,58 @@
+// LzfseDecoder.h
+
+#ifndef __LZFSE_DECODER_H
+#define __LZFSE_DECODER_H
+
+#include "../../Common/MyBuffer.h"
+#include "../../Common/MyCom.h"
+
+#include "../ICoder.h"
+
+#include "../Common/InBuffer.h"
+
+#include "LzOutWindow.h"
+
+namespace NCompress {
+namespace NLzfse {
+
+class CDecoder:
+ public ICompressCoder,
+ public CMyUnknownImp
+{
+ CLzOutWindow m_OutWindowStream;
+ CInBuffer m_InStream;
+ CByteBuffer _literals;
+ CByteBuffer _buffer;
+
+ class CCoderReleaser
+ {
+ CDecoder *m_Coder;
+ public:
+ bool NeedFlush;
+ CCoderReleaser(CDecoder *coder): m_Coder(coder), NeedFlush(true) {}
+ ~CCoderReleaser()
+ {
+ if (NeedFlush)
+ m_Coder->m_OutWindowStream.Flush();
+ }
+ };
+ friend class CCoderReleaser;
+
+ HRESULT GetUInt32(UInt32 &val);
+
+ HRESULT DecodeUncompressed(UInt32 unpackSize);
+ HRESULT DecodeLzvn(UInt32 unpackSize);
+ HRESULT DecodeLzfse(UInt32 unpackSize, Byte version);
+
+ STDMETHOD(CodeReal)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
+public:
+ MY_UNKNOWN_IMP
+
+ STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize,
+ const UInt64 *outSize, ICompressProgressInfo *progress);
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp
index e52e47d0..1c2e3397 100644
--- a/CPP/7zip/UI/Agent/Agent.cpp
+++ b/CPP/7zip/UI/Agent/Agent.cpp
@@ -1217,7 +1217,12 @@ STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
NWindows::NCOM::CPropVariant prop;
if (propID == kpidReadOnly)
- prop = _agentSpec->IsThereReadOnlyArc();
+ {
+ if (_agentSpec->Is_Attrib_ReadOnly())
+ prop = true;
+ else
+ prop = _agentSpec->IsThereReadOnlyArc();
+ }
else if (_proxy2)
{
const CProxyDir2 &dir = _proxy2->Dirs[_proxyDirIndex];
@@ -1564,6 +1569,7 @@ STDMETHODIMP CAgent::Open(
{
COM_TRY_BEGIN
_archiveFilePath = filePath;
+ _attrib = 0;
NFile::NFind::CFileInfo fi;
_isDeviceFile = false;
if (!inStream)
@@ -1572,6 +1578,7 @@ STDMETHODIMP CAgent::Open(
return ::GetLastError();
if (fi.IsDir())
return E_FAIL;
+ _attrib = fi.Attrib;
_isDeviceFile = fi.IsDevice;
}
CArcInfoEx archiverInfo0, archiverInfo1;
diff --git a/CPP/7zip/UI/Agent/Agent.h b/CPP/7zip/UI/Agent/Agent.h
index ae4026d6..7ba96f4a 100644
--- a/CPP/7zip/UI/Agent/Agent.h
+++ b/CPP/7zip/UI/Agent/Agent.h
@@ -241,6 +241,7 @@ public:
CAgentFolder *_agentFolder;
UString _archiveFilePath;
+ DWORD _attrib;
bool _isDeviceFile;
#ifndef EXTRACT_ONLY
@@ -252,6 +253,11 @@ public:
IInArchive *GetArchive() const { if ( _archiveLink.Arcs.IsEmpty()) return 0; return GetArc().Archive; }
bool CanUpdate() const;
+ bool Is_Attrib_ReadOnly() const
+ {
+ return _attrib != INVALID_FILE_ATTRIBUTES && (_attrib & FILE_ATTRIBUTE_READONLY);
+ }
+
bool IsThereReadOnlyArc() const
{
FOR_VECTOR (i, _archiveLink.Arcs)
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
index 0571a452..083e7c84 100644
--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
@@ -372,6 +372,8 @@ void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat
HRESULT CArchiveExtractCallback::GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined)
{
filetimeIsDefined = false;
+ filetime.dwLowDateTime = 0;
+ filetime.dwHighDateTime = 0;
NCOM::CPropVariant prop;
RINOK(_arc->Archive->GetProperty(index, propID, &prop));
if (prop.vt == VT_FILETIME)
@@ -1032,14 +1034,36 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
{
FString fullPathNew;
CreateComplexDirectory(pathParts, fullPathNew);
+
if (_item.IsDir)
{
- _extractedFolderPaths.Add(fullPathNew);
- _extractedFolderIndices.Add(index);
- SetDirTime(fullPathNew,
- (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL,
- (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL,
- (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));
+ CDirPathTime &pt = _extractedFolders.AddNew();
+
+ pt.CTime = _fi.CTime;
+ pt.CTimeDefined = (WriteCTime && _fi.CTimeDefined);
+
+ pt.ATime = _fi.ATime;
+ pt.ATimeDefined = (WriteATime && _fi.ATimeDefined);
+
+ pt.MTimeDefined = false;
+
+ if (WriteMTime)
+ {
+ if (_fi.MTimeDefined)
+ {
+ pt.MTime = _fi.MTime;
+ pt.MTimeDefined = true;
+ }
+ else if (_arc->MTimeDefined)
+ {
+ pt.MTime = _arc->MTime;
+ pt.MTimeDefined = true;
+ }
+ }
+
+ pt.Path = fullPathNew;
+
+ pt.SetDirTime();
}
}
}
@@ -1602,75 +1626,53 @@ STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)
}
-struct CExtrRefSortPair
-{
- unsigned Len;
- unsigned Index;
-
- int Compare(const CExtrRefSortPair &a) const;
-};
-
-#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
-
-int CExtrRefSortPair::Compare(const CExtrRefSortPair &a) const
-{
- RINOZ(-MyCompare(Len, a.Len));
- return MyCompare(Index, a.Index);
-}
-
-static unsigned GetNumSlashes(const FChar *s)
+void CDirPathSortPair::SetNumSlashes(const FChar *s)
{
for (unsigned numSlashes = 0;;)
{
FChar c = *s++;
if (c == 0)
- return numSlashes;
+ {
+ Len = numSlashes;
+ return;
+ }
if (IS_PATH_SEPAR(c))
numSlashes++;
}
}
+bool CDirPathTime::SetDirTime()
+{
+ return NDir::SetDirTime(Path,
+ CTimeDefined ? &CTime : NULL,
+ ATimeDefined ? &ATime : NULL,
+ MTimeDefined ? &MTime : NULL);
+}
+
+
HRESULT CArchiveExtractCallback::SetDirsTimes()
{
if (!_arc)
return S_OK;
- CRecordVector<CExtrRefSortPair> pairs;
- pairs.ClearAndSetSize(_extractedFolderPaths.Size());
+ CRecordVector<CDirPathSortPair> pairs;
+ pairs.ClearAndSetSize(_extractedFolders.Size());
unsigned i;
- for (i = 0; i < _extractedFolderPaths.Size(); i++)
+ for (i = 0; i < _extractedFolders.Size(); i++)
{
- CExtrRefSortPair &pair = pairs[i];
+ CDirPathSortPair &pair = pairs[i];
pair.Index = i;
- pair.Len = GetNumSlashes(_extractedFolderPaths[i]);
+ pair.SetNumSlashes(_extractedFolders[i].Path);
}
pairs.Sort2();
for (i = 0; i < pairs.Size(); i++)
{
- unsigned pairIndex = pairs[i].Index;
- UInt32 index = _extractedFolderIndices[pairIndex];
-
- FILETIME CTime;
- FILETIME ATime;
- FILETIME MTime;
-
- bool CTimeDefined;
- bool ATimeDefined;
- bool MTimeDefined;
-
- RINOK(GetTime(index, kpidCTime, CTime, CTimeDefined));
- RINOK(GetTime(index, kpidATime, ATime, ATimeDefined));
- RINOK(GetTime(index, kpidMTime, MTime, MTimeDefined));
-
- // printf("\n%S", _extractedFolderPaths[pairIndex]);
- SetDirTime(_extractedFolderPaths[pairIndex],
- (WriteCTime && CTimeDefined) ? &CTime : NULL,
- (WriteATime && ATimeDefined) ? &ATime : NULL,
- (WriteMTime && MTimeDefined) ? &MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));
+ _extractedFolders[pairs[i].Index].SetDirTime();
+ // if (!) return GetLastError();
}
ClearExtractedDirsInfo();
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
index 4b96b523..dd5c98c0 100644
--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
@@ -151,6 +151,25 @@ struct CIndexToPathPair
#endif
+
+
+struct CDirPathTime
+{
+ FILETIME CTime;
+ FILETIME ATime;
+ FILETIME MTime;
+
+ bool CTimeDefined;
+ bool ATimeDefined;
+ bool MTimeDefined;
+
+ FString Path;
+
+ bool SetDirTime();
+};
+
+
+
class CArchiveExtractCallback:
public IArchiveExtractCallback,
public IArchiveExtractCallbackMessage,
@@ -241,8 +260,7 @@ class CArchiveExtractCallback:
UInt64 _progressTotal;
bool _progressTotal_Defined;
- FStringVector _extractedFolderPaths;
- CRecordVector<UInt32> _extractedFolderIndices;
+ CObjectVector<CDirPathTime> _extractedFolders;
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX)
bool _saclEnabled;
@@ -348,8 +366,7 @@ public:
private:
void ClearExtractedDirsInfo()
{
- _extractedFolderPaths.Clear();
- _extractedFolderIndices.Clear();
+ _extractedFolders.Clear();
}
HRESULT CloseFile();
diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp
index 69817179..b9b4abd9 100644
--- a/CPP/7zip/UI/Common/OpenArchive.cpp
+++ b/CPP/7zip/UI/Common/OpenArchive.cpp
@@ -857,7 +857,7 @@ HRESULT CArc::GetItem(UInt32 index, CReadArcItem &item) const
if (item.WriteToAltStreamIfColon || needFindAltStream)
{
- /* Good handler must support GetRawProps::GetParent for alt streams./
+ /* Good handler must support GetRawProps::GetParent for alt streams.
So the following code currently is not used */
int colon = FindAltStreamColon_in_Path(item.Path);
if (colon >= 0)
diff --git a/CPP/7zip/UI/Common/OpenArchive.h b/CPP/7zip/UI/Common/OpenArchive.h
index d46d69e8..6eb0d395 100644
--- a/CPP/7zip/UI/Common/OpenArchive.h
+++ b/CPP/7zip/UI/Common/OpenArchive.h
@@ -414,4 +414,23 @@ struct CArchiveLink
bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types);
+
+struct CDirPathSortPair
+{
+ unsigned Len;
+ unsigned Index;
+
+ void SetNumSlashes(const FChar *s);
+
+ int Compare(const CDirPathSortPair &a) const
+ {
+ // We need sorting order where parent items will be after child items
+ if (Len < a.Len) return 1;
+ if (Len > a.Len) return -1;
+ if (Index < a.Index) return -1;
+ if (Index > a.Index) return 1;
+ return 0;
+ }
+};
+
#endif
diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp
index f1826957..5d3c4484 100644
--- a/CPP/7zip/UI/Common/Update.cpp
+++ b/CPP/7zip/UI/Common/Update.cpp
@@ -1046,32 +1046,6 @@ static HRESULT EnumerateInArchiveItems(
#endif
-struct CRefSortPair
-{
- unsigned Len;
- unsigned Index;
-};
-
-#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
-
-static int CompareRefSortPair(const CRefSortPair *a1, const CRefSortPair *a2, void *)
-{
- RINOZ(-MyCompare(a1->Len, a2->Len));
- return MyCompare(a1->Index, a2->Index);
-}
-
-static unsigned GetNumSlashes(const FChar *s)
-{
- for (unsigned numSlashes = 0;;)
- {
- FChar c = *s++;
- if (c == 0)
- return numSlashes;
- if (IS_PATH_SEPAR(c))
- numSlashes++;
- }
-}
-
#ifdef _WIN32
void ConvertToLongNames(NWildcard::CCensor &censor);
#endif
@@ -1190,6 +1164,16 @@ HRESULT UpdateArchive(
throw "there is no such archive";
if (fi.IsDevice)
return E_NOTIMPL;
+
+ if (!options.StdOutMode && options.UpdateArchiveItself)
+ if (fi.IsReadOnly())
+ {
+ errorInfo.SystemError = ERROR_ACCESS_DENIED;
+ errorInfo.Message = "The file is read-only";
+ errorInfo.FileNames.Add(arcPath);
+ return errorInfo.Get_HRESULT_Error();
+ }
+
if (options.VolumesSizes.Size() > 0)
{
errorInfo.FileNames.Add(us2fs(arcPath));
@@ -1510,9 +1494,13 @@ HRESULT UpdateArchive(
CArchivePath &ap = options.Commands[0].ArchivePath;
const FString &tempPath = ap.GetTempPath();
+ // DWORD attrib = 0;
if (thereIsInArchive)
+ {
+ // attrib = NFind::GetFileAttrib(us2fs(arcPath));
if (!DeleteFileAlways(us2fs(arcPath)))
return errorInfo.SetFromLastError("cannot delete the file", us2fs(arcPath));
+ }
if (!MyMoveFile(tempPath, us2fs(arcPath)))
{
@@ -1520,6 +1508,15 @@ HRESULT UpdateArchive(
errorInfo.FileNames.Add(us2fs(arcPath));
return errorInfo.Get_HRESULT_Error();
}
+
+ /*
+ if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY))
+ {
+ DWORD attrib2 = NFind::GetFileAttrib(us2fs(arcPath));
+ if (attrib2 != INVALID_FILE_ATTRIBUTES)
+ NDir::SetFileAttrib(us2fs(arcPath), attrib2 | FILE_ATTRIBUTE_READONLY);
+ }
+ */
}
catch(...)
{
@@ -1609,7 +1606,7 @@ HRESULT UpdateArchive(
if (options.DeleteAfterCompressing)
{
- CRecordVector<CRefSortPair> pairs;
+ CRecordVector<CDirPathSortPair> pairs;
FStringVector foldersNames;
unsigned i;
@@ -1617,12 +1614,12 @@ HRESULT UpdateArchive(
for (i = 0; i < dirItems.Items.Size(); i++)
{
const CDirItem &dirItem = dirItems.Items[i];
- FString phyPath = dirItems.GetPhyPath(i);
+ const FString phyPath = dirItems.GetPhyPath(i);
if (dirItem.IsDir())
{
- CRefSortPair pair;
+ CDirPathSortPair pair;
pair.Index = i;
- pair.Len = GetNumSlashes(phyPath);
+ pair.SetNumSlashes(phyPath);
pairs.Add(pair);
}
else
@@ -1655,11 +1652,11 @@ HRESULT UpdateArchive(
}
}
- pairs.Sort(CompareRefSortPair, NULL);
+ pairs.Sort2();
for (i = 0; i < pairs.Size(); i++)
{
- FString phyPath = dirItems.GetPhyPath(pairs[i].Index);
+ const FString phyPath = dirItems.GetPhyPath(pairs[i].Index);
if (NFind::DoesDirExist(phyPath))
{
RINOK(callback->DeletingAfterArchiving(phyPath, true));