Update LZMA SDK to 23.01

As a bonus, add support for XZ-compressed files in ZIP
This commit is contained in:
Cacodemon345 2023-09-19 01:42:53 +06:00 committed by Christoph Oelckers
commit 4497d7fdaa
89 changed files with 19247 additions and 2061 deletions

View file

@ -36,6 +36,9 @@
// Caution: LzmaDec also pulls in windows.h!
#define NOMINMAX
#include "LzmaDec.h"
#include "Xz.h"
// CRC table needs to be generated prior to reading XZ compressed files.
#include "7zCrc.h"
#include <miniz.h>
#include <bzlib.h>
#include <algorithm>
@ -505,6 +508,142 @@ public:
};
//==========================================================================
//
// DecompressorXZ
//
// The XZ wrapper
// reads data from a XZ compressed stream
//
//==========================================================================
// Wraps around a Decompressor to decompress a XZ stream
class DecompressorXZ : public DecompressorBase
{
enum { BUFF_SIZE = 4096 };
bool SawEOF = false;
CXzUnpacker Stream;
size_t Size;
size_t InPos, InSize;
size_t OutProcessed;
uint8_t InBuff[BUFF_SIZE];
public:
bool Open(FileReader *file, size_t uncompressed_size)
{
if (File != nullptr)
{
DecompressionError("File already open");
return false;
}
uint8_t header[12];
int err;
File = file;
Size = uncompressed_size;
OutProcessed = 0;
// Read zip XZ properties header
if (File->Read(header, sizeof(header)) < (long)sizeof(header))
{
DecompressionError("DecompressorXZ: File too short\n");
return false;
}
File->Seek(-sizeof(header), FileReader::SeekCur);
FillBuffer();
XzUnpacker_Construct(&Stream, &g_Alloc);
XzUnpacker_Init(&Stream);
return true;
}
~DecompressorXZ ()
{
XzUnpacker_Free(&Stream);
}
ptrdiff_t Read (void *buffer, ptrdiff_t len) override
{
if (File == nullptr)
{
DecompressionError("File not open");
return 0;
}
if (g_CrcTable[1] == 0)
{
CrcGenerateTable();
}
int err;
Byte *next_out = (Byte *)buffer;
do
{
ECoderFinishMode finish_mode = CODER_FINISH_ANY;
ECoderStatus status;
size_t out_processed = len;
size_t in_processed = InSize;
err = XzUnpacker_Code(&Stream, next_out, &out_processed, InBuff + InPos, &in_processed, SawEOF, finish_mode, &status);
InPos += in_processed;
InSize -= in_processed;
next_out += out_processed;
len = (long)(len - out_processed);
if (err != SZ_OK)
{
DecompressionError ("Corrupt XZ stream", err);
return 0;
}
if (in_processed == 0 && out_processed == 0)
{
if (status != CODER_STATUS_FINISHED_WITH_MARK)
{
DecompressionError ("Corrupt XZ stream");
return 0;
}
}
if (InSize == 0 && !SawEOF)
{
FillBuffer ();
}
} while (err == SZ_OK && len != 0);
if (err != Z_OK && err != Z_STREAM_END)
{
DecompressionError ("Corrupt XZ stream");
return 0;
}
if (len != 0)
{
DecompressionError ("Ran out of data in XZ stream");
return 0;
}
return (long)(next_out - (Byte *)buffer);
}
void FillBuffer ()
{
auto numread = File->Read(InBuff, BUFF_SIZE);
if (numread < BUFF_SIZE)
{
SawEOF = true;
}
InPos = 0;
InSize = numread;
}
};
//==========================================================================
//
// Console Doom LZSS wrapper.
@ -748,6 +887,18 @@ bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, b
}
break;
}
case METHOD_XZ:
{
auto idec = new DecompressorXZ;
dec = idec;
idec->EnableExceptions(exceptions);
if (!idec->Open(p, length))
{
delete idec;
return false;
}
break;
}
case METHOD_LZSS:
{
auto idec = new DecompressorLZSS;