mirror of
https://github.com/zlib-ng/minizip-ng
synced 2026-08-25 14:26:08 -04:00
Add support for PPMd compression
This commit is contained in:
parent
92eecea9cd
commit
5880418f43
10 changed files with 617 additions and 6 deletions
9
.github/workflows/build.yml
vendored
9
.github/workflows/build.yml
vendored
|
|
@ -106,6 +106,15 @@ jobs:
|
|||
packages: clang-14 llvm-14
|
||||
gcov-exec: llvm-cov-14 gcov
|
||||
|
||||
- name: Ubuntu Clang No Ppmd
|
||||
os: ubuntu-latest
|
||||
compiler: clang-14
|
||||
cxx-compiler: clang++-14
|
||||
cmake-args: -D MZ_CODE_COVERAGE=ON -D MZ_PPMD=OFF
|
||||
codecov: ubuntu_clang_no_ppmd
|
||||
packages: clang-14 llvm-14
|
||||
gcov-exec: llvm-cov-14 gcov
|
||||
|
||||
- name: Ubuntu Clang No Pkcrypt
|
||||
os: ubuntu-latest
|
||||
compiler: clang-14
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ endif()
|
|||
|
||||
option(MZ_BZIP2 "Enables BZIP2 compression" ON)
|
||||
option(MZ_LZMA "Enables LZMA & XZ compression" ON)
|
||||
option(MZ_PPMD "Enables PPMD compression" ON)
|
||||
option(MZ_ZSTD "Enables ZSTD compression" ON)
|
||||
cmake_dependent_option(MZ_LIBCOMP "Enables Apple compression" ON "APPLE" OFF)
|
||||
option(MZ_FETCH_LIBS "Enables fetching third-party libraries if not found" ${WIN32})
|
||||
|
|
@ -363,6 +364,44 @@ if(MZ_LZMA)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if(MZ_PPMD)
|
||||
message(STATUS "Using PPMD")
|
||||
|
||||
clone_repo(ppmd https://github.com/ip7z/7zip "25.01")
|
||||
|
||||
# get the 7zip/PPMd version number
|
||||
file(READ "${PPMD_SOURCE_DIR}/C/7zVersion.h" version)
|
||||
string(REGEX MATCH "MY_VERSION_NUMBERS \"([0-9]*\.[0-9]*)\"" _ ${version})
|
||||
set(7ZIP_VERSION_NUMBER ${CMAKE_MATCH_1})
|
||||
message(STATUS " Found 7Zip/PPMd ${7ZIP_VERSION_NUMBER}")
|
||||
|
||||
# The PPMd repository does not support cmake so we have to create
|
||||
# a PPMd library ourselves
|
||||
set(PPMD_SRC
|
||||
${PPMD_SOURCE_DIR}/C/Ppmd8.c
|
||||
${PPMD_SOURCE_DIR}/C/Ppmd8Dec.c
|
||||
${PPMD_SOURCE_DIR}/C/Ppmd8Enc.c)
|
||||
|
||||
set(PPMD_HDR
|
||||
${PPMD_SOURCE_DIR}/C/7zTypes.h
|
||||
${PPMD_SOURCE_DIR}/C/Compiler.h
|
||||
${PPMD_SOURCE_DIR}/C/CpuArch.h
|
||||
${PPMD_SOURCE_DIR}/C/Ppmd.h
|
||||
${PPMD_SOURCE_DIR}/C/Ppmd8.h
|
||||
${PPMD_SOURCE_DIR}/C/Precomp.h)
|
||||
|
||||
add_library(ppmd STATIC ${PPMD_SRC} ${PPMD_HDR})
|
||||
|
||||
list(APPEND MINIZIP_DEP ppmd)
|
||||
list(APPEND MINIZIP_INC ${PPMD_SOURCE_DIR})
|
||||
list(APPEND MINIZIP_INC ${PPMD_INCLUDE_DIRS})
|
||||
|
||||
list(APPEND MINIZIP_DEP_PKG PPMD)
|
||||
list(APPEND MINIZIP_DEF -DHAVE_PPMD)
|
||||
list(APPEND MINIZIP_SRC mz_strm_ppmd.c)
|
||||
list(APPEND MINIZIP_HDR mz_strm_ppmd.h)
|
||||
endif()
|
||||
|
||||
if(MZ_ZSTD)
|
||||
# Check if zstd is present
|
||||
if(NOT MZ_FORCE_FETCH_LIBS)
|
||||
|
|
@ -418,7 +457,7 @@ if(MZ_ZSTD)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT MZ_LIBCOMP AND NOT MZ_ZLIB AND NOT MZ_ZSTD AND NOT MZ_BZIP2 AND NOT MZ_LZMA)
|
||||
if(NOT MZ_LIBCOMP AND NOT MZ_ZLIB AND NOT MZ_ZSTD AND NOT MZ_BZIP2 AND NOT MZ_LZMA AND NOT MZ_PPMD)
|
||||
message(STATUS "Compression not supported due to missing libraries")
|
||||
|
||||
list(APPEND MINIZIP_DEF -DMZ_ZIP_NO_DECOMPRESSION)
|
||||
|
|
@ -869,6 +908,10 @@ if(MZ_BUILD_TESTS AND MZ_BUILD_UNIT_TESTS)
|
|||
list(APPEND COMPRESS_METHOD_NAMES "xz")
|
||||
list(APPEND COMPRESS_METHOD_ARGS "-n")
|
||||
endif()
|
||||
if(MZ_PPMD)
|
||||
list(APPEND COMPRESS_METHOD_NAMES "ppmd")
|
||||
list(APPEND COMPRESS_METHOD_ARGS "-g")
|
||||
endif()
|
||||
if(MZ_ZSTD)
|
||||
list(APPEND COMPRESS_METHOD_NAMES "zstd")
|
||||
list(APPEND COMPRESS_METHOD_ARGS "-t")
|
||||
|
|
@ -1028,6 +1071,7 @@ add_feature_info(MZ_COMPAT MZ_COMPAT "Enables compatibility layer")
|
|||
add_feature_info(MZ_ZLIB MZ_ZLIB "Enables ZLIB compression")
|
||||
add_feature_info(MZ_BZIP2 MZ_BZIP2 "Enables BZIP2 compression")
|
||||
add_feature_info(MZ_LZMA MZ_LZMA "Enables LZMA & XZ compression")
|
||||
add_feature_info(MZ_PPMD MZ_PPMD "Enables PPMD compression")
|
||||
add_feature_info(MZ_ZSTD MZ_ZSTD "Enables ZSTD compression")
|
||||
add_feature_info(MZ_LIBCOMP MZ_LIBCOMP "Enables Apple compression")
|
||||
add_feature_info(MZ_FETCH_LIBS MZ_FETCH_LIBS "Enables fetching third-party libraries if not found")
|
||||
|
|
|
|||
11
minizip.c
11
minizip.c
|
|
@ -67,7 +67,7 @@ int32_t minizip_banner(void) {
|
|||
|
||||
int32_t minizip_help(void) {
|
||||
printf(
|
||||
"Usage: minizip [-x][-d dir|-l|-e][-o][-f][-y][-c cp][-a][-0 to -9][-b|-m|-t][-k 512][-p pwd][-s] file.zip "
|
||||
"Usage: minizip [-x][-d dir|-l|-e][-o][-f][-y][-c cp][-a][-0 to -9][-b|-m|-t|-g][-k 512][-p pwd][-s] file.zip "
|
||||
"[files]\n\n"
|
||||
" -x Extract files\n"
|
||||
" -l List files\n"
|
||||
|
|
@ -90,7 +90,8 @@ int32_t minizip_help(void) {
|
|||
" -b BZIP2 compression\n"
|
||||
" -m LZMA compression\n"
|
||||
" -n XZ compression\n"
|
||||
" -t ZSTD compression\n\n");
|
||||
" -t ZSTD compression\n"
|
||||
" -g PPMD compression\n\n");
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
|
|
@ -605,6 +606,12 @@ int main(int argc, const char *argv[]) {
|
|||
options.compress_method = MZ_COMPRESS_METHOD_BZIP2;
|
||||
# else
|
||||
err = MZ_SUPPORT_ERROR;
|
||||
# endif
|
||||
else if ((c == 'g') || (c == 'G'))
|
||||
# ifdef HAVE_PPMD
|
||||
options.compress_method = MZ_COMPRESS_METHOD_PPMD;
|
||||
# else
|
||||
err = MZ_SUPPORT_ERROR;
|
||||
# endif
|
||||
else if ((c == 'm') || (c == 'M'))
|
||||
# ifdef HAVE_LZMA
|
||||
|
|
|
|||
1
mz.h
1
mz.h
|
|
@ -67,6 +67,7 @@
|
|||
#define MZ_COMPRESS_METHOD_LZMA (14)
|
||||
#define MZ_COMPRESS_METHOD_ZSTD (93)
|
||||
#define MZ_COMPRESS_METHOD_XZ (95)
|
||||
#define MZ_COMPRESS_METHOD_PPMD (98)
|
||||
#define MZ_COMPRESS_METHOD_AES (99)
|
||||
|
||||
#define MZ_COMPRESS_LEVEL_DEFAULT (-1)
|
||||
|
|
|
|||
2
mz_os.h
2
mz_os.h
|
|
@ -27,7 +27,7 @@ extern "C" {
|
|||
# define MZ_VERSION_MADEBY_HOST_SYSTEM (MZ_HOST_SYSTEM_UNIX)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_LZMA) || defined(HAVE_LIBCOMP)
|
||||
#if defined(HAVE_LZMA) || defined(HAVE_LIBCOMP) || defined(HAVE_PPMD)
|
||||
# define MZ_VERSION_MADEBY_ZIP_VERSION (63)
|
||||
#elif defined(HAVE_WZAES)
|
||||
# define MZ_VERSION_MADEBY_ZIP_VERSION (51)
|
||||
|
|
|
|||
482
mz_strm_ppmd.c
Normal file
482
mz_strm_ppmd.c
Normal file
|
|
@ -0,0 +1,482 @@
|
|||
/* mz_strm_ppmd.c -- Stream for PPMd compress/decompress
|
||||
part of the minizip-ng project
|
||||
|
||||
Copyright (C) Nathan Moinvaziri
|
||||
https://github.com/zlib-ng/minizip-ng
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
#include <sys/param.h> // for MIN()
|
||||
#include <assert.h>
|
||||
|
||||
#include "mz.h"
|
||||
#include "mz_strm.h"
|
||||
#include "mz_strm_ppmd.h"
|
||||
|
||||
#include "C/Ppmd8.h"
|
||||
#include "C/7zTypes.h"
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static mz_stream_vtbl mz_stream_ppmd_vtbl = {
|
||||
mz_stream_ppmd_open, mz_stream_ppmd_is_open, mz_stream_ppmd_read, mz_stream_ppmd_write,
|
||||
mz_stream_ppmd_tell, mz_stream_ppmd_seek, mz_stream_ppmd_close, mz_stream_ppmd_error,
|
||||
mz_stream_ppmd_create, mz_stream_ppmd_delete, mz_stream_ppmd_get_prop_int64, mz_stream_ppmd_set_prop_int64};
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#define PPMD_PRESET_DEFAULT 9 // Should match default in 7-Zip
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
typedef struct mz_in_buffer_s {
|
||||
const void *src;
|
||||
size_t size;
|
||||
size_t pos;
|
||||
} mz_in_buffer;
|
||||
|
||||
typedef struct mz_out_buffer_s {
|
||||
void *dst;
|
||||
size_t size;
|
||||
size_t pos;
|
||||
} mz_out_buffer;
|
||||
|
||||
typedef struct mz_ppmd_info_s {
|
||||
/* hold CPpmd8 or CPpmd7 struct pointer */
|
||||
void *cPpmd;
|
||||
void *rc;
|
||||
mz_in_buffer *in;
|
||||
mz_out_buffer *out;
|
||||
int max_length;
|
||||
int result;
|
||||
void *t;
|
||||
} mz_ppmd_info;
|
||||
|
||||
typedef struct {
|
||||
/* Inherits from IByteIn */
|
||||
Byte (*read)(void *p);
|
||||
mz_in_buffer *in_buffer;
|
||||
void *t;
|
||||
} mz_buffer_reader;
|
||||
|
||||
typedef struct {
|
||||
/* Inherits from IByteOut */
|
||||
void (*write)(void *p, Byte b);
|
||||
mz_out_buffer *out_buffer;
|
||||
mz_ppmd_info *t;
|
||||
} mz_buffer_writer;
|
||||
|
||||
typedef struct mz_stream_ppmd_s {
|
||||
mz_stream stream;
|
||||
CPpmd8 ppmd8;
|
||||
uint8_t buffer[INT16_MAX];
|
||||
int64_t total_in;
|
||||
int64_t total_out;
|
||||
int64_t max_total_in;
|
||||
int32_t mode;
|
||||
int32_t error;
|
||||
int8_t initialized;
|
||||
ISzAlloc allocator;
|
||||
|
||||
// Write specific
|
||||
mz_buffer_writer writer;
|
||||
mz_out_buffer out;
|
||||
int32_t preset; // PPMD uses the term level for this
|
||||
|
||||
// Read Specific
|
||||
mz_buffer_reader reader;
|
||||
mz_in_buffer in;
|
||||
int8_t end_stream;
|
||||
} mz_stream_ppmd;
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/* malloc wrapper for PPMD library */
|
||||
static void *mz_ppmd_alloc_func(const ISzAlloc *p, size_t size) {
|
||||
MZ_UNUSED(p);
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
/* free wrapper for PPMD library */
|
||||
static void mz_ppmd_free_func(const ISzAlloc *p, void *address) {
|
||||
MZ_UNUSED(p);
|
||||
free(address);
|
||||
}
|
||||
|
||||
#ifndef MZ_ZIP_NO_COMPRESSION
|
||||
|
||||
static void writer(void *p, Byte b) {
|
||||
mz_buffer_writer *buffer_writer = (mz_buffer_writer *)p;
|
||||
if (buffer_writer->out_buffer->size == buffer_writer->out_buffer->pos) {
|
||||
return;
|
||||
}
|
||||
*((Byte *)buffer_writer->out_buffer->dst + buffer_writer->out_buffer->pos++) = b;
|
||||
}
|
||||
|
||||
static int32_t mz_stream_ppmd_flush(void *stream) {
|
||||
mz_stream_ppmd *ppmd = (mz_stream_ppmd *)stream;
|
||||
|
||||
if (ppmd->out.pos) {
|
||||
if (mz_stream_write(ppmd->stream.base, ppmd->out.dst, ppmd->out.pos) != ppmd->out.pos)
|
||||
return MZ_WRITE_ERROR;
|
||||
ppmd->total_out += ppmd->out.pos;
|
||||
ppmd->out.pos = 0;
|
||||
}
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
static void mz_setup_buffered_writer(mz_stream_ppmd *ppmd) {
|
||||
ppmd->out.dst = ppmd->buffer;
|
||||
ppmd->out.size = sizeof(ppmd->buffer); // INT16_MAX;
|
||||
ppmd->out.pos = 0;
|
||||
|
||||
ppmd->writer.write = writer;
|
||||
ppmd->writer.out_buffer = &ppmd->out;
|
||||
ppmd->ppmd8.Stream.Out = (IByteOut *)&ppmd->writer;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef MZ_ZIP_NO_DECOMPRESSION
|
||||
|
||||
static Byte reader(void *p) {
|
||||
mz_buffer_reader *buffer_reader = (mz_buffer_reader *)p;
|
||||
mz_stream_ppmd *ppmd = (mz_stream_ppmd *)buffer_reader->t;
|
||||
uint8_t b;
|
||||
int32_t status;
|
||||
|
||||
if ((status = mz_stream_read_uint8((mz_stream_ppmd *)ppmd->stream.base, &b)) != MZ_OK) {
|
||||
if (b == -1) // EOF
|
||||
ppmd->end_stream = 1;
|
||||
else
|
||||
ppmd->error = status;
|
||||
b = 0;
|
||||
} else
|
||||
++ppmd->total_in;
|
||||
|
||||
return (Byte)b;
|
||||
}
|
||||
|
||||
static void mz_setup_buffered_reader(mz_stream_ppmd *ppmd) {
|
||||
ppmd->in.src = ppmd->buffer;
|
||||
ppmd->in.size = sizeof(ppmd->buffer); // INT16_MAX;
|
||||
ppmd->in.pos = 0;
|
||||
|
||||
ppmd->reader.read = reader;
|
||||
ppmd->reader.in_buffer = &ppmd->in;
|
||||
ppmd->ppmd8.Stream.In = (IByteIn *)&ppmd->reader;
|
||||
|
||||
ppmd->reader.t = ppmd;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int32_t mz_stream_ppmd_open(void *stream, const char *path, int32_t mode) {
|
||||
mz_stream_ppmd *ppmd = (mz_stream_ppmd *)stream;
|
||||
|
||||
MZ_UNUSED(path);
|
||||
|
||||
Ppmd8_Construct(&ppmd->ppmd8);
|
||||
|
||||
if (mode & MZ_OPEN_MODE_WRITE) {
|
||||
#ifdef MZ_ZIP_NO_COMPRESSION
|
||||
MZ_UNUSED(stream);
|
||||
return MZ_SUPPORT_ERROR;
|
||||
#else
|
||||
/* PPMD8_MIN_ORDER (= 2) <= order <= PPMD8_MAX_ORDER (= 16)
|
||||
* 1MB (= 2* 0) <= memSize <= 256MB (= 2^ 8) (M = 2^ 20)
|
||||
* restor = 0 (PPMD8_RESTORE_METHOD_RESTART),
|
||||
* 1 (PPMD8_RESTORE_METHOD_CUT_OFF)
|
||||
*
|
||||
* Currently using 7-Zip-compatible values:
|
||||
* order = 3 + level
|
||||
* memory size = 2^ (level- 1) (MB) (level 9 treated as level 8.)
|
||||
* restoration method = 0 for level <= 6, 1 for level >= 7.
|
||||
*
|
||||
*/
|
||||
|
||||
/* PPMd parameters. */
|
||||
unsigned order;
|
||||
uint32_t mem_size;
|
||||
unsigned restor;
|
||||
uint16_t ppmd_param_word;
|
||||
|
||||
if (ppmd->preset < PPMD8_MIN_ORDER || ppmd->preset > PPMD8_MAX_ORDER)
|
||||
return MZ_OPEN_ERROR;
|
||||
|
||||
mz_setup_buffered_writer(ppmd);
|
||||
|
||||
order = ppmd->preset; /* 4, 5, 6, ..., 12. */
|
||||
mem_size = 1 << (MIN(ppmd->preset, 8) - 1); /* 1MB, 2MB, 4MB, ..., 128MB. */
|
||||
restor = (ppmd->preset <= 6 ? 0 : 1);
|
||||
|
||||
mem_size <<= 20; /* Convert B to MB. */
|
||||
|
||||
if (!Ppmd8_Alloc(&ppmd->ppmd8, mem_size, &ppmd->allocator)) {
|
||||
return MZ_MEM_ERROR;
|
||||
}
|
||||
|
||||
Ppmd8_Init_RangeEnc(&ppmd->ppmd8);
|
||||
Ppmd8_Init(&ppmd->ppmd8, order, restor);
|
||||
|
||||
/* wPPMd = (Model order - 1) +
|
||||
* ((Sub-allocator size - 1) << 4) +
|
||||
* (Model restoration method << 12)
|
||||
*
|
||||
* 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
|
||||
* Mdl_Res_Mth ___Sub-allocator_size-1 Mdl_Order-1
|
||||
*/
|
||||
|
||||
/* Form the PPMd properties word. Put out the bytes. */
|
||||
ppmd_param_word = ((order - 1) & 0xf) + ((((mem_size >> 20) - 1) & 0xff) << 4) + ((restor & 0xf) << 12);
|
||||
|
||||
// write header bytes directly to output buffer, bypassing the compression code
|
||||
// These bytes will be included in the compressed size stored in the zip metadata.
|
||||
|
||||
((uint8_t *)ppmd->out.dst)[0] = (uint8_t)(ppmd_param_word & 0xff);
|
||||
((uint8_t *)ppmd->out.dst)[1] = (uint8_t)(ppmd_param_word >> 8);
|
||||
ppmd->out.pos += 2;
|
||||
mz_stream_ppmd_flush(ppmd);
|
||||
#endif
|
||||
} else if (mode & MZ_OPEN_MODE_READ) {
|
||||
#ifdef MZ_ZIP_NO_DECOMPRESSION
|
||||
MZ_UNUSED(stream);
|
||||
return MZ_SUPPORT_ERROR;
|
||||
#else
|
||||
|
||||
uint8_t ppmd_props[2]; /* PPMd properties. */
|
||||
uint16_t ppmd_prop_word; /* PPMd properties. */
|
||||
|
||||
/* Initialize the 7-Zip I/O structure. */
|
||||
mz_setup_buffered_reader(ppmd);
|
||||
|
||||
/* Read & parse the 2 PPMD header bytes into a 16-bit word */
|
||||
if (mz_stream_read_uint8(ppmd->stream.base, &ppmd_props[0]) != MZ_OK ||
|
||||
mz_stream_read_uint8(ppmd->stream.base, &ppmd_props[1]) != MZ_OK)
|
||||
return MZ_STREAM_ERROR;
|
||||
ppmd_prop_word = ppmd_props[0] | (ppmd_props[1] << 8);
|
||||
ppmd->total_in += 2;
|
||||
|
||||
/* wPPMd = (Model order - 1) +
|
||||
* ((Sub-allocator size - 1) << 4) +
|
||||
* (Model restoration method << 12)
|
||||
*
|
||||
* 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
|
||||
* Mdl_Res_Mth ___Sub-allocator_size-1 Mdl_Order-1
|
||||
*/
|
||||
unsigned order = (ppmd_prop_word & 0xf) + 1;
|
||||
uint32_t mem_size = ((ppmd_prop_word >> 4) & 0xff) + 1;
|
||||
unsigned restor = (ppmd_prop_word >> 12);
|
||||
|
||||
/* Convert archive MB value into raw byte value. */
|
||||
mem_size <<= 20;
|
||||
|
||||
if ((order < PPMD8_MIN_ORDER) || (order > PPMD8_MAX_ORDER))
|
||||
return MZ_STREAM_ERROR;
|
||||
|
||||
if (!Ppmd8_Alloc(&ppmd->ppmd8, mem_size, &ppmd->allocator))
|
||||
return MZ_STREAM_ERROR;
|
||||
|
||||
if (!Ppmd8_Init_RangeDec(&ppmd->ppmd8))
|
||||
return MZ_STREAM_ERROR;
|
||||
|
||||
Ppmd8_Init(&ppmd->ppmd8, order, restor);
|
||||
#endif
|
||||
}
|
||||
|
||||
ppmd->initialized = 1;
|
||||
ppmd->mode = mode;
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_ppmd_is_open(void *stream) {
|
||||
mz_stream_ppmd *ppmd = (mz_stream_ppmd *)stream;
|
||||
if (ppmd->initialized != 1)
|
||||
return MZ_OPEN_ERROR;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_ppmd_read(void *stream, void *buf, int32_t size) {
|
||||
#ifdef MZ_ZIP_NO_DECOMPRESSION
|
||||
MZ_UNUSED(stream);
|
||||
MZ_UNUSED(buf);
|
||||
MZ_UNUSED(size);
|
||||
return MZ_SUPPORT_ERROR;
|
||||
#else
|
||||
mz_stream_ppmd *ppmd = (mz_stream_ppmd *)stream;
|
||||
uint8_t *next_out = buf;
|
||||
int32_t avail_out;
|
||||
int32_t avail_in = sizeof(ppmd->buffer);
|
||||
int sym = 0;
|
||||
int32_t written = 0;
|
||||
|
||||
if (ppmd->end_stream)
|
||||
return MZ_OK;
|
||||
|
||||
if (ppmd->max_total_in > 0 && avail_in > (ppmd->max_total_in - ppmd->total_in))
|
||||
avail_in = (int32_t)(ppmd->max_total_in - ppmd->total_in);
|
||||
|
||||
/* Decode input to fill the output buffer. */
|
||||
for (avail_out = size; avail_out > 0 && avail_in > 0; avail_out--, avail_in--) {
|
||||
sym = Ppmd8_DecodeSymbol(&ppmd->ppmd8);
|
||||
|
||||
if (sym < 0 || ppmd->end_stream || ppmd->error)
|
||||
break;
|
||||
|
||||
*(next_out++) = sym;
|
||||
++written;
|
||||
}
|
||||
|
||||
if (sym == -1) {
|
||||
// end_stream
|
||||
ppmd->end_stream = 1;
|
||||
|
||||
// Drop through and return written bytes
|
||||
} else if (sym == -2) {
|
||||
/* Insufficient input data. */
|
||||
return MZ_STREAM_ERROR;
|
||||
} else if (ppmd->error) {
|
||||
/* Invalid end of input data */
|
||||
return ppmd->error;
|
||||
}
|
||||
|
||||
ppmd->total_out += written;
|
||||
return written;
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t mz_stream_ppmd_write(void *stream, const void *buf, int32_t size) {
|
||||
#ifdef MZ_ZIP_NO_COMPRESSION
|
||||
MZ_UNUSED(stream);
|
||||
MZ_UNUSED(buf);
|
||||
MZ_UNUSED(size);
|
||||
return MZ_SUPPORT_ERROR;
|
||||
#else
|
||||
mz_stream_ppmd *ppmd = (mz_stream_ppmd *)stream;
|
||||
const uint8_t *buf_ptr = (const uint8_t *)buf;
|
||||
int32_t bytes_written = 0;
|
||||
|
||||
mz_setup_buffered_writer(ppmd);
|
||||
for (bytes_written = 0; bytes_written < size; bytes_written++) {
|
||||
if (ppmd->out.pos == ppmd->out.size) {
|
||||
if (mz_stream_ppmd_flush(ppmd) != MZ_OK)
|
||||
return MZ_WRITE_ERROR;
|
||||
}
|
||||
|
||||
Ppmd8_EncodeSymbol(&ppmd->ppmd8, buf_ptr[bytes_written]);
|
||||
}
|
||||
ppmd->total_in += size;
|
||||
|
||||
if (mz_stream_ppmd_flush(stream) != MZ_OK)
|
||||
return MZ_WRITE_ERROR;
|
||||
|
||||
return size;
|
||||
#endif
|
||||
}
|
||||
|
||||
int64_t mz_stream_ppmd_tell(void *stream) {
|
||||
mz_stream_ppmd *ppmd = (mz_stream_ppmd *)stream;
|
||||
return ppmd->total_in;
|
||||
}
|
||||
|
||||
int32_t mz_stream_ppmd_seek(void *stream, int64_t offset, int32_t origin) {
|
||||
MZ_UNUSED(stream);
|
||||
MZ_UNUSED(offset);
|
||||
MZ_UNUSED(origin);
|
||||
|
||||
return MZ_SEEK_ERROR;
|
||||
}
|
||||
|
||||
int32_t mz_stream_ppmd_close(void *stream) {
|
||||
mz_stream_ppmd *ppmd = (mz_stream_ppmd *)stream;
|
||||
|
||||
#ifndef MZ_ZIP_NO_COMPRESSION
|
||||
if (ppmd->mode & MZ_OPEN_MODE_WRITE) {
|
||||
mz_setup_buffered_writer(ppmd);
|
||||
|
||||
/* Encode end marker */
|
||||
Ppmd8_EncodeSymbol(&ppmd->ppmd8, -1);
|
||||
|
||||
Ppmd8_Flush_RangeEnc(&ppmd->ppmd8);
|
||||
|
||||
/* Flush any remaining buffered output */
|
||||
mz_stream_ppmd_flush(stream);
|
||||
}
|
||||
#endif
|
||||
|
||||
Ppmd8_Free(&ppmd->ppmd8, &ppmd->allocator);
|
||||
|
||||
ppmd->initialized = 0;
|
||||
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
int32_t mz_stream_ppmd_error(void *stream) {
|
||||
mz_stream_ppmd *ppmd = (mz_stream_ppmd *)stream;
|
||||
return ppmd->error;
|
||||
}
|
||||
|
||||
int32_t mz_stream_ppmd_get_prop_int64(void *stream, int32_t prop, int64_t *value) {
|
||||
mz_stream_ppmd *ppmd = (mz_stream_ppmd *)stream;
|
||||
|
||||
switch (prop) {
|
||||
case MZ_STREAM_PROP_TOTAL_IN:
|
||||
*value = ppmd->total_in;
|
||||
return MZ_OK;
|
||||
case MZ_STREAM_PROP_TOTAL_OUT:
|
||||
*value = ppmd->total_out;
|
||||
return MZ_OK;
|
||||
case MZ_STREAM_PROP_TOTAL_IN_MAX:
|
||||
*value = ppmd->max_total_in;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
return MZ_PARAM_ERROR;
|
||||
}
|
||||
|
||||
int32_t mz_stream_ppmd_set_prop_int64(void *stream, int32_t prop, int64_t value) {
|
||||
mz_stream_ppmd *ppmd = (mz_stream_ppmd *)stream;
|
||||
|
||||
switch (prop) {
|
||||
case MZ_STREAM_PROP_TOTAL_IN_MAX:
|
||||
ppmd->max_total_in = value;
|
||||
return MZ_OK;
|
||||
case MZ_STREAM_PROP_COMPRESS_LEVEL:
|
||||
if (value == MZ_COMPRESS_LEVEL_DEFAULT)
|
||||
ppmd->preset = PPMD_PRESET_DEFAULT;
|
||||
else
|
||||
ppmd->preset = (int16_t)value;
|
||||
return MZ_OK;
|
||||
}
|
||||
|
||||
return MZ_PARAM_ERROR;
|
||||
}
|
||||
|
||||
void *mz_stream_ppmd_create(void) {
|
||||
mz_stream_ppmd *ppmd = (mz_stream_ppmd *)calloc(1, sizeof(mz_stream_ppmd));
|
||||
if (ppmd) {
|
||||
ppmd->stream.vtbl = &mz_stream_ppmd_vtbl;
|
||||
ppmd->allocator.Alloc = mz_ppmd_alloc_func;
|
||||
ppmd->allocator.Free = mz_ppmd_free_func;
|
||||
ppmd->preset = PPMD_PRESET_DEFAULT;
|
||||
}
|
||||
return ppmd;
|
||||
}
|
||||
|
||||
void mz_stream_ppmd_delete(void **stream) {
|
||||
mz_stream_ppmd *ppmd = NULL;
|
||||
if (!stream)
|
||||
return;
|
||||
ppmd = (mz_stream_ppmd *)*stream;
|
||||
free(ppmd);
|
||||
*stream = NULL;
|
||||
}
|
||||
|
||||
void *mz_stream_ppmd_get_interface(void) {
|
||||
return (void *)&mz_stream_ppmd_vtbl;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
43
mz_strm_ppmd.h
Normal file
43
mz_strm_ppmd.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/* mz_strm_ppmd.h -- Stream for PPMd compress/decompress
|
||||
part of the minizip-ng project
|
||||
|
||||
Copyright (C) Nathan Moinvaziri
|
||||
https://github.com/zlib-ng/minizip-ng
|
||||
|
||||
This program is distributed under the terms of the same license as zlib.
|
||||
See the accompanying LICENSE file for the full text of the license.
|
||||
*/
|
||||
|
||||
#ifndef MZ_STREAM_PPMD_H
|
||||
#define MZ_STREAM_PPMD_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
int32_t mz_stream_ppmd_open(void *stream, const char *filename, int32_t mode);
|
||||
int32_t mz_stream_ppmd_is_open(void *stream);
|
||||
int32_t mz_stream_ppmd_read(void *stream, void *buf, int32_t size);
|
||||
int32_t mz_stream_ppmd_write(void *stream, const void *buf, int32_t size);
|
||||
int64_t mz_stream_ppmd_tell(void *stream);
|
||||
int32_t mz_stream_ppmd_seek(void *stream, int64_t offset, int32_t origin);
|
||||
int32_t mz_stream_ppmd_close(void *stream);
|
||||
int32_t mz_stream_ppmd_error(void *stream);
|
||||
|
||||
int32_t mz_stream_ppmd_get_prop_int64(void *stream, int32_t prop, int64_t *value);
|
||||
int32_t mz_stream_ppmd_set_prop_int64(void *stream, int32_t prop, int64_t value);
|
||||
|
||||
void *mz_stream_ppmd_create(void);
|
||||
void mz_stream_ppmd_delete(void **stream);
|
||||
|
||||
void *mz_stream_ppmd_get_interface(void);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
19
mz_zip.c
19
mz_zip.c
|
|
@ -32,6 +32,9 @@
|
|||
#ifdef HAVE_PKCRYPT
|
||||
# include "mz_strm_pkcrypt.h"
|
||||
#endif
|
||||
#ifdef HAVE_PPMD
|
||||
# include "mz_strm_ppmd.h"
|
||||
#endif
|
||||
#ifdef HAVE_WZAES
|
||||
# include "mz_strm_wzaes.h"
|
||||
#endif
|
||||
|
|
@ -41,7 +44,6 @@
|
|||
#ifdef HAVE_ZSTD
|
||||
# include "mz_strm_zstd.h"
|
||||
#endif
|
||||
|
||||
#include "mz_zip.h"
|
||||
|
||||
#include <ctype.h> /* tolower */
|
||||
|
|
@ -715,8 +717,9 @@ static int32_t mz_zip_entry_write_header(void *stream, uint8_t local, mz_zip_fil
|
|||
if ((file_info->flag & MZ_ZIP_FLAG_ENCRYPTED) && (file_info->aes_version))
|
||||
version_needed = 51;
|
||||
#endif
|
||||
#if defined(HAVE_LZMA) || defined(HAVE_LIBCOMP)
|
||||
#if defined(HAVE_LZMA) || defined(HAVE_LIBCOMP) || defined(HAVE_PPMD)
|
||||
if ((file_info->compression_method == MZ_COMPRESS_METHOD_LZMA) ||
|
||||
(file_info->compression_method == MZ_COMPRESS_METHOD_PPMD) ||
|
||||
(file_info->compression_method == MZ_COMPRESS_METHOD_XZ))
|
||||
version_needed = 63;
|
||||
#endif
|
||||
|
|
@ -1704,6 +1707,9 @@ static int32_t mz_zip_entry_open_int(void *handle, uint8_t raw, int16_t compress
|
|||
#if defined(HAVE_LZMA) || defined(HAVE_LIBCOMP)
|
||||
case MZ_COMPRESS_METHOD_XZ:
|
||||
#endif
|
||||
#ifdef HAVE_PPMD
|
||||
case MZ_COMPRESS_METHOD_PPMD:
|
||||
#endif
|
||||
#ifdef HAVE_ZSTD
|
||||
case MZ_COMPRESS_METHOD_ZSTD:
|
||||
#endif
|
||||
|
|
@ -1798,6 +1804,15 @@ static int32_t mz_zip_entry_open_int(void *handle, uint8_t raw, int16_t compress
|
|||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_PPMD
|
||||
else if (zip->file_info.compression_method == MZ_COMPRESS_METHOD_PPMD) {
|
||||
zip->compress_stream = mz_stream_ppmd_create();
|
||||
if (zip->compress_stream) {
|
||||
mz_stream_set_prop_int64(zip->compress_stream, MZ_STREAM_PROP_TOTAL_IN_MAX,
|
||||
zip->file_info.compressed_size);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_ZSTD
|
||||
else if (zip->file_info.compression_method == MZ_COMPRESS_METHOD_ZSTD)
|
||||
zip->compress_stream = mz_stream_zstd_create();
|
||||
|
|
|
|||
|
|
@ -1992,6 +1992,8 @@ void *mz_zip_writer_create(void) {
|
|||
writer->compress_method = MZ_COMPRESS_METHOD_BZIP2;
|
||||
#elif defined(HAVE_LZMA)
|
||||
writer->compress_method = MZ_COMPRESS_METHOD_LZMA;
|
||||
#elif defined(HAVE_PPMD)
|
||||
writer->compress_method = MZ_COMPRESS_METHOD_PPMD;
|
||||
#else
|
||||
writer->compress_method = MZ_COMPRESS_METHOD_STORE;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@
|
|||
#ifdef HAVE_LZMA
|
||||
# include "mz_strm_lzma.h"
|
||||
#endif
|
||||
#ifdef HAVE_PPMD
|
||||
# include "mz_strm_ppmd.h"
|
||||
#endif
|
||||
#ifdef HAVE_ZLIB
|
||||
# include "mz_strm_zlib.h"
|
||||
#endif
|
||||
|
|
@ -136,6 +139,11 @@ TEST(stream, lzma) {
|
|||
return test_compress("lzma", mz_stream_lzma_create);
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_PPMD
|
||||
TEST(stream, ppmd) {
|
||||
return test_compress("ppmd", mz_stream_ppmd_create);
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_ZLIB
|
||||
TEST(stream, zlib) {
|
||||
return test_compress("zlib", mz_stream_zlib_create);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue