mirror of
https://github.com/cuberite/libdeflate.git
synced 2025-09-10 04:41:45 -04:00
Merge pull request #63 from IzumiRaine/zlib-trailing-junk
Add function libdeflate_zlib_decompress_ex
This commit is contained in:
commit
a5cb1d7765
3
Makefile
3
Makefile
@ -216,7 +216,8 @@ TEST_PROG_SRC := programs/benchmark.c \
|
|||||||
programs/checksum.c \
|
programs/checksum.c \
|
||||||
programs/test_checksums.c \
|
programs/test_checksums.c \
|
||||||
programs/test_incomplete_codes.c \
|
programs/test_incomplete_codes.c \
|
||||||
programs/test_slow_decompression.c
|
programs/test_slow_decompression.c \
|
||||||
|
programs/test_zlib.c
|
||||||
|
|
||||||
NONTEST_PROGRAMS := $(NONTEST_PROG_SRC:programs/%.c=%$(PROG_SUFFIX))
|
NONTEST_PROGRAMS := $(NONTEST_PROG_SRC:programs/%.c=%$(PROG_SUFFIX))
|
||||||
DEFAULT_TARGETS += $(NONTEST_PROGRAMS)
|
DEFAULT_TARGETS += $(NONTEST_PROGRAMS)
|
||||||
|
@ -33,14 +33,16 @@
|
|||||||
#include "libdeflate.h"
|
#include "libdeflate.h"
|
||||||
|
|
||||||
LIBDEFLATEEXPORT enum libdeflate_result LIBDEFLATEAPI
|
LIBDEFLATEEXPORT enum libdeflate_result LIBDEFLATEAPI
|
||||||
libdeflate_zlib_decompress(struct libdeflate_decompressor *d,
|
libdeflate_zlib_decompress_ex(struct libdeflate_decompressor *d,
|
||||||
const void *in, size_t in_nbytes,
|
const void *in, size_t in_nbytes,
|
||||||
void *out, size_t out_nbytes_avail,
|
void *out, size_t out_nbytes_avail,
|
||||||
size_t *actual_out_nbytes_ret)
|
size_t *actual_in_nbytes_ret,
|
||||||
|
size_t *actual_out_nbytes_ret)
|
||||||
{
|
{
|
||||||
const u8 *in_next = in;
|
const u8 *in_next = in;
|
||||||
const u8 * const in_end = in_next + in_nbytes;
|
const u8 * const in_end = in_next + in_nbytes;
|
||||||
u16 hdr;
|
u16 hdr;
|
||||||
|
size_t actual_in_nbytes;
|
||||||
size_t actual_out_nbytes;
|
size_t actual_out_nbytes;
|
||||||
enum libdeflate_result result;
|
enum libdeflate_result result;
|
||||||
|
|
||||||
@ -68,10 +70,10 @@ libdeflate_zlib_decompress(struct libdeflate_decompressor *d,
|
|||||||
return LIBDEFLATE_BAD_DATA;
|
return LIBDEFLATE_BAD_DATA;
|
||||||
|
|
||||||
/* Compressed data */
|
/* Compressed data */
|
||||||
result = libdeflate_deflate_decompress(d, in_next,
|
result = libdeflate_deflate_decompress_ex(d, in_next,
|
||||||
in_end - ZLIB_FOOTER_SIZE - in_next,
|
in_end - ZLIB_FOOTER_SIZE - in_next,
|
||||||
out, out_nbytes_avail,
|
out, out_nbytes_avail,
|
||||||
actual_out_nbytes_ret);
|
&actual_in_nbytes, actual_out_nbytes_ret);
|
||||||
if (result != LIBDEFLATE_SUCCESS)
|
if (result != LIBDEFLATE_SUCCESS)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@ -80,12 +82,27 @@ libdeflate_zlib_decompress(struct libdeflate_decompressor *d,
|
|||||||
else
|
else
|
||||||
actual_out_nbytes = out_nbytes_avail;
|
actual_out_nbytes = out_nbytes_avail;
|
||||||
|
|
||||||
in_next = in_end - ZLIB_FOOTER_SIZE;
|
in_next += actual_in_nbytes;
|
||||||
|
|
||||||
/* ADLER32 */
|
/* ADLER32 */
|
||||||
if (libdeflate_adler32(1, out, actual_out_nbytes) !=
|
if (libdeflate_adler32(1, out, actual_out_nbytes) !=
|
||||||
get_unaligned_be32(in_next))
|
get_unaligned_be32(in_next))
|
||||||
return LIBDEFLATE_BAD_DATA;
|
return LIBDEFLATE_BAD_DATA;
|
||||||
|
in_next += 4;
|
||||||
|
|
||||||
|
if (actual_in_nbytes_ret)
|
||||||
|
*actual_in_nbytes_ret = in_next - (u8 *)in;
|
||||||
|
|
||||||
return LIBDEFLATE_SUCCESS;
|
return LIBDEFLATE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LIBDEFLATEEXPORT enum libdeflate_result LIBDEFLATEAPI
|
||||||
|
libdeflate_zlib_decompress(struct libdeflate_decompressor *d,
|
||||||
|
const void *in, size_t in_nbytes,
|
||||||
|
void *out, size_t out_nbytes_avail,
|
||||||
|
size_t *actual_out_nbytes_ret)
|
||||||
|
{
|
||||||
|
return libdeflate_zlib_decompress_ex(d, in, in_nbytes,
|
||||||
|
out, out_nbytes_avail,
|
||||||
|
NULL, actual_out_nbytes_ret);
|
||||||
|
}
|
||||||
|
18
libdeflate.h
18
libdeflate.h
@ -255,6 +255,10 @@ libdeflate_deflate_decompress_ex(struct libdeflate_decompressor *decompressor,
|
|||||||
/*
|
/*
|
||||||
* Like libdeflate_deflate_decompress(), but assumes the zlib wrapper format
|
* Like libdeflate_deflate_decompress(), but assumes the zlib wrapper format
|
||||||
* instead of raw DEFLATE.
|
* instead of raw DEFLATE.
|
||||||
|
*
|
||||||
|
* Decompression will stop at the end of the zlib stream, even if it is shorter
|
||||||
|
* than 'in_nbytes'. If you need to know exactly where the zlib stream ended,
|
||||||
|
* use libdeflate_zlib_decompress_ex().
|
||||||
*/
|
*/
|
||||||
LIBDEFLATEEXPORT enum libdeflate_result LIBDEFLATEAPI
|
LIBDEFLATEEXPORT enum libdeflate_result LIBDEFLATEAPI
|
||||||
libdeflate_zlib_decompress(struct libdeflate_decompressor *decompressor,
|
libdeflate_zlib_decompress(struct libdeflate_decompressor *decompressor,
|
||||||
@ -262,6 +266,20 @@ libdeflate_zlib_decompress(struct libdeflate_decompressor *decompressor,
|
|||||||
void *out, size_t out_nbytes_avail,
|
void *out, size_t out_nbytes_avail,
|
||||||
size_t *actual_out_nbytes_ret);
|
size_t *actual_out_nbytes_ret);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Like libdeflate_zlib_decompress(), but adds the 'actual_in_nbytes_ret'
|
||||||
|
* argument. If 'actual_in_nbytes_ret' is not NULL and the decompression
|
||||||
|
* succeeds (indicating that the first zlib-compressed stream in the input
|
||||||
|
* buffer was decompressed), then the actual number of input bytes consumed is
|
||||||
|
* written to *actual_in_nbytes_ret.
|
||||||
|
*/
|
||||||
|
LIBDEFLATEEXPORT enum libdeflate_result LIBDEFLATEAPI
|
||||||
|
libdeflate_zlib_decompress_ex(struct libdeflate_decompressor *decompressor,
|
||||||
|
const void *in, size_t in_nbytes,
|
||||||
|
void *out, size_t out_nbytes_avail,
|
||||||
|
size_t *actual_in_nbytes_ret,
|
||||||
|
size_t *actual_out_nbytes_ret);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Like libdeflate_deflate_decompress(), but assumes the gzip wrapper format
|
* Like libdeflate_deflate_decompress(), but assumes the gzip wrapper format
|
||||||
* instead of raw DEFLATE.
|
* instead of raw DEFLATE.
|
||||||
|
106
programs/test_zlib.c
Normal file
106
programs/test_zlib.c
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* test_zlib.c
|
||||||
|
*
|
||||||
|
* Verify that libdeflate_zlib_decompress and libdeflate_zlib_decompress_ex can
|
||||||
|
* correctly decompress the results of libdeflate_zlib_compress. Also checks
|
||||||
|
* whether decompression correctly handles additional trailing bytes in the
|
||||||
|
* compressed buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "test_util.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_decompress(u8 const* compressed, size_t compressed_nbytes,
|
||||||
|
u8 const* expected, size_t expected_nbytes)
|
||||||
|
{
|
||||||
|
struct libdeflate_decompressor* d = libdeflate_alloc_decompressor();
|
||||||
|
ASSERT(d != NULL);
|
||||||
|
|
||||||
|
size_t decompressed_nbytes = expected_nbytes;
|
||||||
|
u8 *decompressed = xmalloc(decompressed_nbytes);
|
||||||
|
|
||||||
|
size_t actual_decompressed_nbytes = 0;
|
||||||
|
enum libdeflate_result res =
|
||||||
|
libdeflate_zlib_decompress(d, compressed, compressed_nbytes,
|
||||||
|
decompressed, decompressed_nbytes,
|
||||||
|
&actual_decompressed_nbytes);
|
||||||
|
ASSERT(res == LIBDEFLATE_SUCCESS);
|
||||||
|
ASSERT(actual_decompressed_nbytes == expected_nbytes);
|
||||||
|
ASSERT(memcmp(expected, decompressed, expected_nbytes) == 0);
|
||||||
|
|
||||||
|
free(decompressed);
|
||||||
|
libdeflate_free_decompressor(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_decompress_ex(u8 const* compressed, size_t compressed_nbytes,
|
||||||
|
size_t expected_actual_compressed_nbytes,
|
||||||
|
u8 const* expected, size_t expected_nbytes)
|
||||||
|
{
|
||||||
|
struct libdeflate_decompressor* d = libdeflate_alloc_decompressor();
|
||||||
|
ASSERT(d != NULL);
|
||||||
|
|
||||||
|
size_t decompressed_nbytes = expected_nbytes;
|
||||||
|
u8 *decompressed = xmalloc(decompressed_nbytes);
|
||||||
|
|
||||||
|
size_t actual_compressed_nbytes = 0;
|
||||||
|
size_t actual_decompressed_nbytes = 0;
|
||||||
|
enum libdeflate_result res =
|
||||||
|
libdeflate_zlib_decompress_ex(d, compressed, compressed_nbytes,
|
||||||
|
decompressed, decompressed_nbytes,
|
||||||
|
&actual_compressed_nbytes,
|
||||||
|
&actual_decompressed_nbytes);
|
||||||
|
ASSERT(res == LIBDEFLATE_SUCCESS);
|
||||||
|
ASSERT(actual_compressed_nbytes == expected_actual_compressed_nbytes);
|
||||||
|
ASSERT(actual_decompressed_nbytes == expected_nbytes);
|
||||||
|
ASSERT(memcmp(expected, decompressed, expected_nbytes) == 0);
|
||||||
|
|
||||||
|
free(decompressed);
|
||||||
|
libdeflate_free_decompressor(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
tmain(int argc, tchar *argv[])
|
||||||
|
{
|
||||||
|
program_invocation_name = get_filename(argv[0]);
|
||||||
|
|
||||||
|
size_t original_nbytes = 32768;
|
||||||
|
u8 *original = xmalloc(original_nbytes);
|
||||||
|
|
||||||
|
/* Prepare some dummy data to compress */
|
||||||
|
for (size_t i = 0; i < original_nbytes; ++i) {
|
||||||
|
original[i] = (i % 123) + (i % 1023);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t compressed_nbytes_total = 32768;
|
||||||
|
u8 *compressed = xmalloc(compressed_nbytes_total);
|
||||||
|
memset(compressed, 0x00, compressed_nbytes_total);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't use the full buffer for compressed data, because we want to
|
||||||
|
* test whether decompression can deal with additional trailing bytes.
|
||||||
|
*/
|
||||||
|
size_t compressed_nbytes_avail = 30000;
|
||||||
|
ASSERT(compressed_nbytes_avail < compressed_nbytes_total);
|
||||||
|
|
||||||
|
struct libdeflate_compressor* c = libdeflate_alloc_compressor(6);
|
||||||
|
ASSERT(c != NULL);
|
||||||
|
size_t compressed_nbytes =
|
||||||
|
libdeflate_zlib_compress(c, original, original_nbytes,
|
||||||
|
compressed, compressed_nbytes_avail);
|
||||||
|
ASSERT(compressed_nbytes > 0);
|
||||||
|
libdeflate_free_compressor(c);
|
||||||
|
|
||||||
|
test_decompress(compressed, compressed_nbytes, original, original_nbytes);
|
||||||
|
test_decompress(compressed, compressed_nbytes_total, original, original_nbytes);
|
||||||
|
test_decompress_ex(compressed, compressed_nbytes_total, compressed_nbytes,
|
||||||
|
original, original_nbytes);
|
||||||
|
|
||||||
|
printf("libdeflate_zlib_* tests passed!\n");
|
||||||
|
|
||||||
|
free(compressed);
|
||||||
|
free(original);
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user