Skip to content

Commit ebaa2c2

Browse files
committed
FEAT: decompress/deflate - decompression of data which are in raw deflate format (without envelope)
Example: ``` >> decompress/deflate #{2B492D2E01000C7E7FD804} == #{74657374} ``` Also using it in the ZIP codec.
1 parent bf1d6d1 commit ebaa2c2

File tree

4 files changed

+27
-18
lines changed

4 files changed

+27
-18
lines changed

src/core/n-strings.c

+16-8
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ static struct digest {
346346
// /zlib {Data are in ZLIB format with Adler32 checksum}
347347
// /gzip {Data are in ZLIB format with CRC32 checksum}
348348
// /lzma {Data are in LZMA format}
349+
// /deflate {Data are raw DEFLATE data}
349350
// /size
350351
// bytes [integer!] {Number of decompressed bytes. If not used, size is detected from last 4 source data bytes.}
351352
]
@@ -357,17 +358,24 @@ static struct digest {
357358
REBOOL ref_zlib = D_REF(4);
358359
REBOOL ref_gzip = D_REF(5);
359360
REBOOL ref_lzma = D_REF(6);
360-
REBOOL ref_size = D_REF(7);
361-
REBVAL *size = D_ARG(8);
361+
REBOOL ref_defl = D_REF(7);
362+
REBOOL ref_size = D_REF(8);
363+
REBVAL *size = D_ARG(9);
362364

363-
REBINT limit = 0;
365+
REBCNT limit = 0;
364366
REBCNT len;
365-
366-
if ((ref_zlib && (ref_gzip || ref_lzma)) || (ref_gzip && ref_lzma)) Trap0(RE_BAD_REFINES);
367+
REBINT windowBits = MAX_WBITS;
368+
369+
// test if only one compression type refinement is used
370+
if (
371+
(ref_zlib && (ref_gzip || ref_lzma || ref_defl)) ||
372+
(ref_gzip && (ref_zlib || ref_lzma || ref_defl)) ||
373+
(ref_lzma && (ref_zlib || ref_gzip || ref_defl))
374+
) Trap0(RE_BAD_REFINES);
367375

368376
len = Partial1(data, length);
369377

370-
if (ref_size) limit = Int32s(size, 1); // /limit size
378+
if (ref_size) limit = (REBCNT)Int32s(size, 1); // /limit size
371379

372380
if (ref_lzma) {
373381
#ifdef USE_LZMA
@@ -376,8 +384,8 @@ static struct digest {
376384
Trap0(RE_FEATURE_NA);
377385
#endif
378386
} else {
379-
int windowBits = MAX_WBITS;
380-
if (ref_gzip) windowBits |= 16;
387+
if (ref_defl) windowBits = -windowBits;
388+
else if (ref_gzip) windowBits |= 16;
381389
Set_Binary(D_RET, DecompressZlib(VAL_SERIES(data), VAL_INDEX(data), (REBINT)len, limit, windowBits));
382390
}
383391

src/core/u-compress.c

+7-2
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,11 @@ void Trap_ZStream_Error(z_stream *stream, int err, REBOOL while_compression)
172172
if (len < 0 || (index + len > BIN_LEN(input))) len = BIN_LEN(input) - index;
173173
if (limit > 0) {
174174
size = limit;
175+
} else if (windowBits < 0) {
176+
// limit was not specified, but data are supposed to be raw DEFLATE data
177+
// max teoretic DEFLATE ration is 1032:1, but that is quite unrealistic
178+
// it will be more around 3:1 or 4:1, so 10:1 could be enough for automatic setup.
179+
size = 10 * (REBCNT)len; //@@ fix me, if you don't agree with above claim
175180
} else {
176181
// Get the uncompressed size from last 4 source data bytes.
177182
if (len < 4) Trap0(RE_PAST_END); // !!! better msg needed
@@ -209,8 +214,8 @@ void Trap_ZStream_Error(z_stream *stream, int err, REBOOL while_compression)
209214
//printf("total_out: %i\n", stream.total_out);
210215
inflateEnd(&stream);
211216

212-
SET_STR_END(output, size);
213-
SERIES_TAIL(output) = size;
217+
SET_STR_END(output, stream.total_out);
218+
SERIES_TAIL(output) = stream.total_out;
214219

215220
return output;
216221
}

src/mezz/codec-zip.r

+1-8
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ register-codec [
1414

1515
decode: wrap [
1616
;- privates
17-
buffer: none ; shared binary used for decompression
1817
name: none
1918
method: none
2019
crc:
@@ -34,12 +33,7 @@ register-codec [
3433
]
3534
switch/default method [
3635
8 [ ;- deflate
37-
;@@ TODO: decompress should be able to deflate even without the header bytes!
38-
unless buffer [ buffer: make binary! unc-size ]
39-
insert buffer #{789C} ;ZLIB header
40-
append buffer copy/part data cmp-size
41-
output: decompress/zlib/size buffer unc-size
42-
clear buffer
36+
output: decompress/deflate/size data unc-size
4337
]
4438
14 [ ;- LZMA
4539
output: decompress/lzma/part/size skip data 4 cmp-size unc-size
@@ -219,7 +213,6 @@ register-codec [
219213
if verbose > 1 [sys/log/more 'ZIP ["Unknown ZIP signature:" mold skip to-binary type 4]]
220214
]
221215
]
222-
buffer: none ; cleanup
223216
new-line/skip result true 4
224217
result
225218
][

src/tests/units/compress-test.r3

+3
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ data: "test test test"
4343

4444
===start-group=== "GZIP compression / decompression"
4545

46+
--test-- "DEFLATE decompress"
47+
--assert #{74657374} = decompress/deflate #{2B492D2E01000C7E7FD804}
48+
4649
--test-- "GZIP compress/decompress"
4750
--assert data = to string! decompress/gzip compress/gzip data
4851

0 commit comments

Comments
 (0)