mirror of
https://github.com/LisherSong/ps5-web-file-manager.git
synced 2026-10-06 08:00:23 +02:00
Groundwork for 7z support (the second of the six format x volume
combinations). No engine code yet: this lands the vendor subset, real
fixtures and the end-to-end driver, so the engine has something to be
built and checked against.
Vendor (third_party/7z, LZMA SDK 26.03, public domain):
- decoder-only subset: 7zArcIn/7zDec container, Lzma/Lzma2/Ppmd7/Bcj2/
Bra/Delta codecs, Aes/Sha256 for the password channel to come
- the encoder half (LzmaEnc, Xz*, Sort, Threads, ...) is deliberately
not vendored; the engine never encodes
- README.md records two SDK limitations that shape the engine design:
* CSzFolder caps a folder at 4 coders / 3 bonds, so 7-Zip's own BCJ2
chain (BCJ2 + 4xLZMA2 = 5 coders) is refused by SzAr_DecodeFolder
even though SzArEx_Open parses it happily - the engine therefore
parses folder blobs and drives the codec chain itself
* the C decoder ships no 7zAES coder at all, so both -p and -mhe=on
archives are rejected until the engine implements it on top of the
vendored Aes.c / Sha256.c
Tests:
- make_sevenz_fixtures.py builds real archives with an actual 7-Zip
binary (7za from the Extra package; falls back to the reduced 7zr,
which has no PPMd encoder): store/lzma/lzma2/ppmd/bcj/delta/bcj2,
AES with plain and with encrypted headers, a 7-part -v100k volume
set, and UTF-8 entry names
- sevenz_e2e.c extracts an archive and validates every entry against
the stored CRC; it calls the wide-character file APIs on Windows, so
non-ASCII entry names are really created instead of silently failing
- run-sevenz-tests.sh builds the subset and the driver, then runs the
fixture matrix with an explicit KNOWN_GAPS list that fails loudly
when one of the gaps starts passing
Status: store, lzma, lzma2, ppmd, bcj, delta and utf8 all extract
byte-identical to the source tree (7/10). bcj2, aes, aeshe and
vol.7z.001 are the known gaps, each mapped to a specific piece of
engine work still to come.
170 lines
3.0 KiB
C
170 lines
3.0 KiB
C
/* Delta.c -- Delta converter
|
|
2021-02-09 : Igor Pavlov : Public domain */
|
|
|
|
#include "Precomp.h"
|
|
|
|
#include "Delta.h"
|
|
|
|
void Delta_Init(Byte *state)
|
|
{
|
|
unsigned i;
|
|
for (i = 0; i < DELTA_STATE_SIZE; i++)
|
|
state[i] = 0;
|
|
}
|
|
|
|
|
|
void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size)
|
|
{
|
|
Byte temp[DELTA_STATE_SIZE];
|
|
|
|
if (size == 0)
|
|
return;
|
|
|
|
{
|
|
unsigned i = 0;
|
|
do
|
|
temp[i] = state[i];
|
|
while (++i != delta);
|
|
}
|
|
|
|
if (size <= delta)
|
|
{
|
|
unsigned i = 0, k;
|
|
do
|
|
{
|
|
Byte b = *data;
|
|
*data++ = (Byte)(b - temp[i]);
|
|
temp[i] = b;
|
|
}
|
|
while (++i != size);
|
|
|
|
k = 0;
|
|
|
|
do
|
|
{
|
|
if (i == delta)
|
|
i = 0;
|
|
state[k] = temp[i++];
|
|
}
|
|
while (++k != delta);
|
|
|
|
return;
|
|
}
|
|
|
|
{
|
|
Byte *p = data + size - delta;
|
|
{
|
|
unsigned i = 0;
|
|
do
|
|
state[i] = *p++;
|
|
while (++i != delta);
|
|
}
|
|
{
|
|
const Byte *lim = data + delta;
|
|
ptrdiff_t dif = -(ptrdiff_t)delta;
|
|
|
|
if (((ptrdiff_t)size + dif) & 1)
|
|
{
|
|
--p; *p = (Byte)(*p - p[dif]);
|
|
}
|
|
|
|
while (p != lim)
|
|
{
|
|
--p; *p = (Byte)(*p - p[dif]);
|
|
--p; *p = (Byte)(*p - p[dif]);
|
|
}
|
|
|
|
dif = -dif;
|
|
|
|
do
|
|
{
|
|
--p; *p = (Byte)(*p - temp[--dif]);
|
|
}
|
|
while (dif != 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size)
|
|
{
|
|
unsigned i;
|
|
const Byte *lim;
|
|
|
|
if (size == 0)
|
|
return;
|
|
|
|
i = 0;
|
|
lim = data + size;
|
|
|
|
if (size <= delta)
|
|
{
|
|
do
|
|
*data = (Byte)(*data + state[i++]);
|
|
while (++data != lim);
|
|
|
|
for (; delta != i; state++, delta--)
|
|
*state = state[i];
|
|
data -= i;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
#define B(n) b ## n
|
|
#define I(n) Byte B(n) = state[n];
|
|
#define U(n) { B(n) = (Byte)((B(n)) + *data++); data[-1] = (B(n)); }
|
|
#define F(n) if (data != lim) { U(n) }
|
|
|
|
if (delta == 1)
|
|
{
|
|
I(0)
|
|
if ((lim - data) & 1) { U(0) }
|
|
while (data != lim) { U(0) U(0) }
|
|
data -= 1;
|
|
}
|
|
else if (delta == 2)
|
|
{
|
|
I(0) I(1)
|
|
lim -= 1; while (data < lim) { U(0) U(1) }
|
|
lim += 1; F(0)
|
|
data -= 2;
|
|
}
|
|
else if (delta == 3)
|
|
{
|
|
I(0) I(1) I(2)
|
|
lim -= 2; while (data < lim) { U(0) U(1) U(2) }
|
|
lim += 2; F(0) F(1)
|
|
data -= 3;
|
|
}
|
|
else if (delta == 4)
|
|
{
|
|
I(0) I(1) I(2) I(3)
|
|
lim -= 3; while (data < lim) { U(0) U(1) U(2) U(3) }
|
|
lim += 3; F(0) F(1) F(2)
|
|
data -= 4;
|
|
}
|
|
else
|
|
*/
|
|
{
|
|
do
|
|
{
|
|
*data = (Byte)(*data + state[i++]);
|
|
data++;
|
|
}
|
|
while (i != delta);
|
|
|
|
{
|
|
ptrdiff_t dif = -(ptrdiff_t)delta;
|
|
do
|
|
*data = (Byte)(*data + data[dif]);
|
|
while (++data != lim);
|
|
data += dif;
|
|
}
|
|
}
|
|
}
|
|
|
|
do
|
|
*state++ = *data;
|
|
while (++data != lim);
|
|
}
|