mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-22 07:31:57 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
411f60924f
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -16,3 +16,6 @@
|
|||||||
[submodule "contrib/cctz"]
|
[submodule "contrib/cctz"]
|
||||||
path = contrib/cctz
|
path = contrib/cctz
|
||||||
url = https://github.com/google/cctz.git
|
url = https://github.com/google/cctz.git
|
||||||
|
[submodule "contrib/zlib-ng"]
|
||||||
|
path = contrib/zlib-ng
|
||||||
|
url = https://github.com/Dead2/zlib-ng.git
|
||||||
|
@ -64,6 +64,13 @@ option (ENABLE_TESTS "Enables tests" ON)
|
|||||||
|
|
||||||
option (USE_STATIC_LIBRARIES "Set to FALSE to use shared libraries" ON)
|
option (USE_STATIC_LIBRARIES "Set to FALSE to use shared libraries" ON)
|
||||||
option (MAKE_STATIC_LIBRARIES "Set to FALSE to make shared libraries" ${USE_STATIC_LIBRARIES})
|
option (MAKE_STATIC_LIBRARIES "Set to FALSE to make shared libraries" ${USE_STATIC_LIBRARIES})
|
||||||
|
if (NOT MAKE_STATIC_LIBRARIES)
|
||||||
|
option (SPLIT_SHARED_LIBRARIES "DEV ONLY. Keep all internal libs as separate .so for faster linking" OFF)
|
||||||
|
endif ()
|
||||||
|
if (SPLIT_SHARED_LIBRARIES)
|
||||||
|
set (SPLIT_SHARED SHARED)
|
||||||
|
endif ()
|
||||||
|
|
||||||
if (USE_STATIC_LIBRARIES)
|
if (USE_STATIC_LIBRARIES)
|
||||||
list(REVERSE CMAKE_FIND_LIBRARY_SUFFIXES)
|
list(REVERSE CMAKE_FIND_LIBRARY_SUFFIXES)
|
||||||
endif ()
|
endif ()
|
||||||
@ -116,11 +123,13 @@ if (ARCHNATIVE)
|
|||||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} -march=native")
|
set (COMPILER_FLAGS "${COMPILER_FLAGS} -march=native")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
option (USE_LIBCXX "Use libc++ and libc++abi instead of libstdc++ (only make sense on Linux with Clang)" OFF)
|
if (CMAKE_SYSTEM MATCHES "Linux" AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
if (USE_LIBCXX)
|
option (USE_LIBCXX "Use libc++ and libc++abi instead of libstdc++ (only make sense on Linux with Clang)" ON)
|
||||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} -pthread") # NOTE: Why this is not the default and why this is needed only with libc++?
|
if (USE_LIBCXX)
|
||||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
set (COMPILER_FLAGS "${COMPILER_FLAGS} -pthread") # NOTE: Why this is not the default and why this is needed only with libc++?
|
||||||
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_LIBCPP_DEBUG=1") # More checks in debug build.
|
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||||
|
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_LIBCPP_DEBUG=1") # More checks in debug build.
|
||||||
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# Special options for better optimized code with clang
|
# Special options for better optimized code with clang
|
||||||
|
@ -6,6 +6,7 @@ endif ()
|
|||||||
|
|
||||||
if (NOT ZLIB_FOUND)
|
if (NOT ZLIB_FOUND)
|
||||||
set (USE_INTERNAL_ZLIB_LIBRARY 1)
|
set (USE_INTERNAL_ZLIB_LIBRARY 1)
|
||||||
|
set (ZLIB_COMPAT 1) # for zlib-ng, also enables WITH_GZFILEOP
|
||||||
set (ZLIB_INCLUDE_DIR "${ClickHouse_SOURCE_DIR}/contrib/libzlib-ng" "${ClickHouse_BINARY_DIR}/contrib/libzlib-ng") # generated zconf.h
|
set (ZLIB_INCLUDE_DIR "${ClickHouse_SOURCE_DIR}/contrib/libzlib-ng" "${ClickHouse_BINARY_DIR}/contrib/libzlib-ng") # generated zconf.h
|
||||||
set (ZLIB_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR}) # for poco
|
set (ZLIB_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR}) # for poco
|
||||||
set (ZLIB_FOUND 1) # for poco
|
set (ZLIB_FOUND 1) # for poco
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
get_property (dirs1 TARGET dbms PROPERTY INCLUDE_DIRECTORIES)
|
get_property (dirs1 TARGET dbms PROPERTY INCLUDE_DIRECTORIES)
|
||||||
list(APPEND dirs ${dirs1})
|
list(APPEND dirs ${dirs1})
|
||||||
|
|
||||||
|
get_property (dirs1 TARGET clickhouse_common_io PROPERTY INCLUDE_DIRECTORIES)
|
||||||
|
list(APPEND dirs ${dirs1})
|
||||||
|
|
||||||
get_property (dirs1 TARGET common PROPERTY INCLUDE_DIRECTORIES)
|
get_property (dirs1 TARGET common PROPERTY INCLUDE_DIRECTORIES)
|
||||||
list(APPEND dirs ${dirs1})
|
list(APPEND dirs ${dirs1})
|
||||||
|
|
||||||
|
6
contrib/CMakeLists.txt
vendored
6
contrib/CMakeLists.txt
vendored
@ -45,7 +45,11 @@ if (USE_INTERNAL_UNWIND_LIBRARY)
|
|||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (USE_INTERNAL_ZLIB_LIBRARY)
|
if (USE_INTERNAL_ZLIB_LIBRARY)
|
||||||
add_subdirectory (libzlib-ng)
|
add_subdirectory (zlib-ng)
|
||||||
|
# todo: make pull to Dead2/zlib-ng and remove:
|
||||||
|
# We should use same defines when including zlib.h as used when zlib compiled
|
||||||
|
target_compile_definitions (zlib PUBLIC ZLIB_COMPAT WITH_GZFILEOP)
|
||||||
|
target_compile_definitions (zlibstatic PUBLIC ZLIB_COMPAT WITH_GZFILEOP)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (USE_INTERNAL_CCTZ_LIBRARY)
|
if (USE_INTERNAL_CCTZ_LIBRARY)
|
||||||
|
52
contrib/libzlib-ng/.gitignore
vendored
52
contrib/libzlib-ng/.gitignore
vendored
@ -1,52 +0,0 @@
|
|||||||
*.diff
|
|
||||||
*.patch
|
|
||||||
*.orig
|
|
||||||
*.rej
|
|
||||||
|
|
||||||
*~
|
|
||||||
*.a
|
|
||||||
*.lo
|
|
||||||
*.o
|
|
||||||
*.dylib
|
|
||||||
|
|
||||||
*.gcda
|
|
||||||
*.gcno
|
|
||||||
*.gcov
|
|
||||||
|
|
||||||
/example
|
|
||||||
/example64
|
|
||||||
/examplesh
|
|
||||||
/libz.so*
|
|
||||||
/minigzip
|
|
||||||
/minigzip64
|
|
||||||
/minigzipsh
|
|
||||||
/zlib.pc
|
|
||||||
/CVE-2003-0107
|
|
||||||
|
|
||||||
.DS_Store
|
|
||||||
*.obj
|
|
||||||
*.exe
|
|
||||||
*.pdb
|
|
||||||
*.exp
|
|
||||||
*.lib
|
|
||||||
*.dll
|
|
||||||
*.res
|
|
||||||
foo.gz
|
|
||||||
*.manifest
|
|
||||||
|
|
||||||
CMakeCache.txt
|
|
||||||
CMakeFiles
|
|
||||||
Testing
|
|
||||||
*.cmake
|
|
||||||
*.stackdump
|
|
||||||
zconf.h
|
|
||||||
zconf.h.cmakein
|
|
||||||
zconf.h.included
|
|
||||||
ztest*
|
|
||||||
|
|
||||||
configure.log
|
|
||||||
a.out
|
|
||||||
|
|
||||||
/arch/arm/Makefile
|
|
||||||
/arch/generic/Makefile
|
|
||||||
/arch/x86/Makefile
|
|
@ -1,12 +0,0 @@
|
|||||||
language: c
|
|
||||||
compiler:
|
|
||||||
- gcc
|
|
||||||
- clang
|
|
||||||
env:
|
|
||||||
- BUILDDIR=. TOOL="./configure --zlib-compat"
|
|
||||||
- BUILDDIR=../build TOOL="../zlib-ng/configure --zlib-compat"
|
|
||||||
- BUILDDIR=. TOOL="./configure --zlib-compat --without-optimizations --without-new-strategies"
|
|
||||||
- BUILDDIR=. TOOL="cmake ."
|
|
||||||
- BUILDDIR=../build TOOL="cmake ../zlib-ng"
|
|
||||||
script: mkdir -p $BUILDDIR && cd $BUILDDIR &&
|
|
||||||
$TOOL && make && make test
|
|
@ -1,563 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 2.8.4)
|
|
||||||
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
|
|
||||||
|
|
||||||
project(zlib C)
|
|
||||||
|
|
||||||
set(VERSION "1.2.8")
|
|
||||||
|
|
||||||
set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
|
|
||||||
set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
|
|
||||||
set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers")
|
|
||||||
set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages")
|
|
||||||
set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files")
|
|
||||||
|
|
||||||
include(CheckTypeSize)
|
|
||||||
include(CheckSymbolExists)
|
|
||||||
include(CheckFunctionExists)
|
|
||||||
include(CheckIncludeFile)
|
|
||||||
include(CheckCSourceCompiles)
|
|
||||||
include(CheckCSourceRuns)
|
|
||||||
include(CheckLibraryExists)
|
|
||||||
include(FeatureSummary)
|
|
||||||
|
|
||||||
# make sure we use an appropriate BUILD_TYPE by default, "Release" to be exact
|
|
||||||
# this should select the maximum generic optimisation on the current platform (i.e. -O3 for gcc/clang)
|
|
||||||
if(NOT CMAKE_BUILD_TYPE)
|
|
||||||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
|
|
||||||
"Choose the type of build, standard options are: Debug Release RelWithDebInfo MinSizeRel."
|
|
||||||
FORCE)
|
|
||||||
add_feature_info(CMAKE_BUILD_TYPE 1 "Build type: ${CMAKE_BUILD_TYPE} (default)")
|
|
||||||
else()
|
|
||||||
add_feature_info(CMAKE_BUILD_TYPE 1 "Build type: ${CMAKE_BUILD_TYPE} (selected)")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
enable_testing()
|
|
||||||
|
|
||||||
check_include_file(sys/types.h HAVE_SYS_TYPES_H)
|
|
||||||
check_include_file(stdint.h HAVE_STDINT_H)
|
|
||||||
check_include_file(stddef.h HAVE_STDDEF_H)
|
|
||||||
|
|
||||||
#
|
|
||||||
# Options parsing
|
|
||||||
#
|
|
||||||
set(ARCH ${CMAKE_HOST_SYSTEM_PROCESSOR})
|
|
||||||
message(STATUS "Architecture: ${ARCH}")
|
|
||||||
|
|
||||||
option (ZLIB_COMPAT "Compile with zlib compatible API" OFF)
|
|
||||||
if (ZLIB_COMPAT)
|
|
||||||
add_definitions(-DZLIB_COMPAT)
|
|
||||||
set (WITH_GZFILEOP ON)
|
|
||||||
endif (ZLIB_COMPAT)
|
|
||||||
|
|
||||||
option (WITH_GZFILEOP "Compile with support for gzFile related functions" OFF)
|
|
||||||
if (WITH_GZFILEOP)
|
|
||||||
add_definitions(-DWITH_GZFILEOP)
|
|
||||||
endif (WITH_GZFILEOP)
|
|
||||||
|
|
||||||
option(WITH_OPTIM "Build with optimisation" ON)
|
|
||||||
option(WITH_NEW_QUICK_STRATEGY "Use new quick strategy for compression level 1" OFF) # this option produces corrupt gzip stream so turn it off for now.
|
|
||||||
option(WITH_NEW_MEDIUM_STRATEGY "Use new medium strategy for compression levels 4-6" ON)
|
|
||||||
option(WITH_NATIVE_INSTRUCTIONS
|
|
||||||
"Instruct the compiler to use the full instruction set on this host (gcc/clang -march=native)" OFF)
|
|
||||||
|
|
||||||
if(${CMAKE_C_COMPILER} MATCHES "icc" OR ${CMAKE_C_COMPILER} MATCHES "icpc" OR ${CMAKE_C_COMPILER} MATCHES "icl")
|
|
||||||
if(WITH_NATIVE_INSTRUCTIONS)
|
|
||||||
message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not supported on this configuration")
|
|
||||||
endif()
|
|
||||||
if(CMAKE_HOST_UNIX)
|
|
||||||
if(NOT SSE2FLAG)
|
|
||||||
set(SSE2FLAG "-msse2")
|
|
||||||
endif()
|
|
||||||
if(NOT SSE4FLAG)
|
|
||||||
set(SSE4FLAG "-msse4.2")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
if(NOT SSE2FLAG)
|
|
||||||
set(SSE2FLAG "/arch:SSE2")
|
|
||||||
endif()
|
|
||||||
if(NOT SSE4FLAG)
|
|
||||||
set(SSE4FLAG "/arch:SSE4.2")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
elseif(MSVC)
|
|
||||||
# TODO. ICC can be used through MSVC. I'm not sure if we'd ever see that combination
|
|
||||||
# (who'd use cmake from an IDE...) but checking for ICC before checking for MSVC should
|
|
||||||
# avoid mistakes.
|
|
||||||
# /Oi ?
|
|
||||||
if(NOT ${ARCH} MATCHES "AMD64")
|
|
||||||
set(SSE2FLAG "/arch:SSE2")
|
|
||||||
endif()
|
|
||||||
if(WITH_NATIVE_INSTRUCTIONS)
|
|
||||||
message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not supported on this configuration")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
execute_process(COMMAND ${CMAKE_C_COMPILER} --version OUTPUT_VARIABLE COMPILER_VERSION)
|
|
||||||
if("${COMPILER_VERSION}" MATCHES "gcc" OR "${COMPILER_VERSION}" MATCHES "clang")
|
|
||||||
set(__GNUC__ ON)
|
|
||||||
endif()
|
|
||||||
if(WITH_NATIVE_INSTRUCTIONS)
|
|
||||||
if(__GNUC__)
|
|
||||||
set(NATIVEFLAG "-march=native")
|
|
||||||
else()
|
|
||||||
message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not implemented yet on this configuration")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
if(NOT NATIVEFLAG)
|
|
||||||
if(NOT SSE2FLAG)
|
|
||||||
if(__GNUC__)
|
|
||||||
set(SSE2FLAG "-msse2")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
if(NOT SSE4FLAG)
|
|
||||||
if(__GNUC__)
|
|
||||||
set(SSE4FLAG "-msse4")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
if(NOT PCLMULFLAG)
|
|
||||||
if(__GNUC__)
|
|
||||||
set(PCLMULFLAG "-mpclmul")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
else(NOT NATIVEFLAG)
|
|
||||||
set(SSE2FLAG ${NATIVEFLAG})
|
|
||||||
set(SSE4FLAG ${NATIVEFLAG})
|
|
||||||
set(PCLMULFLAG ${NATIVEFLAG})
|
|
||||||
endif(NOT NATIVEFLAG)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_feature_info(ZLIB_COMPAT ZLIB_COMPAT "Provide a zlib-compatible API")
|
|
||||||
add_feature_info(WITH_GZFILEOP WITH_GZFILEOP "Compile with support for gzFile-related functions")
|
|
||||||
add_feature_info(WITH_OPTIM WITH_OPTIM "Build with optimisation")
|
|
||||||
add_feature_info(WITH_NEW_QUICK_STRATEGY WITH_NEW_QUICK_STRATEGY "Use new quick strategy for compression level 1")
|
|
||||||
add_feature_info(WITH_NEW_MEDIUM_STRATEGY WITH_NEW_MEDIUM_STRATEGY "Use new medium strategy for compression levels 4-6")
|
|
||||||
|
|
||||||
#
|
|
||||||
# Check to see if we have large file support
|
|
||||||
#
|
|
||||||
set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1)
|
|
||||||
# We add these other definitions here because CheckTypeSize.cmake
|
|
||||||
# in CMake 2.4.x does not automatically do so and we want
|
|
||||||
# compatibility with CMake 2.4.x.
|
|
||||||
if(HAVE_SYS_TYPES_H)
|
|
||||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H)
|
|
||||||
endif()
|
|
||||||
if(HAVE_STDINT_H)
|
|
||||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H)
|
|
||||||
endif()
|
|
||||||
if(HAVE_STDDEF_H)
|
|
||||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H)
|
|
||||||
endif()
|
|
||||||
check_type_size(off64_t OFF64_T)
|
|
||||||
if(HAVE_OFF64_T)
|
|
||||||
add_definitions(-D_LARGEFILE64_SOURCE=1)
|
|
||||||
else()
|
|
||||||
check_type_size(_off64_t _OFF64_T)
|
|
||||||
if (HAVE__OFF64_T)
|
|
||||||
add_definitions(-D_LARGEFILE64_SOURCE=1)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
set(CMAKE_REQUIRED_DEFINITIONS) # clear variable
|
|
||||||
|
|
||||||
#
|
|
||||||
# Check for fseeko and other optional functions
|
|
||||||
#
|
|
||||||
check_function_exists(fseeko HAVE_FSEEKO)
|
|
||||||
if(NOT HAVE_FSEEKO)
|
|
||||||
add_definitions(-DNO_FSEEKO)
|
|
||||||
endif()
|
|
||||||
check_function_exists(strerror HAVE_STRERROR)
|
|
||||||
if(NOT HAVE_STRERROR)
|
|
||||||
add_definitions(-DNO_STRERROR)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
#
|
|
||||||
# Check for unistd.h and stdarg.h
|
|
||||||
#
|
|
||||||
check_include_file(unistd.h Z_HAVE_UNISTD_H)
|
|
||||||
check_include_file(stdarg.h Z_HAVE_STDARG_H)
|
|
||||||
|
|
||||||
#
|
|
||||||
# Check if we can hide zlib internal symbols that are linked between separate source files using hidden
|
|
||||||
#
|
|
||||||
check_c_source_compiles(
|
|
||||||
"#define ZLIB_INTERNAL __attribute__((visibility (\"hidden\")))
|
|
||||||
int ZLIB_INTERNAL foo;
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}"
|
|
||||||
HAVE_ATTRIBUTE_VISIBILITY_HIDDEN FAIL_REGEX "not supported")
|
|
||||||
if(HAVE_ATTRIBUTE_VISIBILITY_HIDDEN)
|
|
||||||
add_definitions(-DHAVE_HIDDEN)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
#
|
|
||||||
# Check if we can hide zlib internal symbols that are linked between separate source files using internal
|
|
||||||
#
|
|
||||||
check_c_source_compiles(
|
|
||||||
"#define ZLIB_INTERNAL __attribute__((visibility (\"internal\")))
|
|
||||||
int ZLIB_INTERNAL foo;
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}"
|
|
||||||
HAVE_ATTRIBUTE_VISIBILITY_INTERNAL FAIL_REGEX "not supported")
|
|
||||||
if(HAVE_ATTRIBUTE_VISIBILITY_INTERNAL)
|
|
||||||
add_definitions(-DHAVE_INTERNAL)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
#
|
|
||||||
# check for __builtin_ctzl() support in the compiler
|
|
||||||
#
|
|
||||||
check_c_source_compiles(
|
|
||||||
"int main(void)
|
|
||||||
{
|
|
||||||
unsigned int zero = 0;
|
|
||||||
long test = __builtin_ctzl(zero);
|
|
||||||
(void)test;
|
|
||||||
return 0;
|
|
||||||
}"
|
|
||||||
HAVE_BUILTIN_CTZL
|
|
||||||
)
|
|
||||||
if(HAVE_BUILTIN_CTZL)
|
|
||||||
add_definitions(-DHAVE_BUILTIN_CTZL)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Macro to check if source compiles when cross-compiling
|
|
||||||
# or runs when compiling natively
|
|
||||||
macro(check_c_source_compile_or_run source flag)
|
|
||||||
if(CMAKE_CROSSCOMPILING)
|
|
||||||
check_c_source_compiles("${source}" ${flag})
|
|
||||||
else()
|
|
||||||
check_c_source_runs("${source}" ${flag})
|
|
||||||
endif()
|
|
||||||
endmacro(check_c_source_compile_or_run)
|
|
||||||
if(MSVC)
|
|
||||||
set(CMAKE_DEBUG_POSTFIX "d")
|
|
||||||
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
|
|
||||||
add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
|
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
else()
|
|
||||||
#
|
|
||||||
# not MSVC, so we need to check if we have the MS-style SSE etc. intrinsics
|
|
||||||
#
|
|
||||||
if(WITH_NATIVE_INSTRUCTIONS)
|
|
||||||
set(CMAKE_REQUIRED_FLAGS "${NATIVEFLAG}")
|
|
||||||
else()
|
|
||||||
set(CMAKE_REQUIRED_FLAGS "${SSE2FLAG}")
|
|
||||||
endif()
|
|
||||||
check_c_source_compile_or_run(
|
|
||||||
"#include <immintrin.h>
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
__m128i zero = _mm_setzero_si128();
|
|
||||||
(void)zero;
|
|
||||||
return 0;
|
|
||||||
}"
|
|
||||||
HAVE_SSE2_INTRIN
|
|
||||||
)
|
|
||||||
if(WITH_NATIVE_INSTRUCTIONS)
|
|
||||||
set(CMAKE_REQUIRED_FLAGS "${NATIVEFLAG}")
|
|
||||||
else()
|
|
||||||
# use the generic SSE4 enabler option to check for the SSE4.2 instruction we require:
|
|
||||||
set(CMAKE_REQUIRED_FLAGS "${SSE4FLAG}")
|
|
||||||
endif()
|
|
||||||
check_c_source_compile_or_run(
|
|
||||||
"int main(void)
|
|
||||||
{
|
|
||||||
unsigned val = 0, h = 0;
|
|
||||||
__asm__ __volatile__ ( \"crc32 %1,%0\" : \"+r\" (h) : \"r\" (val) );
|
|
||||||
return (int) h;
|
|
||||||
}"
|
|
||||||
HAVE_SSE42_INTRIN
|
|
||||||
)
|
|
||||||
if(WITH_NATIVE_INSTRUCTIONS)
|
|
||||||
set(CMAKE_REQUIRED_FLAGS "${NATIVEFLAG}")
|
|
||||||
else()
|
|
||||||
# the PCLMUL instruction we use also requires an SSE4.1 instruction check for both
|
|
||||||
set(CMAKE_REQUIRED_FLAGS "${SSE4FLAG} ${PCLMULFLAG}")
|
|
||||||
endif()
|
|
||||||
check_c_source_compile_or_run(
|
|
||||||
"#include <immintrin.h>
|
|
||||||
#include <smmintrin.h>
|
|
||||||
#include <wmmintrin.h>
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
__m128i a = _mm_setzero_si128();
|
|
||||||
__m128i b = _mm_setzero_si128();
|
|
||||||
__m128i c = _mm_clmulepi64_si128(a, b, 0x10);
|
|
||||||
int d = _mm_extract_epi32(c, 2);
|
|
||||||
return d;
|
|
||||||
}"
|
|
||||||
HAVE_PCLMULQDQ_INTRIN
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
#
|
|
||||||
# Enable deflate_medium at level 4-6
|
|
||||||
#
|
|
||||||
if(WITH_NEW_MEDIUM_STRATEGY)
|
|
||||||
add_definitions(-DMEDIUM_STRATEGY)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
#
|
|
||||||
# macro to add either the given intrinsics option to the global compiler options,
|
|
||||||
# or ${NATIVEFLAG} (-march=native) if that is appropriate and possible.
|
|
||||||
# An alternative version of this macro would take a file argument, and set ${flag}
|
|
||||||
# only for that file as opposed to ${NATIVEFLAG} globally, to limit side-effect of
|
|
||||||
# using ${flag} globally.
|
|
||||||
#
|
|
||||||
macro(add_intrinsics_option flag)
|
|
||||||
if(WITH_NATIVE_INSTRUCTIONS AND NATIVEFLAG)
|
|
||||||
if (NOT "${CMAKE_C_FLAGS} " MATCHES ".*${NATIVEFLAG} .*")
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${NATIVEFLAG}")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
if (NOT "${CMAKE_C_FLAGS} " MATCHES ".*${flag} .*")
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endmacro(add_intrinsics_option)
|
|
||||||
|
|
||||||
set(ZLIB_ARCH_SRCS)
|
|
||||||
set(ARCHDIR "arch/generic")
|
|
||||||
if("${ARCH}" MATCHES "x86_64" OR "${ARCH}" MATCHES "AMD64")
|
|
||||||
set(ARCHDIR "arch/x86")
|
|
||||||
add_definitions(-DX86_64 -DX86_NOCHECK_SSE2 -DUNALIGNED_OK -DUNROLL_LESS -DX86_CPUID)
|
|
||||||
add_feature_info(SSE2 1 "Use the SSE2 instruction set, using \"${SSE2FLAG}\"")
|
|
||||||
elseif("${ARCH}" MATCHES "arm" OR "${ARCH}" MATCHES "aarch64")
|
|
||||||
set(ARCHDIR "arch/arm")
|
|
||||||
add_definitions(-DUNALIGNED_OK -DUNROLL_LESS)
|
|
||||||
else()
|
|
||||||
set(ARCHDIR "arch/x86")
|
|
||||||
add_definitions(-DX86 -DUNALIGNED_OK -DUNROLL_LESS -DX86_CPUID)
|
|
||||||
add_feature_info(SSE2 1 "Support the SSE2 instruction set, using \"${SSE2FLAG}\"")
|
|
||||||
endif()
|
|
||||||
if(WITH_OPTIM)
|
|
||||||
if(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "arm" AND NOT CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
|
|
||||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/x86.c)
|
|
||||||
endif()
|
|
||||||
if(HAVE_SSE42_INTRIN)
|
|
||||||
add_definitions(-DX86_SSE4_2_CRC_HASH)
|
|
||||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/insert_string_sse.c)
|
|
||||||
add_feature_info(SSE4_CRC 1 "Support CRC hash generation using the SSE4.2 instruction set, using \"${SSE4FLAG}\"")
|
|
||||||
add_intrinsics_option("${SSE4FLAG}")
|
|
||||||
if(WITH_NEW_QUICK_STRATEGY)
|
|
||||||
add_definitions(-DX86_QUICK_STRATEGY)
|
|
||||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/deflate_quick.c)
|
|
||||||
add_feature_info(SSE4DEFLATE 1 "Support SSE4.2-accelerated quick decompression")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
if(HAVE_SSE2_INTRIN)
|
|
||||||
add_definitions(-DX86_SSE2_FILL_WINDOW)
|
|
||||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/fill_window_sse.c)
|
|
||||||
if(NOT ${ARCH} MATCHES "x86_64")
|
|
||||||
add_intrinsics_option("${SSE2FLAG}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
if(HAVE_PCLMULQDQ_INTRIN)
|
|
||||||
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^x86")
|
|
||||||
add_definitions(-DX86_PCLMULQDQ_CRC)
|
|
||||||
endif()
|
|
||||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/crc_folding.c)
|
|
||||||
add_feature_info(PCLMUL_CRC 1 "Support CRC hash generation using PCLMULQDQ, using \"${SSE4FLAG} ${PCLMULFLAG}\"")
|
|
||||||
add_intrinsics_option("${PCLMULFLAG}")
|
|
||||||
if(NOT HAVE_SSE42_INTRIN)
|
|
||||||
add_intrinsics_option("${SSE4FLAG}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
message(STATUS "Architecture-specific source files: ${ZLIB_ARCH_SRCS}")
|
|
||||||
|
|
||||||
#============================================================================
|
|
||||||
# zconf.h
|
|
||||||
#============================================================================
|
|
||||||
|
|
||||||
macro(generate_cmakein input output)
|
|
||||||
execute_process(COMMAND sed "/#define ZCONF_H/ a\\\n#cmakedefine Z_HAVE_UNISTD_H\\\n#cmakedefine Z_HAVE_STDARG_H\n"
|
|
||||||
INPUT_FILE ${input}
|
|
||||||
OUTPUT_FILE ${output}
|
|
||||||
)
|
|
||||||
|
|
||||||
endmacro(generate_cmakein)
|
|
||||||
|
|
||||||
generate_cmakein( ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.in ${CMAKE_CURRENT_BINARY_DIR}/zconf.h.cmakein )
|
|
||||||
|
|
||||||
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
|
|
||||||
# If we're doing an out of source build and the user has a zconf.h
|
|
||||||
# in their source tree...
|
|
||||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h)
|
|
||||||
message(STATUS "Renaming")
|
|
||||||
message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h")
|
|
||||||
message(STATUS "to 'zconf.h.included' because this file is included with zlib")
|
|
||||||
message(STATUS "but CMake generates it automatically in the build directory.")
|
|
||||||
file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# If we're doing an out of source build and the user has a zconf.h.cmakein
|
|
||||||
# in their source tree...
|
|
||||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein)
|
|
||||||
message(STATUS "Renaming")
|
|
||||||
message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein")
|
|
||||||
message(STATUS "to 'zconf.h.cmakeincluded' because this file is included with zlib")
|
|
||||||
message(STATUS "but CMake generates it automatically in the build directory.")
|
|
||||||
file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakeincluded)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc)
|
|
||||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein
|
|
||||||
${ZLIB_PC} @ONLY)
|
|
||||||
configure_file( ${CMAKE_CURRENT_BINARY_DIR}/zconf.h.cmakein
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY)
|
|
||||||
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
|
|
||||||
|
|
||||||
#============================================================================
|
|
||||||
# zlib
|
|
||||||
#============================================================================
|
|
||||||
|
|
||||||
set(ZLIB_PUBLIC_HDRS
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/zconf.h
|
|
||||||
zlib.h
|
|
||||||
)
|
|
||||||
set(ZLIB_PRIVATE_HDRS
|
|
||||||
crc32.h
|
|
||||||
deflate.h
|
|
||||||
gzguts.h
|
|
||||||
inffast.h
|
|
||||||
inffixed.h
|
|
||||||
inflate.h
|
|
||||||
inftrees.h
|
|
||||||
trees.h
|
|
||||||
zutil.h
|
|
||||||
)
|
|
||||||
set(ZLIB_SRCS
|
|
||||||
adler32.c
|
|
||||||
compress.c
|
|
||||||
crc32.c
|
|
||||||
deflate.c
|
|
||||||
deflate_fast.c
|
|
||||||
deflate_medium.c
|
|
||||||
deflate_slow.c
|
|
||||||
inflate.c
|
|
||||||
infback.c
|
|
||||||
inftrees.c
|
|
||||||
inffast.c
|
|
||||||
match.c
|
|
||||||
trees.c
|
|
||||||
uncompr.c
|
|
||||||
zutil.c
|
|
||||||
)
|
|
||||||
if (WITH_GZFILEOP)
|
|
||||||
set(ZLIB_GZFILE_SRCS
|
|
||||||
gzclose.c
|
|
||||||
gzlib.c
|
|
||||||
gzread.c
|
|
||||||
gzwrite.c
|
|
||||||
)
|
|
||||||
else (WITH_GZFILEOP)
|
|
||||||
set(ZLIB_GZFILE_SRCS
|
|
||||||
)
|
|
||||||
endif (WITH_GZFILEOP)
|
|
||||||
|
|
||||||
|
|
||||||
if(NOT MINGW AND NOT MSYS)
|
|
||||||
set(ZLIB_DLL_SRCS
|
|
||||||
win32/zlib1.rc # If present will override custom build rule below.
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# parse the full version number from zlib.h and include in ZLIB_FULL_VERSION
|
|
||||||
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents)
|
|
||||||
string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*"
|
|
||||||
"\\1" ZLIB_FULL_VERSION ${_zlib_h_contents})
|
|
||||||
|
|
||||||
if(MINGW OR MSYS)
|
|
||||||
# This gets us DLL resource information when compiling on MinGW.
|
|
||||||
if(NOT CMAKE_RC_COMPILER)
|
|
||||||
set(CMAKE_RC_COMPILER windres.exe)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
|
|
||||||
COMMAND ${CMAKE_RC_COMPILER}
|
|
||||||
-D GCC_WINDRES
|
|
||||||
-I ${CMAKE_CURRENT_SOURCE_DIR}
|
|
||||||
-I ${CMAKE_CURRENT_BINARY_DIR}
|
|
||||||
-o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
|
|
||||||
-i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc)
|
|
||||||
set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj)
|
|
||||||
endif(MINGW OR MSYS)
|
|
||||||
|
|
||||||
add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_GZFILE_SRCS} ${ZLIB_ARCH_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
|
|
||||||
add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_GZFILE_SRCS} ${ZLIB_ARCH_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
|
|
||||||
|
|
||||||
set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)
|
|
||||||
set_target_properties(zlib PROPERTIES SOVERSION 1)
|
|
||||||
|
|
||||||
if(NOT CYGWIN)
|
|
||||||
# This property causes shared libraries on Linux to have the full version
|
|
||||||
# encoded into their final filename. We disable this on Cygwin because
|
|
||||||
# it causes cygz-${ZLIB_FULL_VERSION}.dll to be created when cygz.dll
|
|
||||||
# seems to be the default.
|
|
||||||
#
|
|
||||||
# This has no effect with MSVC, on that platform the version info for
|
|
||||||
# the DLL comes from the resource file win32/zlib1.rc
|
|
||||||
set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(UNIX)
|
|
||||||
# On unix-like platforms the library is almost always called libz
|
|
||||||
set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z)
|
|
||||||
if(NOT APPLE)
|
|
||||||
set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"")
|
|
||||||
endif()
|
|
||||||
elseif(MSYS)
|
|
||||||
# Suppress version number from shared library name
|
|
||||||
set(CMAKE_SHARED_LIBRARY_NAME_WITH_VERSION 0)
|
|
||||||
elseif(BUILD_SHARED_LIBS AND WIN32)
|
|
||||||
# Creates zlib1.dll when building shared library version
|
|
||||||
set_target_properties(zlib PROPERTIES SUFFIX "1.dll")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL )
|
|
||||||
install(TARGETS zlib zlibstatic
|
|
||||||
RUNTIME DESTINATION "${INSTALL_BIN_DIR}"
|
|
||||||
ARCHIVE DESTINATION "${INSTALL_LIB_DIR}"
|
|
||||||
LIBRARY DESTINATION "${INSTALL_LIB_DIR}" )
|
|
||||||
endif()
|
|
||||||
if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL )
|
|
||||||
install(FILES ${ZLIB_PUBLIC_HDRS} DESTINATION "${INSTALL_INC_DIR}")
|
|
||||||
endif()
|
|
||||||
if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
|
|
||||||
install(FILES zlib.3 DESTINATION "${INSTALL_MAN_DIR}/man3")
|
|
||||||
endif()
|
|
||||||
if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
|
|
||||||
install(FILES ${ZLIB_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
#============================================================================
|
|
||||||
# Example binaries
|
|
||||||
#============================================================================
|
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
|
||||||
set (CMAKE_EXE_LINKER_FLAGS "")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
add_executable(example test/example.c)
|
|
||||||
target_link_libraries(example zlib)
|
|
||||||
add_test(example example)
|
|
||||||
|
|
||||||
add_executable(minigzip test/minigzip.c)
|
|
||||||
target_link_libraries(minigzip zlib)
|
|
||||||
|
|
||||||
if(HAVE_OFF64_T)
|
|
||||||
add_executable(example64 test/example.c)
|
|
||||||
target_link_libraries(example64 zlib)
|
|
||||||
set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
|
|
||||||
add_test(example64 example64)
|
|
||||||
|
|
||||||
add_executable(minigzip64 test/minigzip.c)
|
|
||||||
target_link_libraries(minigzip64 zlib)
|
|
||||||
set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
|
|
||||||
endif()
|
|
File diff suppressed because it is too large
Load Diff
@ -1,374 +0,0 @@
|
|||||||
##
|
|
||||||
# THIS IS AN UNMAINTAINED COPY OF THE ORIGINAL FILE DISTRIBUTED WITH ZLIB 1.2.8
|
|
||||||
##
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Frequently Asked Questions about zlib
|
|
||||||
|
|
||||||
|
|
||||||
If your question is not there, please check the zlib home page
|
|
||||||
http://zlib.net/ which may have more recent information.
|
|
||||||
The lastest zlib FAQ is at http://zlib.net/zlib_faq.html
|
|
||||||
|
|
||||||
|
|
||||||
1. Is zlib Y2K-compliant?
|
|
||||||
|
|
||||||
Yes. zlib doesn't handle dates.
|
|
||||||
|
|
||||||
2. Where can I get a Windows DLL version?
|
|
||||||
|
|
||||||
The zlib sources can be compiled without change to produce a DLL. See the
|
|
||||||
file win32/DLL_FAQ.txt in the zlib distribution. Pointers to the
|
|
||||||
precompiled DLL are found in the zlib web site at http://zlib.net/ .
|
|
||||||
|
|
||||||
3. Where can I get a Visual Basic interface to zlib?
|
|
||||||
|
|
||||||
See
|
|
||||||
* http://marknelson.us/1997/01/01/zlib-engine/
|
|
||||||
* win32/DLL_FAQ.txt in the zlib distribution
|
|
||||||
|
|
||||||
4. compress() returns Z_BUF_ERROR.
|
|
||||||
|
|
||||||
Make sure that before the call of compress(), the length of the compressed
|
|
||||||
buffer is equal to the available size of the compressed buffer and not
|
|
||||||
zero. For Visual Basic, check that this parameter is passed by reference
|
|
||||||
("as any"), not by value ("as long").
|
|
||||||
|
|
||||||
5. deflate() or inflate() returns Z_BUF_ERROR.
|
|
||||||
|
|
||||||
Before making the call, make sure that avail_in and avail_out are not zero.
|
|
||||||
When setting the parameter flush equal to Z_FINISH, also make sure that
|
|
||||||
avail_out is big enough to allow processing all pending input. Note that a
|
|
||||||
Z_BUF_ERROR is not fatal--another call to deflate() or inflate() can be
|
|
||||||
made with more input or output space. A Z_BUF_ERROR may in fact be
|
|
||||||
unavoidable depending on how the functions are used, since it is not
|
|
||||||
possible to tell whether or not there is more output pending when
|
|
||||||
strm.avail_out returns with zero. See http://zlib.net/zlib_how.html for a
|
|
||||||
heavily annotated example.
|
|
||||||
|
|
||||||
6. Where's the zlib documentation (man pages, etc.)?
|
|
||||||
|
|
||||||
It's in zlib.h . Examples of zlib usage are in the files test/example.c
|
|
||||||
and test/minigzip.c, with more in examples/ .
|
|
||||||
|
|
||||||
7. Why don't you use GNU autoconf or libtool or ...?
|
|
||||||
|
|
||||||
Because we would like to keep zlib as a very small and simple package.
|
|
||||||
zlib is rather portable and doesn't need much configuration.
|
|
||||||
|
|
||||||
8. I found a bug in zlib.
|
|
||||||
|
|
||||||
Most of the time, such problems are due to an incorrect usage of zlib.
|
|
||||||
Please try to reproduce the problem with a small program and send the
|
|
||||||
corresponding source to us at zlib@gzip.org . Do not send multi-megabyte
|
|
||||||
data files without prior agreement.
|
|
||||||
|
|
||||||
9. Why do I get "undefined reference to gzputc"?
|
|
||||||
|
|
||||||
If "make test" produces something like
|
|
||||||
|
|
||||||
example.o(.text+0x154): undefined reference to `gzputc'
|
|
||||||
|
|
||||||
check that you don't have old files libz.* in /usr/lib, /usr/local/lib or
|
|
||||||
/usr/X11R6/lib. Remove any old versions, then do "make install".
|
|
||||||
|
|
||||||
10. I need a Delphi interface to zlib.
|
|
||||||
|
|
||||||
See the contrib/delphi directory in the zlib distribution.
|
|
||||||
|
|
||||||
11. Can zlib handle .zip archives?
|
|
||||||
|
|
||||||
Not by itself, no. See the directory contrib/minizip in the zlib
|
|
||||||
distribution.
|
|
||||||
|
|
||||||
12. Can zlib handle .Z files?
|
|
||||||
|
|
||||||
No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt
|
|
||||||
the code of uncompress on your own.
|
|
||||||
|
|
||||||
13. How can I make a Unix shared library?
|
|
||||||
|
|
||||||
By default a shared (and a static) library is built for Unix. So:
|
|
||||||
|
|
||||||
make distclean
|
|
||||||
./configure
|
|
||||||
make
|
|
||||||
|
|
||||||
14. How do I install a shared zlib library on Unix?
|
|
||||||
|
|
||||||
After the above, then:
|
|
||||||
|
|
||||||
make install
|
|
||||||
|
|
||||||
However, many flavors of Unix come with a shared zlib already installed.
|
|
||||||
Before going to the trouble of compiling a shared version of zlib and
|
|
||||||
trying to install it, you may want to check if it's already there! If you
|
|
||||||
can #include <zlib.h>, it's there. The -lz option will probably link to
|
|
||||||
it. You can check the version at the top of zlib.h or with the
|
|
||||||
ZLIB_VERSION symbol defined in zlib.h .
|
|
||||||
|
|
||||||
15. I have a question about OttoPDF.
|
|
||||||
|
|
||||||
We are not the authors of OttoPDF. The real author is on the OttoPDF web
|
|
||||||
site: Joel Hainley, jhainley@myndkryme.com.
|
|
||||||
|
|
||||||
16. Can zlib decode Flate data in an Adobe PDF file?
|
|
||||||
|
|
||||||
Yes. See http://www.pdflib.com/ . To modify PDF forms, see
|
|
||||||
http://sourceforge.net/projects/acroformtool/ .
|
|
||||||
|
|
||||||
17. Why am I getting this "register_frame_info not found" error on Solaris?
|
|
||||||
|
|
||||||
After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib
|
|
||||||
generates an error such as:
|
|
||||||
|
|
||||||
ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so:
|
|
||||||
symbol __register_frame_info: referenced symbol not found
|
|
||||||
|
|
||||||
The symbol __register_frame_info is not part of zlib, it is generated by
|
|
||||||
the C compiler (cc or gcc). You must recompile applications using zlib
|
|
||||||
which have this problem. This problem is specific to Solaris. See
|
|
||||||
http://www.sunfreeware.com for Solaris versions of zlib and applications
|
|
||||||
using zlib.
|
|
||||||
|
|
||||||
18. Why does gzip give an error on a file I make with compress/deflate?
|
|
||||||
|
|
||||||
The compress and deflate functions produce data in the zlib format, which
|
|
||||||
is different and incompatible with the gzip format. The gz* functions in
|
|
||||||
zlib on the other hand use the gzip format. Both the zlib and gzip formats
|
|
||||||
use the same compressed data format internally, but have different headers
|
|
||||||
and trailers around the compressed data.
|
|
||||||
|
|
||||||
19. Ok, so why are there two different formats?
|
|
||||||
|
|
||||||
The gzip format was designed to retain the directory information about a
|
|
||||||
single file, such as the name and last modification date. The zlib format
|
|
||||||
on the other hand was designed for in-memory and communication channel
|
|
||||||
applications, and has a much more compact header and trailer and uses a
|
|
||||||
faster integrity check than gzip.
|
|
||||||
|
|
||||||
20. Well that's nice, but how do I make a gzip file in memory?
|
|
||||||
|
|
||||||
You can request that deflate write the gzip format instead of the zlib
|
|
||||||
format using deflateInit2(). You can also request that inflate decode the
|
|
||||||
gzip format using inflateInit2(). Read zlib.h for more details.
|
|
||||||
|
|
||||||
21. Is zlib thread-safe?
|
|
||||||
|
|
||||||
Yes. However any library routines that zlib uses and any application-
|
|
||||||
provided memory allocation routines must also be thread-safe. zlib's gz*
|
|
||||||
functions use stdio library routines, and most of zlib's functions use the
|
|
||||||
library memory allocation routines by default. zlib's *Init* functions
|
|
||||||
allow for the application to provide custom memory allocation routines.
|
|
||||||
|
|
||||||
Of course, you should only operate on any given zlib or gzip stream from a
|
|
||||||
single thread at a time.
|
|
||||||
|
|
||||||
22. Can I use zlib in my commercial application?
|
|
||||||
|
|
||||||
Yes. Please read the license in zlib.h.
|
|
||||||
|
|
||||||
23. Is zlib under the GNU license?
|
|
||||||
|
|
||||||
No. Please read the license in zlib.h.
|
|
||||||
|
|
||||||
24. The license says that altered source versions must be "plainly marked". So
|
|
||||||
what exactly do I need to do to meet that requirement?
|
|
||||||
|
|
||||||
You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In
|
|
||||||
particular, the final version number needs to be changed to "f", and an
|
|
||||||
identification string should be appended to ZLIB_VERSION. Version numbers
|
|
||||||
x.x.x.f are reserved for modifications to zlib by others than the zlib
|
|
||||||
maintainers. For example, if the version of the base zlib you are altering
|
|
||||||
is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and
|
|
||||||
ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also
|
|
||||||
update the version strings in deflate.c and inftrees.c.
|
|
||||||
|
|
||||||
For altered source distributions, you should also note the origin and
|
|
||||||
nature of the changes in zlib.h, as well as in ChangeLog and README, along
|
|
||||||
with the dates of the alterations. The origin should include at least your
|
|
||||||
name (or your company's name), and an email address to contact for help or
|
|
||||||
issues with the library.
|
|
||||||
|
|
||||||
Note that distributing a compiled zlib library along with zlib.h and
|
|
||||||
zconf.h is also a source distribution, and so you should change
|
|
||||||
ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes
|
|
||||||
in zlib.h as you would for a full source distribution.
|
|
||||||
|
|
||||||
25. Will zlib work on a big-endian or little-endian architecture, and can I
|
|
||||||
exchange compressed data between them?
|
|
||||||
|
|
||||||
Yes and yes.
|
|
||||||
|
|
||||||
26. Will zlib work on a 64-bit machine?
|
|
||||||
|
|
||||||
Yes. It has been tested on 64-bit machines, and has no dependence on any
|
|
||||||
data types being limited to 32-bits in length. If you have any
|
|
||||||
difficulties, please provide a complete problem report to zlib@gzip.org
|
|
||||||
|
|
||||||
27. Will zlib decompress data from the PKWare Data Compression Library?
|
|
||||||
|
|
||||||
No. The PKWare DCL uses a completely different compressed data format than
|
|
||||||
does PKZIP and zlib. However, you can look in zlib's contrib/blast
|
|
||||||
directory for a possible solution to your problem.
|
|
||||||
|
|
||||||
28. Can I access data randomly in a compressed stream?
|
|
||||||
|
|
||||||
No, not without some preparation. If when compressing you periodically use
|
|
||||||
Z_FULL_FLUSH, carefully write all the pending data at those points, and
|
|
||||||
keep an index of those locations, then you can start decompression at those
|
|
||||||
points. You have to be careful to not use Z_FULL_FLUSH too often, since it
|
|
||||||
can significantly degrade compression. Alternatively, you can scan a
|
|
||||||
deflate stream once to generate an index, and then use that index for
|
|
||||||
random access. See examples/zran.c .
|
|
||||||
|
|
||||||
29. Does zlib work on MVS, OS/390, CICS, etc.?
|
|
||||||
|
|
||||||
It has in the past, but we have not heard of any recent evidence. There
|
|
||||||
were working ports of zlib 1.1.4 to MVS, but those links no longer work.
|
|
||||||
If you know of recent, successful applications of zlib on these operating
|
|
||||||
systems, please let us know. Thanks.
|
|
||||||
|
|
||||||
30. Is there some simpler, easier to read version of inflate I can look at to
|
|
||||||
understand the deflate format?
|
|
||||||
|
|
||||||
First off, you should read RFC 1951. Second, yes. Look in zlib's
|
|
||||||
contrib/puff directory.
|
|
||||||
|
|
||||||
31. Does zlib infringe on any patents?
|
|
||||||
|
|
||||||
As far as we know, no. In fact, that was originally the whole point behind
|
|
||||||
zlib. Look here for some more information:
|
|
||||||
|
|
||||||
http://www.gzip.org/#faq11
|
|
||||||
|
|
||||||
32. Can zlib work with greater than 4 GB of data?
|
|
||||||
|
|
||||||
Yes. inflate() and deflate() will process any amount of data correctly.
|
|
||||||
Each call of inflate() or deflate() is limited to input and output chunks
|
|
||||||
of the maximum value that can be stored in the compiler's "unsigned int"
|
|
||||||
type, but there is no limit to the number of chunks. Note however that the
|
|
||||||
strm.total_in and strm_total_out counters may be limited to 4 GB. These
|
|
||||||
counters are provided as a convenience and are not used internally by
|
|
||||||
inflate() or deflate(). The application can easily set up its own counters
|
|
||||||
updated after each call of inflate() or deflate() to count beyond 4 GB.
|
|
||||||
compress() and uncompress() may be limited to 4 GB, since they operate in a
|
|
||||||
single call. gzseek() and gztell() may be limited to 4 GB depending on how
|
|
||||||
zlib is compiled. See the zlibCompileFlags() function in zlib.h.
|
|
||||||
|
|
||||||
The word "may" appears several times above since there is a 4 GB limit only
|
|
||||||
if the compiler's "long" type is 32 bits. If the compiler's "long" type is
|
|
||||||
64 bits, then the limit is 16 exabytes.
|
|
||||||
|
|
||||||
33. Does zlib have any security vulnerabilities?
|
|
||||||
|
|
||||||
The only one that we are aware of is potentially in gzprintf(). If zlib is
|
|
||||||
compiled to use sprintf() or vsprintf(), then there is no protection
|
|
||||||
against a buffer overflow of an 8K string space (or other value as set by
|
|
||||||
gzbuffer()), other than the caller of gzprintf() assuring that the output
|
|
||||||
will not exceed 8K. On the other hand, if zlib is compiled to use
|
|
||||||
snprintf() or vsnprintf(), which should normally be the case, then there is
|
|
||||||
no vulnerability. The ./configure script will display warnings if an
|
|
||||||
insecure variation of sprintf() will be used by gzprintf(). Also the
|
|
||||||
zlibCompileFlags() function will return information on what variant of
|
|
||||||
sprintf() is used by gzprintf().
|
|
||||||
|
|
||||||
If you don't have snprintf() or vsnprintf() and would like one, you can
|
|
||||||
find a portable implementation here:
|
|
||||||
|
|
||||||
http://www.ijs.si/software/snprintf/
|
|
||||||
|
|
||||||
Note that you should be using the most recent version of zlib. Versions
|
|
||||||
1.1.3 and before were subject to a double-free vulnerability, and versions
|
|
||||||
1.2.1 and 1.2.2 were subject to an access exception when decompressing
|
|
||||||
invalid compressed data.
|
|
||||||
|
|
||||||
34. Is there a Java version of zlib?
|
|
||||||
|
|
||||||
Probably what you want is to use zlib in Java. zlib is already included
|
|
||||||
as part of the Java SDK in the java.util.zip package. If you really want
|
|
||||||
a version of zlib written in the Java language, look on the zlib home
|
|
||||||
page for links: http://zlib.net/ .
|
|
||||||
|
|
||||||
35. I get this or that compiler or source-code scanner warning when I crank it
|
|
||||||
up to maximally-pedantic. Can't you guys write proper code?
|
|
||||||
|
|
||||||
Many years ago, we gave up attempting to avoid warnings on every compiler
|
|
||||||
in the universe. It just got to be a waste of time, and some compilers
|
|
||||||
were downright silly as well as contradicted each other. So now, we simply
|
|
||||||
make sure that the code always works.
|
|
||||||
|
|
||||||
36. Valgrind (or some similar memory access checker) says that deflate is
|
|
||||||
performing a conditional jump that depends on an uninitialized value.
|
|
||||||
Isn't that a bug?
|
|
||||||
|
|
||||||
No. That is intentional for performance reasons, and the output of deflate
|
|
||||||
is not affected. This only started showing up recently since zlib 1.2.x
|
|
||||||
uses malloc() by default for allocations, whereas earlier versions used
|
|
||||||
calloc(), which zeros out the allocated memory. Even though the code was
|
|
||||||
correct, versions 1.2.4 and later was changed to not stimulate these
|
|
||||||
checkers.
|
|
||||||
|
|
||||||
37. Will zlib read the (insert any ancient or arcane format here) compressed
|
|
||||||
data format?
|
|
||||||
|
|
||||||
Probably not. Look in the comp.compression FAQ for pointers to various
|
|
||||||
formats and associated software.
|
|
||||||
|
|
||||||
38. How can I encrypt/decrypt zip files with zlib?
|
|
||||||
|
|
||||||
zlib doesn't support encryption. The original PKZIP encryption is very
|
|
||||||
weak and can be broken with freely available programs. To get strong
|
|
||||||
encryption, use GnuPG, http://www.gnupg.org/ , which already includes zlib
|
|
||||||
compression. For PKZIP compatible "encryption", look at
|
|
||||||
http://www.info-zip.org/
|
|
||||||
|
|
||||||
39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
|
|
||||||
|
|
||||||
"gzip" is the gzip format, and "deflate" is the zlib format. They should
|
|
||||||
probably have called the second one "zlib" instead to avoid confusion with
|
|
||||||
the raw deflate compressed data format. While the HTTP 1.1 RFC 2616
|
|
||||||
correctly points to the zlib specification in RFC 1950 for the "deflate"
|
|
||||||
transfer encoding, there have been reports of servers and browsers that
|
|
||||||
incorrectly produce or expect raw deflate data per the deflate
|
|
||||||
specification in RFC 1951, most notably Microsoft. So even though the
|
|
||||||
"deflate" transfer encoding using the zlib format would be the more
|
|
||||||
efficient approach (and in fact exactly what the zlib format was designed
|
|
||||||
for), using the "gzip" transfer encoding is probably more reliable due to
|
|
||||||
an unfortunate choice of name on the part of the HTTP 1.1 authors.
|
|
||||||
|
|
||||||
Bottom line: use the gzip format for HTTP 1.1 encoding.
|
|
||||||
|
|
||||||
40. Does zlib support the new "Deflate64" format introduced by PKWare?
|
|
||||||
|
|
||||||
No. PKWare has apparently decided to keep that format proprietary, since
|
|
||||||
they have not documented it as they have previous compression formats. In
|
|
||||||
any case, the compression improvements are so modest compared to other more
|
|
||||||
modern approaches, that it's not worth the effort to implement.
|
|
||||||
|
|
||||||
41. I'm having a problem with the zip functions in zlib, can you help?
|
|
||||||
|
|
||||||
There are no zip functions in zlib. You are probably using minizip by
|
|
||||||
Giles Vollant, which is found in the contrib directory of zlib. It is not
|
|
||||||
part of zlib. In fact none of the stuff in contrib is part of zlib. The
|
|
||||||
files in there are not supported by the zlib authors. You need to contact
|
|
||||||
the authors of the respective contribution for help.
|
|
||||||
|
|
||||||
42. The match.asm code in contrib is under the GNU General Public License.
|
|
||||||
Since it's part of zlib, doesn't that mean that all of zlib falls under the
|
|
||||||
GNU GPL?
|
|
||||||
|
|
||||||
No. The files in contrib are not part of zlib. They were contributed by
|
|
||||||
other authors and are provided as a convenience to the user within the zlib
|
|
||||||
distribution. Each item in contrib has its own license.
|
|
||||||
|
|
||||||
43. Is zlib subject to export controls? What is its ECCN?
|
|
||||||
|
|
||||||
zlib is not subject to export controls, and so is classified as EAR99.
|
|
||||||
|
|
||||||
44. Can you please sign these lengthy legal documents and fax them back to us
|
|
||||||
so that we can use your software in our product?
|
|
||||||
|
|
||||||
No. Go away. Shoo.
|
|
@ -1,55 +0,0 @@
|
|||||||
CMakeLists.txt cmake build file
|
|
||||||
ChangeLog.zlib history of changes up to the fork from zlib 1.2.8
|
|
||||||
FAQ.zlib Frequently Asked Questions about zlib, as distributed in zlib 1.2.8
|
|
||||||
INDEX this file
|
|
||||||
Makefile dummy Makefile that tells you to ./configure
|
|
||||||
Makefile.in template for Unix Makefile
|
|
||||||
README guess what
|
|
||||||
README.zlib Copy of the original README file distributed in zlib 1.2.8
|
|
||||||
configure configure script for Unix
|
|
||||||
test/example.c zlib usages examples for build testing
|
|
||||||
test/minigzip.c minimal gzip-like functionality for build testing
|
|
||||||
test/infcover.c inf*.c code coverage for build coverage testing
|
|
||||||
treebuild.xml XML description of source file dependencies
|
|
||||||
zconf.h.cmakein zconf.h template for cmake
|
|
||||||
zconf.h.in zconf.h template for configure
|
|
||||||
zlib.3 Man page for zlib
|
|
||||||
zlib.3.pdf Man page in PDF format
|
|
||||||
zlib.map Linux symbol information
|
|
||||||
zlib.pc.in Template for pkg-config descriptor
|
|
||||||
zlib.pc.cmakein zlib.pc template for cmake
|
|
||||||
zlib2ansi perl script to convert source files for C++ compilation
|
|
||||||
|
|
||||||
arch/ architecture-specific code
|
|
||||||
doc/ documentation for formats and algorithms
|
|
||||||
win32/ makefiles for Windows
|
|
||||||
|
|
||||||
zlib public header files (required for library use):
|
|
||||||
zconf.h
|
|
||||||
zlib.h
|
|
||||||
|
|
||||||
private source files used to build the zlib library:
|
|
||||||
adler32.c
|
|
||||||
compress.c
|
|
||||||
crc32.c
|
|
||||||
crc32.h
|
|
||||||
deflate.c
|
|
||||||
deflate.h
|
|
||||||
gzclose.c
|
|
||||||
gzguts.h
|
|
||||||
gzlib.c
|
|
||||||
gzread.c
|
|
||||||
gzwrite.c
|
|
||||||
infback.c
|
|
||||||
inffast.c
|
|
||||||
inffast.h
|
|
||||||
inffixed.h
|
|
||||||
inflate.c
|
|
||||||
inflate.h
|
|
||||||
inftrees.c
|
|
||||||
inftrees.h
|
|
||||||
trees.c
|
|
||||||
trees.h
|
|
||||||
uncompr.c
|
|
||||||
zutil.c
|
|
||||||
zutil.h
|
|
@ -1,19 +0,0 @@
|
|||||||
(C) 1995-2013 Jean-loup Gailly and Mark Adler
|
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
|
||||||
warranty. In no event will the authors be held liable for any damages
|
|
||||||
arising from the use of this software.
|
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
|
||||||
including commercial applications, and to alter it and redistribute it
|
|
||||||
freely, subject to the following restrictions:
|
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
|
||||||
claim that you wrote the original software. If you use this software
|
|
||||||
in a product, an acknowledgment in the product documentation would be
|
|
||||||
appreciated but is not required.
|
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
|
||||||
misrepresented as being the original software.
|
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
|
@ -1,329 +0,0 @@
|
|||||||
# Makefile for zlib
|
|
||||||
# Copyright (C) 1995-2013 Jean-loup Gailly, Mark Adler
|
|
||||||
# For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
|
|
||||||
# To compile and test, type:
|
|
||||||
# ./configure; make test
|
|
||||||
# Normally configure builds both a static and a shared library.
|
|
||||||
# If you want to build just a static library, use: ./configure --static
|
|
||||||
|
|
||||||
# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type:
|
|
||||||
# make install
|
|
||||||
# To install in $HOME instead of /usr/local, use:
|
|
||||||
# make install prefix=$HOME
|
|
||||||
|
|
||||||
CC=cc
|
|
||||||
|
|
||||||
CFLAGS=-O
|
|
||||||
#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
|
|
||||||
#CFLAGS=-g -DDEBUG
|
|
||||||
#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
|
|
||||||
# -Wstrict-prototypes -Wmissing-prototypes
|
|
||||||
|
|
||||||
SFLAGS=-O
|
|
||||||
LDFLAGS=
|
|
||||||
TEST_LDFLAGS=-L. libz.a
|
|
||||||
LDSHARED=$(CC)
|
|
||||||
|
|
||||||
STATICLIB=libz.a
|
|
||||||
SHAREDLIB=libz.so
|
|
||||||
SHAREDLIBV=libz.so.1.2.8
|
|
||||||
SHAREDLIBM=libz.so.1
|
|
||||||
IMPORTLIB=
|
|
||||||
SHAREDTARGET=libz.so.1.2.8
|
|
||||||
|
|
||||||
LIBS=$(STATICLIB) $(SHAREDTARGET)
|
|
||||||
|
|
||||||
AR=ar
|
|
||||||
ARFLAGS=rc
|
|
||||||
DEFFILE=
|
|
||||||
RC=
|
|
||||||
RCFLAGS=
|
|
||||||
RCOBJS=
|
|
||||||
STRIP=
|
|
||||||
RANLIB=ranlib
|
|
||||||
LDCONFIG=ldconfig
|
|
||||||
LDSHAREDLIBC=-lc
|
|
||||||
TAR=tar
|
|
||||||
SHELL=/bin/sh
|
|
||||||
EXE=
|
|
||||||
|
|
||||||
SRCDIR=.
|
|
||||||
INCLUDES=-I$(SRCDIR)
|
|
||||||
|
|
||||||
ARCHDIR=arch/generic
|
|
||||||
ARCH_STATIC_OBJS=
|
|
||||||
ARCH_SHARED_OBJS=
|
|
||||||
|
|
||||||
prefix = /usr/local
|
|
||||||
exec_prefix = ${prefix}
|
|
||||||
bindir = ${exec_prefix}/bin
|
|
||||||
libdir = ${exec_prefix}/lib
|
|
||||||
sharedlibdir = ${libdir}
|
|
||||||
includedir = ${prefix}/include
|
|
||||||
mandir = ${prefix}/share/man
|
|
||||||
man3dir = ${mandir}/man3
|
|
||||||
pkgconfigdir = ${libdir}/pkgconfig
|
|
||||||
|
|
||||||
OBJZ = adler32.o compress.o crc32.o deflate.o deflate_fast.o deflate_medium.o deflate_slow.o match.o infback.o inffast.o inflate.o inftrees.o trees.o uncompr.o zutil.o $(ARCH_STATIC_OBJS)
|
|
||||||
OBJG = gzclose.o gzlib.o gzread.o gzwrite.o
|
|
||||||
OBJC = $(OBJZ) $(OBJG)
|
|
||||||
|
|
||||||
PIC_OBJZ = adler32.lo compress.lo crc32.lo deflate.lo deflate_fast.lo deflate_medium.lo deflate_slow.lo match.lo infback.lo inffast.lo inflate.lo inftrees.lo trees.lo uncompr.lo zutil.lo $(ARCH_SHARED_OBJS)
|
|
||||||
PIC_OBJG = gzclose.lo gzlib.lo gzread.lo gzwrite.lo
|
|
||||||
PIC_OBJC = $(PIC_OBJZ) $(PIC_OBJG)
|
|
||||||
|
|
||||||
OBJS = $(OBJC)
|
|
||||||
|
|
||||||
PIC_OBJS = $(PIC_OBJC)
|
|
||||||
|
|
||||||
all: static shared
|
|
||||||
|
|
||||||
static: example$(EXE) minigzip$(EXE)
|
|
||||||
|
|
||||||
shared: examplesh$(EXE) minigzipsh$(EXE)
|
|
||||||
|
|
||||||
all64: example64$(EXE) minigzip64$(EXE)
|
|
||||||
|
|
||||||
check: test
|
|
||||||
|
|
||||||
$(ARCHDIR)/%.o: $(SRCDIR)/$(ARCHDIR)/%.c
|
|
||||||
$(MAKE) -C $(ARCHDIR) $(notdir $@)
|
|
||||||
|
|
||||||
$(ARCHDIR)/%.lo: $(SRCDIR)/$(ARCHDIR)/%.c
|
|
||||||
$(MAKE) -C $(ARCHDIR) $(notdir $@)
|
|
||||||
|
|
||||||
%.o: $(ARCHDIR)/%.o
|
|
||||||
-cp $< $@
|
|
||||||
|
|
||||||
%.lo: $(ARCHDIR)/%.lo
|
|
||||||
-cp $< $@
|
|
||||||
|
|
||||||
test: all
|
|
||||||
$(MAKE) -C test
|
|
||||||
|
|
||||||
infcover.o: $(SRCDIR)/test/infcover.c $(SRCDIR)/zlib.h zconf.h
|
|
||||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/test/infcover.c
|
|
||||||
|
|
||||||
infcover$(EXE): infcover.o $(STATICLIB)
|
|
||||||
$(CC) $(CFLAGS) -o $@ infcover.o $(STATICLIB)
|
|
||||||
ifneq ($(STRIP),)
|
|
||||||
$(STRIP) $@
|
|
||||||
endif
|
|
||||||
|
|
||||||
cover: infcover$(EXE)
|
|
||||||
rm -f *.gcda
|
|
||||||
./infcover
|
|
||||||
gcov inf*.c
|
|
||||||
|
|
||||||
$(STATICLIB): $(OBJS)
|
|
||||||
$(AR) $(ARFLAGS) $@ $(OBJS)
|
|
||||||
-@ ($(RANLIB) $@ || true) >/dev/null 2>&1
|
|
||||||
|
|
||||||
example.o: $(SRCDIR)/test/example.c $(SRCDIR)/zlib.h zconf.h
|
|
||||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/test/example.c
|
|
||||||
|
|
||||||
minigzip.o: $(SRCDIR)/test/minigzip.c $(SRCDIR)/zlib.h zconf.h
|
|
||||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/test/minigzip.c
|
|
||||||
|
|
||||||
example64.o: $(SRCDIR)/test/example.c $(SRCDIR)/zlib.h zconf.h
|
|
||||||
$(CC) $(CFLAGS) $(INCLUDES) -D_FILE_OFFSET_BITS=64 -c -o $@ $(SRCDIR)/test/example.c
|
|
||||||
|
|
||||||
minigzip64.o: $(SRCDIR)/test/minigzip.c $(SRCDIR)/zlib.h zconf.h
|
|
||||||
$(CC) $(CFLAGS) $(INCLUDES) -D_FILE_OFFSET_BITS=64 -c -o $@ $(SRCDIR)/test/minigzip.c
|
|
||||||
|
|
||||||
zlibrc.o: win32/zlib1.rc
|
|
||||||
$(RC) $(RCFLAGS) -o $@ win32/zlib1.rc
|
|
||||||
|
|
||||||
.SUFFIXES: .lo
|
|
||||||
|
|
||||||
%.o: $(SRCDIR)/%.c
|
|
||||||
$(CC) $(INCLUDES) $(CFLAGS) -c -o $@ $<
|
|
||||||
|
|
||||||
%.lo: $(SRCDIR)/%.c
|
|
||||||
$(CC) $(INCLUDES) $(SFLAGS) -DPIC -c -o $@ $<
|
|
||||||
|
|
||||||
$(SHAREDTARGET): $(PIC_OBJS) $(DEFFILE) $(RCOBJS)
|
|
||||||
ifneq ($(SHAREDTARGET),)
|
|
||||||
$(LDSHARED) $(SFLAGS) -o $@ $(DEFFILE) $(PIC_OBJS) $(RCOBJS) $(LDSHAREDLIBC) $(LDFLAGS)
|
|
||||||
ifneq ($(STRIP),)
|
|
||||||
$(STRIP) $@
|
|
||||||
endif
|
|
||||||
ifneq ($(SHAREDLIB),$(SHAREDTARGET))
|
|
||||||
rm -f $(SHAREDLIB) $(SHAREDLIBM)
|
|
||||||
ln -s $@ $(SHAREDLIB)
|
|
||||||
ln -s $@ $(SHAREDLIBM)
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
example$(EXE): example.o $(STATICLIB)
|
|
||||||
$(CC) $(CFLAGS) -o $@ example.o $(TEST_LDFLAGS)
|
|
||||||
ifneq ($(STRIP),)
|
|
||||||
$(STRIP) $@
|
|
||||||
endif
|
|
||||||
|
|
||||||
minigzip$(EXE): minigzip.o $(STATICLIB)
|
|
||||||
$(CC) $(CFLAGS) -o $@ minigzip.o $(TEST_LDFLAGS)
|
|
||||||
ifneq ($(STRIP),)
|
|
||||||
$(STRIP) $@
|
|
||||||
endif
|
|
||||||
|
|
||||||
examplesh$(EXE): example.o $(SHAREDTARGET)
|
|
||||||
$(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDTARGET)
|
|
||||||
ifneq ($(STRIP),)
|
|
||||||
$(STRIP) $@
|
|
||||||
endif
|
|
||||||
|
|
||||||
minigzipsh$(EXE): minigzip.o $(SHAREDTARGET)
|
|
||||||
$(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDTARGET)
|
|
||||||
ifneq ($(STRIP),)
|
|
||||||
$(STRIP) $@
|
|
||||||
endif
|
|
||||||
|
|
||||||
example64$(EXE): example64.o $(STATICLIB)
|
|
||||||
$(CC) $(CFLAGS) -o $@ example64.o $(TEST_LDFLAGS)
|
|
||||||
ifneq ($(STRIP),)
|
|
||||||
$(STRIP) $@
|
|
||||||
endif
|
|
||||||
|
|
||||||
minigzip64$(EXE): minigzip64.o $(STATICLIB)
|
|
||||||
$(CC) $(CFLAGS) -o $@ minigzip64.o $(TEST_LDFLAGS)
|
|
||||||
ifneq ($(STRIP),)
|
|
||||||
$(STRIP) $@
|
|
||||||
endif
|
|
||||||
|
|
||||||
install-shared: $(SHAREDTARGET)
|
|
||||||
ifneq ($(SHAREDTARGET),)
|
|
||||||
-@if [ ! -d $(DESTDIR)$(sharedlibdir) ]; then mkdir -p $(DESTDIR)$(sharedlibdir); fi
|
|
||||||
cp $(SHAREDTARGET) $(DESTDIR)$(sharedlibdir)
|
|
||||||
chmod 644 $(DESTDIR)$(sharedlibdir)/$(SHAREDTARGET)
|
|
||||||
ifneq ($(SHAREDLIB),$(SHAREDTARGET))
|
|
||||||
rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM)
|
|
||||||
ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB)
|
|
||||||
ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM)
|
|
||||||
($(LDCONFIG) || true) >/dev/null 2>&1
|
|
||||||
# ldconfig is for Linux
|
|
||||||
endif
|
|
||||||
ifneq ($(IMPORTLIB),)
|
|
||||||
cp $(IMPORTLIB) $(DESTDIR)$(sharedlibdir)
|
|
||||||
chmod 644 $(DESTDIR)$(sharedlibdir)/$(IMPORTLIB)
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
install-static: $(STATICLIB)
|
|
||||||
-@if [ ! -d $(DESTDIR)$(libdir) ]; then mkdir -p $(DESTDIR)$(libdir); fi
|
|
||||||
cp $(STATICLIB) $(DESTDIR)$(libdir)
|
|
||||||
chmod 644 $(DESTDIR)$(libdir)/$(STATICLIB)
|
|
||||||
-@($(RANLIB) $(DESTDIR)$(libdir)/$(STATICLIB) || true) >/dev/null 2>&1
|
|
||||||
# The ranlib in install-static is needed on NeXTSTEP which checks file times
|
|
||||||
|
|
||||||
install-libs: install-shared install-static
|
|
||||||
-@if [ ! -d $(DESTDIR)$(man3dir) ]; then mkdir -p $(DESTDIR)$(man3dir); fi
|
|
||||||
-@if [ ! -d $(DESTDIR)$(pkgconfigdir) ]; then mkdir -p $(DESTDIR)$(pkgconfigdir); fi
|
|
||||||
cp $(SRCDIR)/zlib.3 $(DESTDIR)$(man3dir)
|
|
||||||
chmod 644 $(DESTDIR)$(man3dir)/zlib.3
|
|
||||||
cp zlib.pc $(DESTDIR)$(pkgconfigdir)
|
|
||||||
chmod 644 $(DESTDIR)$(pkgconfigdir)/zlib.pc
|
|
||||||
|
|
||||||
install: install-libs
|
|
||||||
-@if [ ! -d $(DESTDIR)$(includedir) ]; then mkdir -p $(DESTDIR)$(includedir); fi
|
|
||||||
cp $(SRCDIR)/zlib.h zconf.h $(DESTDIR)$(includedir)
|
|
||||||
chmod 644 $(DESTDIR)$(includedir)/zlib.h $(DESTDIR)$(includedir)/zconf.h
|
|
||||||
|
|
||||||
uninstall-static:
|
|
||||||
cd $(DESTDIR)$(libdir) && rm -f $(STATICLIB)
|
|
||||||
|
|
||||||
uninstall-shared:
|
|
||||||
ifneq ($(SHAREDLIB),)
|
|
||||||
cd $(DESTDIR)$(sharedlibdir) && rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM)
|
|
||||||
endif
|
|
||||||
ifneq ($(IMPORTLIB),)
|
|
||||||
cd $(DESTDIR)$(sharedlibdir) && rm -f $(IMPORTLIB)
|
|
||||||
endif
|
|
||||||
|
|
||||||
uninstall: uninstall-static uninstall-shared
|
|
||||||
cd $(DESTDIR)$(includedir) && rm -f zlib.h zconf.h
|
|
||||||
cd $(DESTDIR)$(man3dir) && rm -f zlib.3
|
|
||||||
cd $(DESTDIR)$(pkgconfigdir) && rm -f zlib.pc
|
|
||||||
|
|
||||||
docs: zlib.3.pdf
|
|
||||||
|
|
||||||
zlib.3.pdf: $(SRCDIR)/zlib.3
|
|
||||||
groff -mandoc -f H -T ps $(SRCDIR)/zlib.3 | ps2pdf - zlib.3.pdf
|
|
||||||
|
|
||||||
mostlyclean: clean
|
|
||||||
clean:
|
|
||||||
@if [ -f $(ARCHDIR)/Makefile ]; then $(MAKE) -C $(ARCHDIR) clean; fi
|
|
||||||
@if [ -f test/Makefile ]; then $(MAKE) -C test clean; fi
|
|
||||||
rm -f *.o *.lo *~ \
|
|
||||||
example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \
|
|
||||||
example64$(EXE) minigzip64$(EXE) \
|
|
||||||
infcover \
|
|
||||||
$(STATICLIB) $(IMPORTLIB) $(SHAREDLIB) $(SHAREDLIBV) $(SHAREDLIBM) \
|
|
||||||
foo.gz so_locations \
|
|
||||||
_match.s maketree
|
|
||||||
rm -rf objs
|
|
||||||
rm -f *.gcda *.gcno *.gcov
|
|
||||||
rm -f a.out
|
|
||||||
|
|
||||||
maintainer-clean: distclean
|
|
||||||
distclean: clean
|
|
||||||
@if [ -f $(ARCHDIR)/Makefile ]; then $(MAKE) -C $(ARCHDIR) distclean; fi
|
|
||||||
@if [ -f test/Makefile ]; then $(MAKE) -C test distclean; fi
|
|
||||||
rm -f zlib.pc configure.log zconf.h zconf.h.cmakein
|
|
||||||
-@rm -f .DS_Store
|
|
||||||
# Reset Makefile if building inside source tree
|
|
||||||
@if [ -f Makefile.in ]; then \
|
|
||||||
printf 'all:\n\t-@echo "Please use ./configure first. Thank you."\n' > Makefile ; \
|
|
||||||
printf '\ndistclean:\n\tmake -f Makefile.in distclean\n' >> Makefile ; \
|
|
||||||
touch -r $(SRCDIR)/Makefile.in Makefile ; fi
|
|
||||||
# Reset zconf.h and zconf.h.cmakein if building inside source tree
|
|
||||||
@if [ -f zconf.h.in ]; then \
|
|
||||||
cp -p $(SRCDIR)/zconf.h.in zconf.h ; \
|
|
||||||
TEMPFILE=zconfh_$$ ; \
|
|
||||||
echo "/#define ZCONF_H/ a\\\\\n#cmakedefine Z_HAVE_UNISTD_H\n" >> $$TEMPFILE &&\
|
|
||||||
sed -f $$TEMPFILE $(SRCDIR)/zconf.h.in > zconf.h.cmakein &&\
|
|
||||||
touch -r $(SRCDIR)/zconf.h.in zconf.h.cmakein &&\
|
|
||||||
rm $$TEMPFILE ; fi
|
|
||||||
# Cleanup these files if building outside source tree
|
|
||||||
@if [ ! -f zlib.3 ]; then rm -f zlib.3.pdf Makefile; fi
|
|
||||||
# Remove arch and test directory if building outside source tree
|
|
||||||
@if [ ! -f $(ARCHDIR)/Makefile.in ]; then rm -rf arch; fi
|
|
||||||
@if [ ! -f test/Makefile.in ]; then rm -rf test; fi
|
|
||||||
|
|
||||||
tags:
|
|
||||||
etags $(SRCDIR)/*.[ch]
|
|
||||||
|
|
||||||
depend:
|
|
||||||
makedepend -- $(CFLAGS) -- $(SRCDIR)/*.[ch]
|
|
||||||
makedepend -a -o.lo -- $(SFLAGS) -- $(SRCDIR)/*.[ch]
|
|
||||||
@sed "s=^$(SRCDIR)/\([a-zA-Z0-9_]*\.\(lo\|o\):\)=\1=g" < Makefile > Makefile.tmp
|
|
||||||
@mv -f Makefile.tmp Makefile
|
|
||||||
|
|
||||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
|
||||||
|
|
||||||
adler32.o zutil.o: $(SRCDIR)/zutil.h $(SRCDIR)/zlib.h zconf.h
|
|
||||||
gzclose.o gzlib.o gzread.o gzwrite.o: $(SRCDIR)/zlib.h zconf.h $(SRCDIR)/gzguts.h
|
|
||||||
compress.o example.o minigzip.o uncompr.o: $(SRCDIR)/zlib.h zconf.h
|
|
||||||
crc32.o: $(SRCDIR)/zutil.h $(SRCDIR)/zlib.h zconf.h $(SRCDIR)/crc32.h
|
|
||||||
deflate.o: $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/match.h $(SRCDIR)/zutil.h $(SRCDIR)/zlib.h zconf.h
|
|
||||||
deflate_fast.o: $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/match.h
|
|
||||||
deflate_medium.o: $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/match.h
|
|
||||||
deflate_slow.o: $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/match.h
|
|
||||||
infback.o inflate.o: $(SRCDIR)/zutil.h $(SRCDIR)/zlib.h zconf.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/inffixed.h
|
|
||||||
inffast.o: $(SRCDIR)/zutil.h $(SRCDIR)/zlib.h zconf.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h
|
|
||||||
inftrees.o: $(SRCDIR)/zutil.h $(SRCDIR)/zlib.h zconf.h $(SRCDIR)/inftrees.h
|
|
||||||
trees.o: $(SRCDIR)/deflate.h $(SRCDIR)/zutil.h $(SRCDIR)/zlib.h zconf.h $(SRCDIR)/trees.h
|
|
||||||
|
|
||||||
adler32.lo zutil.lo: $(SRCDIR)/zutil.h $(SRCDIR)/zlib.h zconf.h
|
|
||||||
gzclose.lo gzlib.lo gzread.lo gzwrite.lo: $(SRCDIR)/zlib.h zconf.h $(SRCDIR)/gzguts.h
|
|
||||||
compress.lo example.lo minigzip.lo uncompr.lo: $(SRCDIR)/zlib.h zconf.h
|
|
||||||
crc32.lo: $(SRCDIR)/zutil.h $(SRCDIR)/zlib.h zconf.h $(SRCDIR)/crc32.h
|
|
||||||
deflate.lo: $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/match.h $(SRCDIR)/zutil.h $(SRCDIR)/zlib.h zconf.h
|
|
||||||
deflate_fast.lo: $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/match.h
|
|
||||||
deflate_medium.lo: $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/match.h
|
|
||||||
deflate_slow.lo: $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/match.h
|
|
||||||
infback.lo inflate.lo: $(SRCDIR)/zutil.h $(SRCDIR)/zlib.h zconf.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/inffixed.h
|
|
||||||
inffast.lo: $(SRCDIR)/zutil.h $(SRCDIR)/zlib.h zconf.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h
|
|
||||||
inftrees.lo: $(SRCDIR)/zutil.h $(SRCDIR)/zlib.h zconf.h $(SRCDIR)/inftrees.h
|
|
||||||
trees.lo: $(SRCDIR)/deflate.h $(SRCDIR)/zutil.h $(SRCDIR)/zlib.h zconf.h $(SRCDIR)/trees.h
|
|
@ -1,63 +0,0 @@
|
|||||||
zlib-ng - zlib for the next generation systems
|
|
||||||
|
|
||||||
Maintained by Hans Kristian Rosbach
|
|
||||||
aka Dead2 (zlib-ng àt circlestorm dót org)
|
|
||||||
|
|
||||||
|
|
||||||
Fork Motivation and History
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
The motivation for this fork was due to seeing several 3rd party
|
|
||||||
contributions containing new optimizations not getting implemented
|
|
||||||
into the official zlib repository.
|
|
||||||
|
|
||||||
Mark Adler has been maintaining zlib for a very long time, and he has
|
|
||||||
done a great job and hopefully he will continue for a long time yet.
|
|
||||||
The idea of zlib-ng is not to replace zlib, but to co-exist as a
|
|
||||||
drop-in replacement with a lower threshold for code change.
|
|
||||||
|
|
||||||
zlib has a long history and is incredibly portable, even supporting
|
|
||||||
lots of systems that predate the Internet. This is great, but it does
|
|
||||||
complicate further development and maintainability.
|
|
||||||
The zlib code has to make numerous workarounds for old compilers that
|
|
||||||
do not understand ANSI-C or to accommodate systems with limitations
|
|
||||||
such as operating in a 16-bit environment.
|
|
||||||
|
|
||||||
Many of these workarounds are only maintenance burdens, some of them
|
|
||||||
are pretty huge code-wise. For example, the [v]s[n]printf workaround
|
|
||||||
code has a whopping 8 different implementations just to cater to
|
|
||||||
various old compilers. With this many workarounds cluttered throughout
|
|
||||||
the code, new programmers with an idea/interest for zlib will need
|
|
||||||
to take some time to figure out why all of these seemingly strange
|
|
||||||
things are used, and how to work within those confines.
|
|
||||||
|
|
||||||
So I decided to make a fork, merge all the Intel optimizations, merge
|
|
||||||
the Cloudflare optimizations that did not conflict, plus a couple
|
|
||||||
of other smaller patches. Then I started cleaning out workarounds,
|
|
||||||
various dead code, all contrib and example code as there is little
|
|
||||||
point in having those in this fork for different reasons.
|
|
||||||
|
|
||||||
Lastly I have been cleaning up the handling of different arches,
|
|
||||||
so that it will be easier to implement arch-specific code without
|
|
||||||
cluttering up the main code too much.
|
|
||||||
|
|
||||||
Now, there is still a lot to do and I am sure there are better ways
|
|
||||||
of doing several of the changes I have done. And I would be delighted
|
|
||||||
to receive patches, preferably as pull requests on github.
|
|
||||||
Just remember that any code you submit must be your own and it must
|
|
||||||
be zlib licensed.
|
|
||||||
|
|
||||||
Please read LICENSE.md, it is very simple and very liberal.
|
|
||||||
|
|
||||||
|
|
||||||
Acknowledgments
|
|
||||||
----------------
|
|
||||||
|
|
||||||
Big thanks to Raske Sider AS / raskesider.no for sponsoring my
|
|
||||||
maintainership of zlib-ng.
|
|
||||||
|
|
||||||
The deflate format used by zlib was defined by Phil Katz.
|
|
||||||
The deflate and zlib specifications were written by L. Peter Deutsch.
|
|
||||||
|
|
||||||
zlib was originally created by Jean-loup Gailly (compression)
|
|
||||||
and Mark Adler (decompression).
|
|
@ -1,12 +0,0 @@
|
|||||||
Sources imported from https://github.com/Dead2/zlib-ng/tree/343c4c549107d31f6eeabfb4b31bec4502a2ea0e
|
|
||||||
CMakeLists.txt taken from https://github.com/mtl1979/zlib-ng/tree/ad8868ab0e78a87fb0485d4bc67b8cfe96e00891
|
|
||||||
|
|
||||||
Zlib with CloudFlare patches provides slightly better performance for decompression and compression
|
|
||||||
with level > 1. Unfortunately, we can't use that version due to GPL-licensed code. If you still
|
|
||||||
want to use it, replace contents of this directory with contents of https://github.com/cloudflare/zlib
|
|
||||||
and add the following lines at the beginning of CMakeLists.txt:
|
|
||||||
|
|
||||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-variable -DHAS_PCLMUL")
|
|
||||||
set (ZLIB_ASMS
|
|
||||||
contrib/amd64/crc32-pclmul_asm.S
|
|
||||||
)
|
|
@ -1,65 +0,0 @@
|
|||||||
Travis CI: [![build status](https://api.travis-ci.org/Dead2/zlib-ng.svg)](https://travis-ci.org/Dead2/zlib-ng/)
|
|
||||||
|
|
||||||
zlib-ng - zlib for the next generation systems
|
|
||||||
|
|
||||||
Maintained by Hans Kristian Rosbach
|
|
||||||
aka Dead2 (zlib-ng àt circlestorm dót org)
|
|
||||||
|
|
||||||
|
|
||||||
Fork Motivation and History
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
The motivation for this fork was due to seeing several 3rd party
|
|
||||||
contributions containing new optimizations not getting implemented
|
|
||||||
into the official zlib repository.
|
|
||||||
|
|
||||||
Mark Adler has been maintaining zlib for a very long time, and he has
|
|
||||||
done a great job and hopefully he will continue for a long time yet.
|
|
||||||
The idea of zlib-ng is not to replace zlib, but to co-exist as a
|
|
||||||
drop-in replacement with a lower threshold for code change.
|
|
||||||
|
|
||||||
zlib has a long history and is incredibly portable, even supporting
|
|
||||||
lots of systems that predate the Internet. This is great, but it does
|
|
||||||
complicate further development and maintainability.
|
|
||||||
The zlib code has to make numerous workarounds for old compilers that
|
|
||||||
do not understand ANSI-C or to accommodate systems with limitations
|
|
||||||
such as operating in a 16-bit environment.
|
|
||||||
|
|
||||||
Many of these workarounds are only maintenance burdens, some of them
|
|
||||||
are pretty huge code-wise. For example, the [v]s[n]printf workaround
|
|
||||||
code has a whopping 8 different implementations just to cater to
|
|
||||||
various old compilers. With this many workarounds cluttered throughout
|
|
||||||
the code, new programmers with an idea/interest for zlib will need
|
|
||||||
to take some time to figure out why all of these seemingly strange
|
|
||||||
things are used, and how to work within those confines.
|
|
||||||
|
|
||||||
So I decided to make a fork, merge all the Intel optimizations, merge
|
|
||||||
the Cloudflare optimizations that did not conflict, plus a couple
|
|
||||||
of other smaller patches. Then I started cleaning out workarounds,
|
|
||||||
various dead code, all contrib and example code as there is little
|
|
||||||
point in having those in this fork for different reasons.
|
|
||||||
|
|
||||||
Lastly I have been cleaning up the handling of different arches,
|
|
||||||
so that it will be easier to implement arch-specific code without
|
|
||||||
cluttering up the main code too much.
|
|
||||||
|
|
||||||
Now, there is still a lot to do and I am sure there are better ways
|
|
||||||
of doing several of the changes I have done. And I would be delighted
|
|
||||||
to receive patches, preferably as pull requests on github.
|
|
||||||
Just remember that any code you submit must be your own and it must
|
|
||||||
be zlib licensed.
|
|
||||||
|
|
||||||
Please read LICENSE.md, it is very simple and very liberal.
|
|
||||||
|
|
||||||
|
|
||||||
Acknowledgments
|
|
||||||
----------------
|
|
||||||
|
|
||||||
Big thanks to Raske Sider AS / raskesider.no for sponsoring my
|
|
||||||
maintainership of zlib-ng.
|
|
||||||
|
|
||||||
The deflate format used by zlib was defined by Phil Katz.
|
|
||||||
The deflate and zlib specifications were written by L. Peter Deutsch.
|
|
||||||
|
|
||||||
zlib was originally created by Jean-loup Gailly (compression)
|
|
||||||
and Mark Adler (decompression).
|
|
@ -1,121 +0,0 @@
|
|||||||
##
|
|
||||||
# THIS IS AN UNMAINTAINED COPY OF THE ORIGINAL FILE DISTRIBUTED WITH ZLIB 1.2.8
|
|
||||||
##
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ZLIB DATA COMPRESSION LIBRARY
|
|
||||||
|
|
||||||
zlib 1.2.8 is a general purpose data compression library. All the code is
|
|
||||||
thread safe. The data format used by the zlib library is described by RFCs
|
|
||||||
(Request for Comments) 1950 to 1952 in the files
|
|
||||||
http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and
|
|
||||||
rfc1952 (gzip format).
|
|
||||||
|
|
||||||
All functions of the compression library are documented in the file zlib.h
|
|
||||||
(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example
|
|
||||||
of the library is given in the file test/example.c which also tests that
|
|
||||||
the library is working correctly. Another example is given in the file
|
|
||||||
test/minigzip.c. The compression library itself is composed of all source
|
|
||||||
files in the root directory.
|
|
||||||
|
|
||||||
To compile all files and run the test program, follow the instructions given at
|
|
||||||
the top of Makefile.in. In short "./configure; make test", and if that goes
|
|
||||||
well, "make install" should work for most flavors of Unix. For Windows, use
|
|
||||||
one of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use
|
|
||||||
make_vms.com.
|
|
||||||
|
|
||||||
Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant
|
|
||||||
<info@winimage.com> for the Windows DLL version. The zlib home page is
|
|
||||||
http://zlib.net/ . Before reporting a problem, please check this site to
|
|
||||||
verify that you have the latest version of zlib; otherwise get the latest
|
|
||||||
version and check whether the problem still exists or not.
|
|
||||||
|
|
||||||
PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help.
|
|
||||||
|
|
||||||
Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
|
|
||||||
issue of Dr. Dobb's Journal; a copy of the article is available at
|
|
||||||
http://marknelson.us/1997/01/01/zlib-engine/ .
|
|
||||||
|
|
||||||
The changes made in version 1.2.8 are documented in the file ChangeLog.
|
|
||||||
|
|
||||||
Unsupported third party contributions are provided in directory contrib/ .
|
|
||||||
|
|
||||||
zlib is available in Java using the java.util.zip package, documented at
|
|
||||||
http://java.sun.com/developer/technicalArticles/Programming/compression/ .
|
|
||||||
|
|
||||||
A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org> is available
|
|
||||||
at CPAN (Comprehensive Perl Archive Network) sites, including
|
|
||||||
http://search.cpan.org/~pmqs/IO-Compress-Zlib/ .
|
|
||||||
|
|
||||||
A Python interface to zlib written by A.M. Kuchling <amk@amk.ca> is
|
|
||||||
available in Python 1.5 and later versions, see
|
|
||||||
http://docs.python.org/library/zlib.html .
|
|
||||||
|
|
||||||
zlib is built into tcl: http://wiki.tcl.tk/4610 .
|
|
||||||
|
|
||||||
An experimental package to read and write files in .zip format, written on top
|
|
||||||
of zlib by Gilles Vollant <info@winimage.com>, is available in the
|
|
||||||
contrib/minizip directory of zlib.
|
|
||||||
|
|
||||||
|
|
||||||
Notes for some targets:
|
|
||||||
|
|
||||||
- For Windows DLL versions, please see win32/DLL_FAQ.txt
|
|
||||||
|
|
||||||
- For 64-bit Irix, deflate.c must be compiled without any optimization. With
|
|
||||||
-O, one libpng test fails. The test works in 32 bit mode (with the -n32
|
|
||||||
compiler flag). The compiler bug has been reported to SGI.
|
|
||||||
|
|
||||||
- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works
|
|
||||||
when compiled with cc.
|
|
||||||
|
|
||||||
- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is
|
|
||||||
necessary to get gzprintf working correctly. This is done by configure.
|
|
||||||
|
|
||||||
- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with
|
|
||||||
other compilers. Use "make test" to check your compiler.
|
|
||||||
|
|
||||||
- gzdopen is not supported on RISCOS or BEOS.
|
|
||||||
|
|
||||||
- For PalmOs, see http://palmzlib.sourceforge.net/
|
|
||||||
|
|
||||||
|
|
||||||
Acknowledgments:
|
|
||||||
|
|
||||||
The deflate format used by zlib was defined by Phil Katz. The deflate and
|
|
||||||
zlib specifications were written by L. Peter Deutsch. Thanks to all the
|
|
||||||
people who reported problems and suggested various improvements in zlib; they
|
|
||||||
are too numerous to cite here.
|
|
||||||
|
|
||||||
Copyright notice:
|
|
||||||
|
|
||||||
(C) 1995-2013 Jean-loup Gailly and Mark Adler
|
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
|
||||||
warranty. In no event will the authors be held liable for any damages
|
|
||||||
arising from the use of this software.
|
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
|
||||||
including commercial applications, and to alter it and redistribute it
|
|
||||||
freely, subject to the following restrictions:
|
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
|
||||||
claim that you wrote the original software. If you use this software
|
|
||||||
in a product, an acknowledgment in the product documentation would be
|
|
||||||
appreciated but is not required.
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
|
||||||
misrepresented as being the original software.
|
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
|
||||||
|
|
||||||
Jean-loup Gailly Mark Adler
|
|
||||||
jloup@gzip.org madler@alumni.caltech.edu
|
|
||||||
|
|
||||||
If you use the zlib library in a product, we would appreciate *not* receiving
|
|
||||||
lengthy legal documents to sign. The sources are provided for free but without
|
|
||||||
warranty of any kind. The library has been entirely written by Jean-loup
|
|
||||||
Gailly and Mark Adler; it does not include third-party code.
|
|
||||||
|
|
||||||
If you redistribute modified sources, we would appreciate that you include in
|
|
||||||
the file ChangeLog history information documenting your changes. Please read
|
|
||||||
the FAQ for more information on the distribution of modified source versions.
|
|
@ -1,177 +0,0 @@
|
|||||||
/* adler32.c -- compute the Adler-32 checksum of a data stream
|
|
||||||
* Copyright (C) 1995-2011 Mark Adler
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* @(#) $Id$ */
|
|
||||||
|
|
||||||
#include "zutil.h"
|
|
||||||
|
|
||||||
static uint32_t adler32_combine_(uint32_t adler1, uint32_t adler2, z_off64_t len2);
|
|
||||||
|
|
||||||
#define BASE 65521U /* largest prime smaller than 65536 */
|
|
||||||
#define NMAX 5552
|
|
||||||
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
|
|
||||||
|
|
||||||
#define DO1(buf, i) {adler += (buf)[i]; sum2 += adler;}
|
|
||||||
#define DO2(buf, i) DO1(buf, i); DO1(buf, i+1);
|
|
||||||
#define DO4(buf, i) DO2(buf, i); DO2(buf, i+2);
|
|
||||||
#define DO8(buf, i) DO4(buf, i); DO4(buf, i+4);
|
|
||||||
#define DO16(buf) DO8(buf, 0); DO8(buf, 8);
|
|
||||||
|
|
||||||
/* use NO_DIVIDE if your processor does not do division in hardware --
|
|
||||||
try it both ways to see which is faster */
|
|
||||||
#ifdef NO_DIVIDE
|
|
||||||
/* note that this assumes BASE is 65521, where 65536 % 65521 == 15
|
|
||||||
(thank you to John Reiser for pointing this out) */
|
|
||||||
# define CHOP(a) \
|
|
||||||
do { \
|
|
||||||
uint32_t tmp = a >> 16; \
|
|
||||||
a &= 0xffff; \
|
|
||||||
a += (tmp << 4) - tmp; \
|
|
||||||
} while (0)
|
|
||||||
# define MOD28(a) \
|
|
||||||
do { \
|
|
||||||
CHOP(a); \
|
|
||||||
if (a >= BASE) a -= BASE; \
|
|
||||||
} while (0)
|
|
||||||
# define MOD(a) \
|
|
||||||
do { \
|
|
||||||
CHOP(a); \
|
|
||||||
MOD28(a); \
|
|
||||||
} while (0)
|
|
||||||
# define MOD63(a) \
|
|
||||||
do { /* this assumes a is not negative */ \
|
|
||||||
z_off64_t tmp = a >> 32; \
|
|
||||||
a &= 0xffffffffL; \
|
|
||||||
a += (tmp << 8) - (tmp << 5) + tmp; \
|
|
||||||
tmp = a >> 16; \
|
|
||||||
a &= 0xffffL; \
|
|
||||||
a += (tmp << 4) - tmp; \
|
|
||||||
tmp = a >> 16; \
|
|
||||||
a &= 0xffffL; \
|
|
||||||
a += (tmp << 4) - tmp; \
|
|
||||||
if (a >= BASE) a -= BASE; \
|
|
||||||
} while (0)
|
|
||||||
#else
|
|
||||||
# define MOD(a) a %= BASE
|
|
||||||
# define MOD28(a) a %= BASE
|
|
||||||
# define MOD63(a) a %= BASE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ========================================================================= */
|
|
||||||
uint32_t ZEXPORT adler32(uint32_t adler, const unsigned char *buf, uint32_t len) {
|
|
||||||
uint32_t sum2;
|
|
||||||
unsigned n;
|
|
||||||
|
|
||||||
/* split Adler-32 into component sums */
|
|
||||||
sum2 = (adler >> 16) & 0xffff;
|
|
||||||
adler &= 0xffff;
|
|
||||||
|
|
||||||
/* in case user likes doing a byte at a time, keep it fast */
|
|
||||||
if (len == 1) {
|
|
||||||
adler += buf[0];
|
|
||||||
if (adler >= BASE)
|
|
||||||
adler -= BASE;
|
|
||||||
sum2 += adler;
|
|
||||||
if (sum2 >= BASE)
|
|
||||||
sum2 -= BASE;
|
|
||||||
return adler | (sum2 << 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* initial Adler-32 value (deferred check for len == 1 speed) */
|
|
||||||
if (buf == Z_NULL)
|
|
||||||
return 1L;
|
|
||||||
|
|
||||||
/* in case short lengths are provided, keep it somewhat fast */
|
|
||||||
if (len < 16) {
|
|
||||||
while (len--) {
|
|
||||||
adler += *buf++;
|
|
||||||
sum2 += adler;
|
|
||||||
}
|
|
||||||
if (adler >= BASE)
|
|
||||||
adler -= BASE;
|
|
||||||
MOD28(sum2); /* only added so many BASE's */
|
|
||||||
return adler | (sum2 << 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* do length NMAX blocks -- requires just one modulo operation */
|
|
||||||
while (len >= NMAX) {
|
|
||||||
len -= NMAX;
|
|
||||||
#ifndef UNROLL_LESS
|
|
||||||
n = NMAX / 16; /* NMAX is divisible by 16 */
|
|
||||||
#else
|
|
||||||
n = NMAX / 8; /* NMAX is divisible by 8 */
|
|
||||||
#endif
|
|
||||||
do {
|
|
||||||
#ifndef UNROLL_LESS
|
|
||||||
DO16(buf); /* 16 sums unrolled */
|
|
||||||
buf += 16;
|
|
||||||
#else
|
|
||||||
DO8(buf, 0); /* 8 sums unrolled */
|
|
||||||
buf += 8;
|
|
||||||
#endif
|
|
||||||
} while (--n);
|
|
||||||
MOD(adler);
|
|
||||||
MOD(sum2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* do remaining bytes (less than NMAX, still just one modulo) */
|
|
||||||
if (len) { /* avoid modulos if none remaining */
|
|
||||||
#ifndef UNROLL_LESS
|
|
||||||
while (len >= 16) {
|
|
||||||
len -= 16;
|
|
||||||
DO16(buf);
|
|
||||||
buf += 16;
|
|
||||||
#else
|
|
||||||
while (len >= 8) {
|
|
||||||
len -= 8;
|
|
||||||
DO8(buf, 0);
|
|
||||||
buf += 8;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
while (len--) {
|
|
||||||
adler += *buf++;
|
|
||||||
sum2 += adler;
|
|
||||||
}
|
|
||||||
MOD(adler);
|
|
||||||
MOD(sum2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* return recombined sums */
|
|
||||||
return adler | (sum2 << 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================================================================= */
|
|
||||||
static uint32_t adler32_combine_(uint32_t adler1, uint32_t adler2, z_off64_t len2) {
|
|
||||||
uint32_t sum1;
|
|
||||||
uint32_t sum2;
|
|
||||||
unsigned rem;
|
|
||||||
|
|
||||||
/* for negative len, return invalid adler32 as a clue for debugging */
|
|
||||||
if (len2 < 0)
|
|
||||||
return 0xffffffff;
|
|
||||||
|
|
||||||
/* the derivation of this formula is left as an exercise for the reader */
|
|
||||||
MOD63(len2); /* assumes len2 >= 0 */
|
|
||||||
rem = (unsigned)len2;
|
|
||||||
sum1 = adler1 & 0xffff;
|
|
||||||
sum2 = rem * sum1;
|
|
||||||
MOD(sum2);
|
|
||||||
sum1 += (adler2 & 0xffff) + BASE - 1;
|
|
||||||
sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
|
|
||||||
if (sum1 >= BASE) sum1 -= BASE;
|
|
||||||
if (sum1 >= BASE) sum1 -= BASE;
|
|
||||||
if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1);
|
|
||||||
if (sum2 >= BASE) sum2 -= BASE;
|
|
||||||
return sum1 | (sum2 << 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================================================================= */
|
|
||||||
uint32_t ZEXPORT adler32_combine(uint32_t adler1, uint32_t adler2, z_off_t len2) {
|
|
||||||
return adler32_combine_(adler1, adler2, len2);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t ZEXPORT adler32_combine64(uint32_t adler1, uint32_t adler2, z_off64_t len2) {
|
|
||||||
return adler32_combine_(adler1, adler2, len2);
|
|
||||||
}
|
|
2
contrib/libzlib-ng/arch/.gitignore
vendored
2
contrib/libzlib-ng/arch/.gitignore
vendored
@ -1,2 +0,0 @@
|
|||||||
# ignore Makefiles; they're all automatically generated
|
|
||||||
Makefile
|
|
@ -1,20 +0,0 @@
|
|||||||
# Makefile for zlib
|
|
||||||
# Copyright (C) 1995-2013 Jean-loup Gailly, Mark Adler
|
|
||||||
# For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
|
|
||||||
CC=
|
|
||||||
CFLAGS=
|
|
||||||
SFLAGS=
|
|
||||||
INCLUDES=
|
|
||||||
|
|
||||||
SRCDIR=
|
|
||||||
SRCTOP=
|
|
||||||
|
|
||||||
all:
|
|
||||||
|
|
||||||
|
|
||||||
mostlyclean: clean
|
|
||||||
clean:
|
|
||||||
rm -f *.o *.lo *~ \
|
|
||||||
rm -rf objs
|
|
||||||
rm -f *.gcda *.gcno *.gcov
|
|
@ -1,20 +0,0 @@
|
|||||||
# Makefile for zlib
|
|
||||||
# Copyright (C) 1995-2013 Jean-loup Gailly, Mark Adler
|
|
||||||
# For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
|
|
||||||
CC=
|
|
||||||
CFLAGS=
|
|
||||||
SFLAGS=
|
|
||||||
INCLUDES=
|
|
||||||
|
|
||||||
SRCDIR=
|
|
||||||
SRCTOP=
|
|
||||||
|
|
||||||
all:
|
|
||||||
|
|
||||||
|
|
||||||
mostlyclean: clean
|
|
||||||
clean:
|
|
||||||
rm -f *.o *.lo *~ \
|
|
||||||
rm -rf objs
|
|
||||||
rm -f *.gcda *.gcno *.gcov
|
|
@ -1,3 +0,0 @@
|
|||||||
fill_window_sse.c SSE2 optimized fill_window
|
|
||||||
deflate_quick.c SSE4 optimized deflate strategy for use as level 1
|
|
||||||
crc_folding.c SSE4 + PCLMULQDQ optimized CRC folding implementation
|
|
@ -1,53 +0,0 @@
|
|||||||
# Makefile for zlib
|
|
||||||
# Copyright (C) 1995-2013 Jean-loup Gailly, Mark Adler
|
|
||||||
# For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
|
|
||||||
CC=
|
|
||||||
CFLAGS=
|
|
||||||
SFLAGS=
|
|
||||||
INCLUDES=
|
|
||||||
|
|
||||||
SRCDIR=
|
|
||||||
SRCTOP=
|
|
||||||
|
|
||||||
all: x86.o x86.lo fill_window_sse.o fill_window_sse.lo deflate_quick.o deflate_quick.lo insert_string_sse.o insert_string_sse.lo crc_folding.o crc_folding.lo
|
|
||||||
|
|
||||||
x86.o:
|
|
||||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/x86.c
|
|
||||||
|
|
||||||
x86.lo:
|
|
||||||
$(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/x86.c
|
|
||||||
|
|
||||||
fill_window_sse.o:
|
|
||||||
$(CC) $(CFLAGS) -msse2 $(INCLUDES) -c -o $@ $(SRCDIR)/fill_window_sse.c
|
|
||||||
|
|
||||||
fill_window_sse.lo:
|
|
||||||
$(CC) $(SFLAGS) -msse2 -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/fill_window_sse.c
|
|
||||||
|
|
||||||
deflate_quick.o:
|
|
||||||
$(CC) $(CFLAGS) -msse4 $(INCLUDES) -c -o $@ $(SRCDIR)/deflate_quick.c
|
|
||||||
|
|
||||||
deflate_quick.lo:
|
|
||||||
$(CC) $(SFLAGS) -msse4 -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/deflate_quick.c
|
|
||||||
|
|
||||||
insert_string_sse.o:
|
|
||||||
$(CC) $(CFLAGS) -msse4 $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse.c
|
|
||||||
|
|
||||||
insert_string_sse.lo:
|
|
||||||
$(CC) $(SFLAGS) -msse4 -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse.c
|
|
||||||
|
|
||||||
crc_folding.o:
|
|
||||||
$(CC) $(CFLAGS) -mpclmul -msse4 $(INCLUDES) -c -o $@ $(SRCDIR)/crc_folding.c
|
|
||||||
|
|
||||||
crc_folding.lo:
|
|
||||||
$(CC) $(SFLAGS) -mpclmul -msse4 -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/crc_folding.c
|
|
||||||
|
|
||||||
|
|
||||||
mostlyclean: clean
|
|
||||||
clean:
|
|
||||||
rm -f *.o *.lo *~ \
|
|
||||||
rm -rf objs
|
|
||||||
rm -f *.gcda *.gcno *.gcov
|
|
||||||
|
|
||||||
distclean:
|
|
||||||
rm -f Makefile
|
|
@ -1,465 +0,0 @@
|
|||||||
/*
|
|
||||||
* Compute the CRC32 using a parallelized folding approach with the PCLMULQDQ
|
|
||||||
* instruction.
|
|
||||||
*
|
|
||||||
* A white paper describing this algorithm can be found at:
|
|
||||||
* http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf
|
|
||||||
*
|
|
||||||
* Copyright (C) 2013 Intel Corporation. All rights reserved.
|
|
||||||
* Authors:
|
|
||||||
* Wajdi Feghali <wajdi.k.feghali@intel.com>
|
|
||||||
* Jim Guilford <james.guilford@intel.com>
|
|
||||||
* Vinodh Gopal <vinodh.gopal@intel.com>
|
|
||||||
* Erdinc Ozturk <erdinc.ozturk@intel.com>
|
|
||||||
* Jim Kukunas <james.t.kukunas@linux.intel.com>
|
|
||||||
*
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef X86_PCLMULQDQ_CRC
|
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <immintrin.h>
|
|
||||||
#include <wmmintrin.h>
|
|
||||||
|
|
||||||
#include "deflate.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define CRC_LOAD(s) \
|
|
||||||
do { \
|
|
||||||
__m128i xmm_crc0 = _mm_loadu_si128((__m128i *)s->crc0 + 0);\
|
|
||||||
__m128i xmm_crc1 = _mm_loadu_si128((__m128i *)s->crc0 + 1);\
|
|
||||||
__m128i xmm_crc2 = _mm_loadu_si128((__m128i *)s->crc0 + 2);\
|
|
||||||
__m128i xmm_crc3 = _mm_loadu_si128((__m128i *)s->crc0 + 3);\
|
|
||||||
__m128i xmm_crc_part = _mm_loadu_si128((__m128i *)s->crc0 + 4);
|
|
||||||
|
|
||||||
#define CRC_SAVE(s) \
|
|
||||||
_mm_storeu_si128((__m128i *)s->crc0 + 0, xmm_crc0);\
|
|
||||||
_mm_storeu_si128((__m128i *)s->crc0 + 1, xmm_crc1);\
|
|
||||||
_mm_storeu_si128((__m128i *)s->crc0 + 2, xmm_crc2);\
|
|
||||||
_mm_storeu_si128((__m128i *)s->crc0 + 3, xmm_crc3);\
|
|
||||||
_mm_storeu_si128((__m128i *)s->crc0 + 4, xmm_crc_part);\
|
|
||||||
} while (0);
|
|
||||||
|
|
||||||
ZLIB_INTERNAL void crc_fold_init(deflate_state *const s) {
|
|
||||||
CRC_LOAD(s)
|
|
||||||
|
|
||||||
xmm_crc0 = _mm_cvtsi32_si128(0x9db42487);
|
|
||||||
xmm_crc1 = _mm_setzero_si128();
|
|
||||||
xmm_crc2 = _mm_setzero_si128();
|
|
||||||
xmm_crc3 = _mm_setzero_si128();
|
|
||||||
|
|
||||||
CRC_SAVE(s)
|
|
||||||
|
|
||||||
s->strm->adler = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
local void fold_1(deflate_state *const s, __m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) {
|
|
||||||
const __m128i xmm_fold4 = _mm_set_epi32(
|
|
||||||
0x00000001, 0x54442bd4,
|
|
||||||
0x00000001, 0xc6e41596);
|
|
||||||
|
|
||||||
__m128i x_tmp3;
|
|
||||||
__m128 ps_crc0, ps_crc3, ps_res;
|
|
||||||
|
|
||||||
x_tmp3 = *xmm_crc3;
|
|
||||||
|
|
||||||
*xmm_crc3 = *xmm_crc0;
|
|
||||||
*xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01);
|
|
||||||
*xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10);
|
|
||||||
ps_crc0 = _mm_castsi128_ps(*xmm_crc0);
|
|
||||||
ps_crc3 = _mm_castsi128_ps(*xmm_crc3);
|
|
||||||
ps_res = _mm_xor_ps(ps_crc0, ps_crc3);
|
|
||||||
|
|
||||||
*xmm_crc0 = *xmm_crc1;
|
|
||||||
*xmm_crc1 = *xmm_crc2;
|
|
||||||
*xmm_crc2 = x_tmp3;
|
|
||||||
*xmm_crc3 = _mm_castps_si128(ps_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
local void fold_2(deflate_state *const s, __m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) {
|
|
||||||
const __m128i xmm_fold4 = _mm_set_epi32(
|
|
||||||
0x00000001, 0x54442bd4,
|
|
||||||
0x00000001, 0xc6e41596);
|
|
||||||
|
|
||||||
__m128i x_tmp3, x_tmp2;
|
|
||||||
__m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3, ps_res31, ps_res20;
|
|
||||||
|
|
||||||
x_tmp3 = *xmm_crc3;
|
|
||||||
x_tmp2 = *xmm_crc2;
|
|
||||||
|
|
||||||
*xmm_crc3 = *xmm_crc1;
|
|
||||||
*xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01);
|
|
||||||
*xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10);
|
|
||||||
ps_crc3 = _mm_castsi128_ps(*xmm_crc3);
|
|
||||||
ps_crc1 = _mm_castsi128_ps(*xmm_crc1);
|
|
||||||
ps_res31 = _mm_xor_ps(ps_crc3, ps_crc1);
|
|
||||||
|
|
||||||
*xmm_crc2 = *xmm_crc0;
|
|
||||||
*xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01);
|
|
||||||
*xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x10);
|
|
||||||
ps_crc0 = _mm_castsi128_ps(*xmm_crc0);
|
|
||||||
ps_crc2 = _mm_castsi128_ps(*xmm_crc2);
|
|
||||||
ps_res20 = _mm_xor_ps(ps_crc0, ps_crc2);
|
|
||||||
|
|
||||||
*xmm_crc0 = x_tmp2;
|
|
||||||
*xmm_crc1 = x_tmp3;
|
|
||||||
*xmm_crc2 = _mm_castps_si128(ps_res20);
|
|
||||||
*xmm_crc3 = _mm_castps_si128(ps_res31);
|
|
||||||
}
|
|
||||||
|
|
||||||
local void fold_3(deflate_state *const s, __m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) {
|
|
||||||
const __m128i xmm_fold4 = _mm_set_epi32(
|
|
||||||
0x00000001, 0x54442bd4,
|
|
||||||
0x00000001, 0xc6e41596);
|
|
||||||
|
|
||||||
__m128i x_tmp3;
|
|
||||||
__m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3, ps_res32, ps_res21, ps_res10;
|
|
||||||
|
|
||||||
x_tmp3 = *xmm_crc3;
|
|
||||||
|
|
||||||
*xmm_crc3 = *xmm_crc2;
|
|
||||||
*xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x01);
|
|
||||||
*xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10);
|
|
||||||
ps_crc2 = _mm_castsi128_ps(*xmm_crc2);
|
|
||||||
ps_crc3 = _mm_castsi128_ps(*xmm_crc3);
|
|
||||||
ps_res32 = _mm_xor_ps(ps_crc2, ps_crc3);
|
|
||||||
|
|
||||||
*xmm_crc2 = *xmm_crc1;
|
|
||||||
*xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01);
|
|
||||||
*xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x10);
|
|
||||||
ps_crc1 = _mm_castsi128_ps(*xmm_crc1);
|
|
||||||
ps_crc2 = _mm_castsi128_ps(*xmm_crc2);
|
|
||||||
ps_res21 = _mm_xor_ps(ps_crc1, ps_crc2);
|
|
||||||
|
|
||||||
*xmm_crc1 = *xmm_crc0;
|
|
||||||
*xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01);
|
|
||||||
*xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x10);
|
|
||||||
ps_crc0 = _mm_castsi128_ps(*xmm_crc0);
|
|
||||||
ps_crc1 = _mm_castsi128_ps(*xmm_crc1);
|
|
||||||
ps_res10 = _mm_xor_ps(ps_crc0, ps_crc1);
|
|
||||||
|
|
||||||
*xmm_crc0 = x_tmp3;
|
|
||||||
*xmm_crc1 = _mm_castps_si128(ps_res10);
|
|
||||||
*xmm_crc2 = _mm_castps_si128(ps_res21);
|
|
||||||
*xmm_crc3 = _mm_castps_si128(ps_res32);
|
|
||||||
}
|
|
||||||
|
|
||||||
local void fold_4(deflate_state *const s, __m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) {
|
|
||||||
const __m128i xmm_fold4 = _mm_set_epi32(
|
|
||||||
0x00000001, 0x54442bd4,
|
|
||||||
0x00000001, 0xc6e41596);
|
|
||||||
|
|
||||||
__m128i x_tmp0, x_tmp1, x_tmp2, x_tmp3;
|
|
||||||
__m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3;
|
|
||||||
__m128 ps_t0, ps_t1, ps_t2, ps_t3;
|
|
||||||
__m128 ps_res0, ps_res1, ps_res2, ps_res3;
|
|
||||||
|
|
||||||
x_tmp0 = *xmm_crc0;
|
|
||||||
x_tmp1 = *xmm_crc1;
|
|
||||||
x_tmp2 = *xmm_crc2;
|
|
||||||
x_tmp3 = *xmm_crc3;
|
|
||||||
|
|
||||||
*xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01);
|
|
||||||
x_tmp0 = _mm_clmulepi64_si128(x_tmp0, xmm_fold4, 0x10);
|
|
||||||
ps_crc0 = _mm_castsi128_ps(*xmm_crc0);
|
|
||||||
ps_t0 = _mm_castsi128_ps(x_tmp0);
|
|
||||||
ps_res0 = _mm_xor_ps(ps_crc0, ps_t0);
|
|
||||||
|
|
||||||
*xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01);
|
|
||||||
x_tmp1 = _mm_clmulepi64_si128(x_tmp1, xmm_fold4, 0x10);
|
|
||||||
ps_crc1 = _mm_castsi128_ps(*xmm_crc1);
|
|
||||||
ps_t1 = _mm_castsi128_ps(x_tmp1);
|
|
||||||
ps_res1 = _mm_xor_ps(ps_crc1, ps_t1);
|
|
||||||
|
|
||||||
*xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x01);
|
|
||||||
x_tmp2 = _mm_clmulepi64_si128(x_tmp2, xmm_fold4, 0x10);
|
|
||||||
ps_crc2 = _mm_castsi128_ps(*xmm_crc2);
|
|
||||||
ps_t2 = _mm_castsi128_ps(x_tmp2);
|
|
||||||
ps_res2 = _mm_xor_ps(ps_crc2, ps_t2);
|
|
||||||
|
|
||||||
*xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x01);
|
|
||||||
x_tmp3 = _mm_clmulepi64_si128(x_tmp3, xmm_fold4, 0x10);
|
|
||||||
ps_crc3 = _mm_castsi128_ps(*xmm_crc3);
|
|
||||||
ps_t3 = _mm_castsi128_ps(x_tmp3);
|
|
||||||
ps_res3 = _mm_xor_ps(ps_crc3, ps_t3);
|
|
||||||
|
|
||||||
*xmm_crc0 = _mm_castps_si128(ps_res0);
|
|
||||||
*xmm_crc1 = _mm_castps_si128(ps_res1);
|
|
||||||
*xmm_crc2 = _mm_castps_si128(ps_res2);
|
|
||||||
*xmm_crc3 = _mm_castps_si128(ps_res3);
|
|
||||||
}
|
|
||||||
|
|
||||||
local const unsigned ALIGNED_(32) pshufb_shf_table[60] = {
|
|
||||||
0x84838281, 0x88878685, 0x8c8b8a89, 0x008f8e8d, /* shl 15 (16 - 1)/shr1 */
|
|
||||||
0x85848382, 0x89888786, 0x8d8c8b8a, 0x01008f8e, /* shl 14 (16 - 3)/shr2 */
|
|
||||||
0x86858483, 0x8a898887, 0x8e8d8c8b, 0x0201008f, /* shl 13 (16 - 4)/shr3 */
|
|
||||||
0x87868584, 0x8b8a8988, 0x8f8e8d8c, 0x03020100, /* shl 12 (16 - 4)/shr4 */
|
|
||||||
0x88878685, 0x8c8b8a89, 0x008f8e8d, 0x04030201, /* shl 11 (16 - 5)/shr5 */
|
|
||||||
0x89888786, 0x8d8c8b8a, 0x01008f8e, 0x05040302, /* shl 10 (16 - 6)/shr6 */
|
|
||||||
0x8a898887, 0x8e8d8c8b, 0x0201008f, 0x06050403, /* shl 9 (16 - 7)/shr7 */
|
|
||||||
0x8b8a8988, 0x8f8e8d8c, 0x03020100, 0x07060504, /* shl 8 (16 - 8)/shr8 */
|
|
||||||
0x8c8b8a89, 0x008f8e8d, 0x04030201, 0x08070605, /* shl 7 (16 - 9)/shr9 */
|
|
||||||
0x8d8c8b8a, 0x01008f8e, 0x05040302, 0x09080706, /* shl 6 (16 -10)/shr10*/
|
|
||||||
0x8e8d8c8b, 0x0201008f, 0x06050403, 0x0a090807, /* shl 5 (16 -11)/shr11*/
|
|
||||||
0x8f8e8d8c, 0x03020100, 0x07060504, 0x0b0a0908, /* shl 4 (16 -12)/shr12*/
|
|
||||||
0x008f8e8d, 0x04030201, 0x08070605, 0x0c0b0a09, /* shl 3 (16 -13)/shr13*/
|
|
||||||
0x01008f8e, 0x05040302, 0x09080706, 0x0d0c0b0a, /* shl 2 (16 -14)/shr14*/
|
|
||||||
0x0201008f, 0x06050403, 0x0a090807, 0x0e0d0c0b /* shl 1 (16 -15)/shr15*/
|
|
||||||
};
|
|
||||||
|
|
||||||
local void partial_fold(deflate_state *const s, const size_t len, __m128i *xmm_crc0, __m128i *xmm_crc1,
|
|
||||||
__m128i *xmm_crc2, __m128i *xmm_crc3, __m128i *xmm_crc_part) {
|
|
||||||
|
|
||||||
const __m128i xmm_fold4 = _mm_set_epi32(
|
|
||||||
0x00000001, 0x54442bd4,
|
|
||||||
0x00000001, 0xc6e41596);
|
|
||||||
const __m128i xmm_mask3 = _mm_set1_epi32(0x80808080);
|
|
||||||
|
|
||||||
__m128i xmm_shl, xmm_shr, xmm_tmp1, xmm_tmp2, xmm_tmp3;
|
|
||||||
__m128i xmm_a0_0, xmm_a0_1;
|
|
||||||
__m128 ps_crc3, psa0_0, psa0_1, ps_res;
|
|
||||||
|
|
||||||
xmm_shl = _mm_load_si128((__m128i *)pshufb_shf_table + (len - 1));
|
|
||||||
xmm_shr = xmm_shl;
|
|
||||||
xmm_shr = _mm_xor_si128(xmm_shr, xmm_mask3);
|
|
||||||
|
|
||||||
xmm_a0_0 = _mm_shuffle_epi8(*xmm_crc0, xmm_shl);
|
|
||||||
|
|
||||||
*xmm_crc0 = _mm_shuffle_epi8(*xmm_crc0, xmm_shr);
|
|
||||||
xmm_tmp1 = _mm_shuffle_epi8(*xmm_crc1, xmm_shl);
|
|
||||||
*xmm_crc0 = _mm_or_si128(*xmm_crc0, xmm_tmp1);
|
|
||||||
|
|
||||||
*xmm_crc1 = _mm_shuffle_epi8(*xmm_crc1, xmm_shr);
|
|
||||||
xmm_tmp2 = _mm_shuffle_epi8(*xmm_crc2, xmm_shl);
|
|
||||||
*xmm_crc1 = _mm_or_si128(*xmm_crc1, xmm_tmp2);
|
|
||||||
|
|
||||||
*xmm_crc2 = _mm_shuffle_epi8(*xmm_crc2, xmm_shr);
|
|
||||||
xmm_tmp3 = _mm_shuffle_epi8(*xmm_crc3, xmm_shl);
|
|
||||||
*xmm_crc2 = _mm_or_si128(*xmm_crc2, xmm_tmp3);
|
|
||||||
|
|
||||||
*xmm_crc3 = _mm_shuffle_epi8(*xmm_crc3, xmm_shr);
|
|
||||||
*xmm_crc_part = _mm_shuffle_epi8(*xmm_crc_part, xmm_shl);
|
|
||||||
*xmm_crc3 = _mm_or_si128(*xmm_crc3, *xmm_crc_part);
|
|
||||||
|
|
||||||
xmm_a0_1 = _mm_clmulepi64_si128(xmm_a0_0, xmm_fold4, 0x10);
|
|
||||||
xmm_a0_0 = _mm_clmulepi64_si128(xmm_a0_0, xmm_fold4, 0x01);
|
|
||||||
|
|
||||||
ps_crc3 = _mm_castsi128_ps(*xmm_crc3);
|
|
||||||
psa0_0 = _mm_castsi128_ps(xmm_a0_0);
|
|
||||||
psa0_1 = _mm_castsi128_ps(xmm_a0_1);
|
|
||||||
|
|
||||||
ps_res = _mm_xor_ps(ps_crc3, psa0_0);
|
|
||||||
ps_res = _mm_xor_ps(ps_res, psa0_1);
|
|
||||||
|
|
||||||
*xmm_crc3 = _mm_castps_si128(ps_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
ZLIB_INTERNAL void crc_fold_copy(deflate_state *const s, unsigned char *dst, const unsigned char *src, long len) {
|
|
||||||
unsigned long algn_diff;
|
|
||||||
__m128i xmm_t0, xmm_t1, xmm_t2, xmm_t3;
|
|
||||||
|
|
||||||
CRC_LOAD(s)
|
|
||||||
|
|
||||||
if (len < 16) {
|
|
||||||
if (len == 0)
|
|
||||||
return;
|
|
||||||
xmm_crc_part = _mm_loadu_si128((__m128i *)src);
|
|
||||||
goto partial;
|
|
||||||
}
|
|
||||||
|
|
||||||
algn_diff = (0 - (uintptr_t)src) & 0xF;
|
|
||||||
if (algn_diff) {
|
|
||||||
xmm_crc_part = _mm_loadu_si128((__m128i *)src);
|
|
||||||
_mm_storeu_si128((__m128i *)dst, xmm_crc_part);
|
|
||||||
|
|
||||||
dst += algn_diff;
|
|
||||||
src += algn_diff;
|
|
||||||
len -= algn_diff;
|
|
||||||
|
|
||||||
partial_fold(s, algn_diff, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3,
|
|
||||||
&xmm_crc_part);
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((len -= 64) >= 0) {
|
|
||||||
xmm_t0 = _mm_load_si128((__m128i *)src);
|
|
||||||
xmm_t1 = _mm_load_si128((__m128i *)src + 1);
|
|
||||||
xmm_t2 = _mm_load_si128((__m128i *)src + 2);
|
|
||||||
xmm_t3 = _mm_load_si128((__m128i *)src + 3);
|
|
||||||
|
|
||||||
fold_4(s, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3);
|
|
||||||
|
|
||||||
_mm_storeu_si128((__m128i *)dst, xmm_t0);
|
|
||||||
_mm_storeu_si128((__m128i *)dst + 1, xmm_t1);
|
|
||||||
_mm_storeu_si128((__m128i *)dst + 2, xmm_t2);
|
|
||||||
_mm_storeu_si128((__m128i *)dst + 3, xmm_t3);
|
|
||||||
|
|
||||||
xmm_crc0 = _mm_xor_si128(xmm_crc0, xmm_t0);
|
|
||||||
xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t1);
|
|
||||||
xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t2);
|
|
||||||
xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t3);
|
|
||||||
|
|
||||||
src += 64;
|
|
||||||
dst += 64;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* len = num bytes left - 64
|
|
||||||
*/
|
|
||||||
if (len + 16 >= 0) {
|
|
||||||
len += 16;
|
|
||||||
|
|
||||||
xmm_t0 = _mm_load_si128((__m128i *)src);
|
|
||||||
xmm_t1 = _mm_load_si128((__m128i *)src + 1);
|
|
||||||
xmm_t2 = _mm_load_si128((__m128i *)src + 2);
|
|
||||||
|
|
||||||
fold_3(s, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3);
|
|
||||||
|
|
||||||
_mm_storeu_si128((__m128i *)dst, xmm_t0);
|
|
||||||
_mm_storeu_si128((__m128i *)dst + 1, xmm_t1);
|
|
||||||
_mm_storeu_si128((__m128i *)dst + 2, xmm_t2);
|
|
||||||
|
|
||||||
xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t0);
|
|
||||||
xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t1);
|
|
||||||
xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t2);
|
|
||||||
|
|
||||||
if (len == 0)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
dst += 48;
|
|
||||||
xmm_crc_part = _mm_load_si128((__m128i *)src + 3);
|
|
||||||
} else if (len + 32 >= 0) {
|
|
||||||
len += 32;
|
|
||||||
|
|
||||||
xmm_t0 = _mm_load_si128((__m128i *)src);
|
|
||||||
xmm_t1 = _mm_load_si128((__m128i *)src + 1);
|
|
||||||
|
|
||||||
fold_2(s, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3);
|
|
||||||
|
|
||||||
_mm_storeu_si128((__m128i *)dst, xmm_t0);
|
|
||||||
_mm_storeu_si128((__m128i *)dst + 1, xmm_t1);
|
|
||||||
|
|
||||||
xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t0);
|
|
||||||
xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t1);
|
|
||||||
|
|
||||||
if (len == 0)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
dst += 32;
|
|
||||||
xmm_crc_part = _mm_load_si128((__m128i *)src + 2);
|
|
||||||
} else if (len + 48 >= 0) {
|
|
||||||
len += 48;
|
|
||||||
|
|
||||||
xmm_t0 = _mm_load_si128((__m128i *)src);
|
|
||||||
|
|
||||||
fold_1(s, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3);
|
|
||||||
|
|
||||||
_mm_storeu_si128((__m128i *)dst, xmm_t0);
|
|
||||||
|
|
||||||
xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t0);
|
|
||||||
|
|
||||||
if (len == 0)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
dst += 16;
|
|
||||||
xmm_crc_part = _mm_load_si128((__m128i *)src + 1);
|
|
||||||
} else {
|
|
||||||
len += 64;
|
|
||||||
if (len == 0)
|
|
||||||
goto done;
|
|
||||||
xmm_crc_part = _mm_load_si128((__m128i *)src);
|
|
||||||
}
|
|
||||||
|
|
||||||
partial:
|
|
||||||
_mm_storeu_si128((__m128i *)dst, xmm_crc_part);
|
|
||||||
partial_fold(s, len, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3,
|
|
||||||
&xmm_crc_part);
|
|
||||||
done:
|
|
||||||
CRC_SAVE(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
local const unsigned ALIGNED_(16) crc_k[] = {
|
|
||||||
0xccaa009e, 0x00000000, /* rk1 */
|
|
||||||
0x751997d0, 0x00000001, /* rk2 */
|
|
||||||
0xccaa009e, 0x00000000, /* rk5 */
|
|
||||||
0x63cd6124, 0x00000001, /* rk6 */
|
|
||||||
0xf7011640, 0x00000001, /* rk7 */
|
|
||||||
0xdb710640, 0x00000001 /* rk8 */
|
|
||||||
};
|
|
||||||
|
|
||||||
local const unsigned ALIGNED_(16) crc_mask[4] = {
|
|
||||||
0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000
|
|
||||||
};
|
|
||||||
|
|
||||||
local const unsigned ALIGNED_(16) crc_mask2[4] = {
|
|
||||||
0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
|
|
||||||
};
|
|
||||||
|
|
||||||
uint32_t ZLIB_INTERNAL crc_fold_512to32(deflate_state *const s) {
|
|
||||||
const __m128i xmm_mask = _mm_load_si128((__m128i *)crc_mask);
|
|
||||||
const __m128i xmm_mask2 = _mm_load_si128((__m128i *)crc_mask2);
|
|
||||||
|
|
||||||
uint32_t crc;
|
|
||||||
__m128i x_tmp0, x_tmp1, x_tmp2, crc_fold;
|
|
||||||
|
|
||||||
CRC_LOAD(s)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* k1
|
|
||||||
*/
|
|
||||||
crc_fold = _mm_load_si128((__m128i *)crc_k);
|
|
||||||
|
|
||||||
x_tmp0 = _mm_clmulepi64_si128(xmm_crc0, crc_fold, 0x10);
|
|
||||||
xmm_crc0 = _mm_clmulepi64_si128(xmm_crc0, crc_fold, 0x01);
|
|
||||||
xmm_crc1 = _mm_xor_si128(xmm_crc1, x_tmp0);
|
|
||||||
xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_crc0);
|
|
||||||
|
|
||||||
x_tmp1 = _mm_clmulepi64_si128(xmm_crc1, crc_fold, 0x10);
|
|
||||||
xmm_crc1 = _mm_clmulepi64_si128(xmm_crc1, crc_fold, 0x01);
|
|
||||||
xmm_crc2 = _mm_xor_si128(xmm_crc2, x_tmp1);
|
|
||||||
xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_crc1);
|
|
||||||
|
|
||||||
x_tmp2 = _mm_clmulepi64_si128(xmm_crc2, crc_fold, 0x10);
|
|
||||||
xmm_crc2 = _mm_clmulepi64_si128(xmm_crc2, crc_fold, 0x01);
|
|
||||||
xmm_crc3 = _mm_xor_si128(xmm_crc3, x_tmp2);
|
|
||||||
xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* k5
|
|
||||||
*/
|
|
||||||
crc_fold = _mm_load_si128((__m128i *)crc_k + 1);
|
|
||||||
|
|
||||||
xmm_crc0 = xmm_crc3;
|
|
||||||
xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0);
|
|
||||||
xmm_crc0 = _mm_srli_si128(xmm_crc0, 8);
|
|
||||||
xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc0);
|
|
||||||
|
|
||||||
xmm_crc0 = xmm_crc3;
|
|
||||||
xmm_crc3 = _mm_slli_si128(xmm_crc3, 4);
|
|
||||||
xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0x10);
|
|
||||||
xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc0);
|
|
||||||
xmm_crc3 = _mm_and_si128(xmm_crc3, xmm_mask2);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* k7
|
|
||||||
*/
|
|
||||||
xmm_crc1 = xmm_crc3;
|
|
||||||
xmm_crc2 = xmm_crc3;
|
|
||||||
crc_fold = _mm_load_si128((__m128i *)crc_k + 2);
|
|
||||||
|
|
||||||
xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0);
|
|
||||||
xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2);
|
|
||||||
xmm_crc3 = _mm_and_si128(xmm_crc3, xmm_mask);
|
|
||||||
|
|
||||||
xmm_crc2 = xmm_crc3;
|
|
||||||
xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0x10);
|
|
||||||
xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2);
|
|
||||||
xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc1);
|
|
||||||
|
|
||||||
crc = _mm_extract_epi32(xmm_crc3, 2);
|
|
||||||
return ~crc;
|
|
||||||
CRC_SAVE(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -1,165 +0,0 @@
|
|||||||
/*
|
|
||||||
* Fill Window with SSE2-optimized hash shifting
|
|
||||||
*
|
|
||||||
* Copyright (C) 2013 Intel Corporation
|
|
||||||
* Authors:
|
|
||||||
* Arjan van de Ven <arjan@linux.intel.com>
|
|
||||||
* Jim Kukunas <james.t.kukunas@linux.intel.com>
|
|
||||||
*
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
#ifdef X86_SSE2_FILL_WINDOW
|
|
||||||
|
|
||||||
#include <immintrin.h>
|
|
||||||
#include "deflate.h"
|
|
||||||
|
|
||||||
extern int read_buf(z_stream *strm, unsigned char *buf, unsigned size);
|
|
||||||
|
|
||||||
ZLIB_INTERNAL void fill_window_sse(deflate_state *s) {
|
|
||||||
const __m128i xmm_wsize = _mm_set1_epi16(s->w_size);
|
|
||||||
|
|
||||||
register unsigned n;
|
|
||||||
register Pos *p;
|
|
||||||
unsigned more; /* Amount of free space at the end of the window. */
|
|
||||||
unsigned int wsize = s->w_size;
|
|
||||||
|
|
||||||
Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");
|
|
||||||
|
|
||||||
do {
|
|
||||||
more = (unsigned)(s->window_size -(unsigned long)s->lookahead -(unsigned long)s->strstart);
|
|
||||||
|
|
||||||
/* Deal with !@#$% 64K limit: */
|
|
||||||
if (sizeof(int) <= 2) {
|
|
||||||
if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
|
|
||||||
more = wsize;
|
|
||||||
|
|
||||||
} else if (more == (unsigned)(-1)) {
|
|
||||||
/* Very unlikely, but possible on 16 bit machine if
|
|
||||||
* strstart == 0 && lookahead == 1 (input done a byte at time)
|
|
||||||
*/
|
|
||||||
more--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the window is almost full and there is insufficient lookahead,
|
|
||||||
* move the upper half to the lower one to make room in the upper half.
|
|
||||||
*/
|
|
||||||
if (s->strstart >= wsize+MAX_DIST(s)) {
|
|
||||||
memcpy(s->window, s->window+wsize, (unsigned)wsize);
|
|
||||||
s->match_start -= wsize;
|
|
||||||
s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
|
|
||||||
s->block_start -= (long) wsize;
|
|
||||||
|
|
||||||
/* Slide the hash table (could be avoided with 32 bit values
|
|
||||||
at the expense of memory usage). We slide even when level == 0
|
|
||||||
to keep the hash table consistent if we switch back to level > 0
|
|
||||||
later. (Using level 0 permanently is not an optimal usage of
|
|
||||||
zlib, so we don't care about this pathological case.)
|
|
||||||
*/
|
|
||||||
n = s->hash_size;
|
|
||||||
p = &s->head[n];
|
|
||||||
p -= 8;
|
|
||||||
do {
|
|
||||||
__m128i value, result;
|
|
||||||
|
|
||||||
value = _mm_loadu_si128((__m128i *)p);
|
|
||||||
result = _mm_subs_epu16(value, xmm_wsize);
|
|
||||||
_mm_storeu_si128((__m128i *)p, result);
|
|
||||||
|
|
||||||
p -= 8;
|
|
||||||
n -= 8;
|
|
||||||
} while (n > 0);
|
|
||||||
|
|
||||||
n = wsize;
|
|
||||||
p = &s->prev[n];
|
|
||||||
p -= 8;
|
|
||||||
do {
|
|
||||||
__m128i value, result;
|
|
||||||
|
|
||||||
value = _mm_loadu_si128((__m128i *)p);
|
|
||||||
result = _mm_subs_epu16(value, xmm_wsize);
|
|
||||||
_mm_storeu_si128((__m128i *)p, result);
|
|
||||||
|
|
||||||
p -= 8;
|
|
||||||
n -= 8;
|
|
||||||
} while (n > 0);
|
|
||||||
more += wsize;
|
|
||||||
}
|
|
||||||
if (s->strm->avail_in == 0) break;
|
|
||||||
|
|
||||||
/* If there was no sliding:
|
|
||||||
* strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
|
|
||||||
* more == window_size - lookahead - strstart
|
|
||||||
* => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
|
|
||||||
* => more >= window_size - 2*WSIZE + 2
|
|
||||||
* In the BIG_MEM or MMAP case (not yet supported),
|
|
||||||
* window_size == input_size + MIN_LOOKAHEAD &&
|
|
||||||
* strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
|
|
||||||
* Otherwise, window_size == 2*WSIZE so more >= 2.
|
|
||||||
* If there was sliding, more >= WSIZE. So in all cases, more >= 2.
|
|
||||||
*/
|
|
||||||
Assert(more >= 2, "more < 2");
|
|
||||||
|
|
||||||
n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
|
|
||||||
s->lookahead += n;
|
|
||||||
|
|
||||||
/* Initialize the hash value now that we have some input: */
|
|
||||||
if (s->lookahead + s->insert >= MIN_MATCH) {
|
|
||||||
unsigned int str = s->strstart - s->insert;
|
|
||||||
s->ins_h = s->window[str];
|
|
||||||
if (str >= 1)
|
|
||||||
UPDATE_HASH(s, s->ins_h, str + 1 - (MIN_MATCH-1));
|
|
||||||
#if MIN_MATCH != 3
|
|
||||||
Call UPDATE_HASH() MIN_MATCH-3 more times
|
|
||||||
#endif
|
|
||||||
while (s->insert) {
|
|
||||||
UPDATE_HASH(s, s->ins_h, str);
|
|
||||||
s->prev[str & s->w_mask] = s->head[s->ins_h];
|
|
||||||
s->head[s->ins_h] = (Pos)str;
|
|
||||||
str++;
|
|
||||||
s->insert--;
|
|
||||||
if (s->lookahead + s->insert < MIN_MATCH)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
|
|
||||||
* but this is not important since only literal bytes will be emitted.
|
|
||||||
*/
|
|
||||||
} while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
|
|
||||||
|
|
||||||
/* If the WIN_INIT bytes after the end of the current data have never been
|
|
||||||
* written, then zero those bytes in order to avoid memory check reports of
|
|
||||||
* the use of uninitialized (or uninitialised as Julian writes) bytes by
|
|
||||||
* the longest match routines. Update the high water mark for the next
|
|
||||||
* time through here. WIN_INIT is set to MAX_MATCH since the longest match
|
|
||||||
* routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
|
|
||||||
*/
|
|
||||||
if (s->high_water < s->window_size) {
|
|
||||||
unsigned long curr = s->strstart + (unsigned long)(s->lookahead);
|
|
||||||
unsigned long init;
|
|
||||||
|
|
||||||
if (s->high_water < curr) {
|
|
||||||
/* Previous high water mark below current data -- zero WIN_INIT
|
|
||||||
* bytes or up to end of window, whichever is less.
|
|
||||||
*/
|
|
||||||
init = s->window_size - curr;
|
|
||||||
if (init > WIN_INIT)
|
|
||||||
init = WIN_INIT;
|
|
||||||
memset(s->window + curr, 0, (unsigned)init);
|
|
||||||
s->high_water = curr + init;
|
|
||||||
} else if (s->high_water < (unsigned long)curr + WIN_INIT) {
|
|
||||||
/* High water mark at or above current data, but below current data
|
|
||||||
* plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
|
|
||||||
* to end of window, whichever is less.
|
|
||||||
*/
|
|
||||||
init = (unsigned long)curr + WIN_INIT - s->high_water;
|
|
||||||
if (init > s->window_size - s->high_water)
|
|
||||||
init = s->window_size - s->high_water;
|
|
||||||
memset(s->window + s->high_water, 0, (unsigned)init);
|
|
||||||
s->high_water += init;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert((unsigned long)s->strstart <= s->window_size - MIN_LOOKAHEAD, "not enough room for search");
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,50 +0,0 @@
|
|||||||
/* insert_string_sse -- insert_string variant using SSE4.2's CRC instructions
|
|
||||||
*
|
|
||||||
* Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "deflate.h"
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Insert string str in the dictionary and set match_head to the previous head
|
|
||||||
* of the hash chain (the most recent string with same hash key). Return
|
|
||||||
* the previous length of the hash chain.
|
|
||||||
* IN assertion: all calls to to INSERT_STRING are made with consecutive
|
|
||||||
* input characters and the first MIN_MATCH bytes of str are valid
|
|
||||||
* (except for the last MIN_MATCH-1 bytes of the input file).
|
|
||||||
*/
|
|
||||||
#ifdef X86_SSE4_2_CRC_HASH
|
|
||||||
Pos insert_string_sse(deflate_state *const s, const Pos str, unsigned int count) {
|
|
||||||
Pos ret = 0;
|
|
||||||
unsigned int idx;
|
|
||||||
unsigned *ip, val, h = 0;
|
|
||||||
|
|
||||||
for (idx = 0; idx < count; idx++) {
|
|
||||||
ip = (unsigned *)&s->window[str+idx];
|
|
||||||
val = *ip;
|
|
||||||
h = 0;
|
|
||||||
|
|
||||||
if (s->level >= 6)
|
|
||||||
val &= 0xFFFFFF;
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
h = _mm_crc32_u32(h, val);
|
|
||||||
#else
|
|
||||||
__asm__ __volatile__ (
|
|
||||||
"crc32 %1,%0\n\t"
|
|
||||||
: "+r" (h)
|
|
||||||
: "r" (val)
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (s->head[h & s->hash_mask] != str+idx) {
|
|
||||||
s->prev[(str+idx) & s->w_mask] = s->head[h & s->hash_mask];
|
|
||||||
s->head[h & s->hash_mask] = str+idx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret = s->prev[(str+count-1) & s->w_mask];
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
* x86 feature check
|
|
||||||
*
|
|
||||||
* Copyright (C) 2013 Intel Corporation. All rights reserved.
|
|
||||||
* Author:
|
|
||||||
* Jim Kukunas
|
|
||||||
*
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "x86.h"
|
|
||||||
|
|
||||||
ZLIB_INTERNAL int x86_cpu_has_sse2;
|
|
||||||
ZLIB_INTERNAL int x86_cpu_has_sse42;
|
|
||||||
ZLIB_INTERNAL int x86_cpu_has_pclmulqdq;
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#include <intrin.h>
|
|
||||||
#else
|
|
||||||
// Newer versions of GCC and clang come with cpuid.h
|
|
||||||
#include <cpuid.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) {
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
unsigned int registers[4];
|
|
||||||
__cpuid(registers, info);
|
|
||||||
|
|
||||||
*eax = registers[0];
|
|
||||||
*ebx = registers[1];
|
|
||||||
*ecx = registers[2];
|
|
||||||
*edx = registers[3];
|
|
||||||
#else
|
|
||||||
unsigned int _eax;
|
|
||||||
unsigned int _ebx;
|
|
||||||
unsigned int _ecx;
|
|
||||||
unsigned int _edx;
|
|
||||||
__cpuid(info, _eax, _ebx, _ecx, _edx);
|
|
||||||
*eax = _eax;
|
|
||||||
*ebx = _ebx;
|
|
||||||
*ecx = _ecx;
|
|
||||||
*edx = _edx;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZLIB_INTERNAL x86_check_features(void) {
|
|
||||||
unsigned eax, ebx, ecx, edx;
|
|
||||||
cpuid(1 /*CPU_PROCINFO_AND_FEATUREBITS*/, &eax, &ebx, &ecx, &edx);
|
|
||||||
|
|
||||||
x86_cpu_has_sse2 = edx & 0x4000000;
|
|
||||||
x86_cpu_has_sse42 = ecx & 0x100000;
|
|
||||||
x86_cpu_has_pclmulqdq = ecx & 0x2;
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
/* cpu.h -- check for CPU features
|
|
||||||
* Copyright (C) 2013 Intel Corporation Jim Kukunas
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CPU_H_
|
|
||||||
#define CPU_H_
|
|
||||||
|
|
||||||
#if defined(HAVE_INTERNAL)
|
|
||||||
# define ZLIB_INTERNAL __attribute__((visibility ("internal")))
|
|
||||||
#elif defined(HAVE_HIDDEN)
|
|
||||||
# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
|
|
||||||
#else
|
|
||||||
# define ZLIB_INTERNAL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern int x86_cpu_has_sse2;
|
|
||||||
extern int x86_cpu_has_sse42;
|
|
||||||
extern int x86_cpu_has_pclmulqdq;
|
|
||||||
|
|
||||||
void ZLIB_INTERNAL x86_check_features(void);
|
|
||||||
|
|
||||||
#endif /* CPU_H_ */
|
|
@ -1,74 +0,0 @@
|
|||||||
/* compress.c -- compress a memory buffer
|
|
||||||
* Copyright (C) 1995-2005, 2014 Jean-loup Gailly, Mark Adler.
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* @(#) $Id$ */
|
|
||||||
|
|
||||||
#define ZLIB_INTERNAL
|
|
||||||
#include "zlib.h"
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
Compresses the source buffer into the destination buffer. The level
|
|
||||||
parameter has the same meaning as in deflateInit. sourceLen is the byte
|
|
||||||
length of the source buffer. Upon entry, destLen is the total size of the
|
|
||||||
destination buffer, which must be at least 0.1% larger than sourceLen plus
|
|
||||||
12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
|
|
||||||
|
|
||||||
compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
|
|
||||||
memory, Z_BUF_ERROR if there was not enough room in the output buffer,
|
|
||||||
Z_STREAM_ERROR if the level parameter is invalid.
|
|
||||||
*/
|
|
||||||
int ZEXPORT compress2(unsigned char *dest, size_t *destLen, const unsigned char *source,
|
|
||||||
size_t sourceLen, int level) {
|
|
||||||
z_stream stream;
|
|
||||||
int err;
|
|
||||||
const unsigned int max = (unsigned int)0 - 1;
|
|
||||||
size_t left;
|
|
||||||
|
|
||||||
left = *destLen;
|
|
||||||
*destLen = 0;
|
|
||||||
|
|
||||||
stream.zalloc = (alloc_func)0;
|
|
||||||
stream.zfree = (free_func)0;
|
|
||||||
stream.opaque = NULL;
|
|
||||||
|
|
||||||
err = deflateInit(&stream, level);
|
|
||||||
if (err != Z_OK)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
stream.next_out = dest;
|
|
||||||
stream.avail_out = 0;
|
|
||||||
stream.next_in = (const unsigned char *)source;
|
|
||||||
stream.avail_in = 0;
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (stream.avail_out == 0) {
|
|
||||||
stream.avail_out = left > (unsigned long)max ? max : (unsigned int)left;
|
|
||||||
left -= stream.avail_out;
|
|
||||||
}
|
|
||||||
if (stream.avail_in == 0) {
|
|
||||||
stream.avail_in = sourceLen > (unsigned long)max ? max : (unsigned int)sourceLen;
|
|
||||||
sourceLen -= stream.avail_in;
|
|
||||||
}
|
|
||||||
err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH);
|
|
||||||
} while (err == Z_OK);
|
|
||||||
|
|
||||||
*destLen = stream.total_out;
|
|
||||||
deflateEnd(&stream);
|
|
||||||
return err == Z_STREAM_END ? Z_OK : err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
*/
|
|
||||||
int ZEXPORT compress(unsigned char *dest, size_t *destLen, const unsigned char *source, size_t sourceLen) {
|
|
||||||
return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
If the default memLevel or windowBits for deflateInit() is changed, then
|
|
||||||
this function needs to be updated.
|
|
||||||
*/
|
|
||||||
size_t ZEXPORT compressBound(size_t sourceLen) {
|
|
||||||
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13;
|
|
||||||
}
|
|
923
contrib/libzlib-ng/configure
vendored
923
contrib/libzlib-ng/configure
vendored
@ -1,923 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# configure script for zlib.
|
|
||||||
#
|
|
||||||
# Normally configure builds both a static and a shared library.
|
|
||||||
# If you want to build just a static library, use: ./configure --static
|
|
||||||
#
|
|
||||||
# To impose specific compiler or flags or install directory, use for example:
|
|
||||||
# prefix=$HOME CC=cc CFLAGS="-O4" ./configure
|
|
||||||
# or for csh/tcsh users:
|
|
||||||
# (setenv prefix $HOME; setenv CC cc; setenv CFLAGS "-O4"; ./configure)
|
|
||||||
|
|
||||||
# Incorrect settings of CC or CFLAGS may prevent creating a shared library.
|
|
||||||
# If you have problems, try without defining CC and CFLAGS before reporting
|
|
||||||
# an error.
|
|
||||||
|
|
||||||
# start off configure.log
|
|
||||||
echo -------------------- >> configure.log
|
|
||||||
echo $0 $* >> configure.log
|
|
||||||
date >> configure.log
|
|
||||||
|
|
||||||
SRCDIR=$(cd $(dirname $0); pwd)
|
|
||||||
BUILDDIR=$(pwd)
|
|
||||||
|
|
||||||
# set command prefix for cross-compilation
|
|
||||||
if [ -n "${CHOST}" ]; then
|
|
||||||
uname="`echo "${CHOST}" | sed -e 's/^[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)-.*$/\1/'`"
|
|
||||||
CROSS_PREFIX="${CHOST}-"
|
|
||||||
ARCH="`echo "${CHOST}" | sed -e 's/-.*//'`"
|
|
||||||
else
|
|
||||||
ARCH="`uname -m`"
|
|
||||||
fi
|
|
||||||
|
|
||||||
case "${ARCH}" in
|
|
||||||
x86_64)
|
|
||||||
case "${CFLAGS}" in
|
|
||||||
*-m32*)
|
|
||||||
ARCH=i686
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
i386 | i486 | i586 | i686)
|
|
||||||
case "${CFLAGS}" in
|
|
||||||
*-m64*)
|
|
||||||
ARCH=x86_64
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# destination name for static library
|
|
||||||
STATICLIB=libz.a
|
|
||||||
|
|
||||||
# destination name for windows import library
|
|
||||||
IMPORTLIB=
|
|
||||||
|
|
||||||
# extract zlib version numbers from zlib.h
|
|
||||||
VER=`sed -n -e '/ZLIB_VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}/zlib.h`
|
|
||||||
VER3=`sed -n -e '/ZLIB_VERSION "/s/.*"\([0-9]*\\.[0-9]*\\.[0-9]*\).*/\1/p' < ${SRCDIR}/zlib.h`
|
|
||||||
VER2=`sed -n -e '/ZLIB_VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < ${SRCDIR}/zlib.h`
|
|
||||||
VER1=`sed -n -e '/ZLIB_VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < ${SRCDIR}/zlib.h`
|
|
||||||
|
|
||||||
# establish commands for library building
|
|
||||||
if "${CROSS_PREFIX}ar" --version >/dev/null 2>/dev/null || test $? -lt 126; then
|
|
||||||
AR=${AR-"${CROSS_PREFIX}ar"}
|
|
||||||
test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log
|
|
||||||
else
|
|
||||||
AR=${AR-"ar"}
|
|
||||||
test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log
|
|
||||||
fi
|
|
||||||
ARFLAGS=${ARFLAGS-"rc"}
|
|
||||||
if "${CROSS_PREFIX}ranlib" --version >/dev/null 2>/dev/null || test $? -lt 126; then
|
|
||||||
RANLIB=${RANLIB-"${CROSS_PREFIX}ranlib"}
|
|
||||||
test -n "${CROSS_PREFIX}" && echo Using ${RANLIB} | tee -a configure.log
|
|
||||||
else
|
|
||||||
RANLIB=${RANLIB-"ranlib"}
|
|
||||||
fi
|
|
||||||
if "${CROSS_PREFIX}nm" --version >/dev/null 2>/dev/null || test $? -lt 126; then
|
|
||||||
NM=${NM-"${CROSS_PREFIX}nm"}
|
|
||||||
test -n "${CROSS_PREFIX}" && echo Using ${NM} | tee -a configure.log
|
|
||||||
else
|
|
||||||
NM=${NM-"nm"}
|
|
||||||
fi
|
|
||||||
|
|
||||||
# set defaults before processing command line options
|
|
||||||
LDCONFIG=${LDCONFIG-"ldconfig"}
|
|
||||||
LDSHAREDLIBC="${LDSHAREDLIBC--lc}"
|
|
||||||
DEFFILE=
|
|
||||||
RC=
|
|
||||||
RCFLAGS=
|
|
||||||
RCOBJS=
|
|
||||||
STRIP=
|
|
||||||
ARCHS=
|
|
||||||
prefix=${prefix-/usr/local}
|
|
||||||
exec_prefix=${exec_prefix-'${prefix}'}
|
|
||||||
bindir=${bindir-'${exec_prefix}/bin'}
|
|
||||||
libdir=${libdir-'${exec_prefix}/lib'}
|
|
||||||
sharedlibdir=${sharedlibdir-'${libdir}'}
|
|
||||||
includedir=${includedir-'${prefix}/include'}
|
|
||||||
mandir=${mandir-'${prefix}/share/man'}
|
|
||||||
shared_ext='.so'
|
|
||||||
shared=1
|
|
||||||
gzfileops=0
|
|
||||||
compat=0
|
|
||||||
cover=0
|
|
||||||
build32=0
|
|
||||||
build64=0
|
|
||||||
without_optimizations=0
|
|
||||||
without_new_strategies=0
|
|
||||||
gcc=0
|
|
||||||
old_cc="$CC"
|
|
||||||
old_cflags="$CFLAGS"
|
|
||||||
OBJC='$(OBJZ)'
|
|
||||||
PIC_OBJC='$(PIC_OBJZ)'
|
|
||||||
INSTALLTARGETS="install-shared install-static"
|
|
||||||
UNINSTALLTARGETS="uninstall-shared uninstall-static"
|
|
||||||
|
|
||||||
TEST="teststatic"
|
|
||||||
|
|
||||||
# leave this script, optionally in a bad way
|
|
||||||
leave()
|
|
||||||
{
|
|
||||||
if test "$*" != "0"; then
|
|
||||||
echo "** $0 aborting." | tee -a configure.log
|
|
||||||
fi
|
|
||||||
rm -f $test.[co] $test $test$shared_ext $test.gcno ./--version
|
|
||||||
echo -------------------- >> configure.log
|
|
||||||
echo >> configure.log
|
|
||||||
echo >> configure.log
|
|
||||||
exit $1
|
|
||||||
}
|
|
||||||
|
|
||||||
# process command line options
|
|
||||||
while test $# -ge 1
|
|
||||||
do
|
|
||||||
case "$1" in
|
|
||||||
-h* | --help)
|
|
||||||
echo 'usage:' | tee -a configure.log
|
|
||||||
echo ' configure [--zlib-compat] [--prefix=PREFIX] [--eprefix=EXPREFIX]' | tee -a configure.log
|
|
||||||
echo ' [--static] [--32] [--64] [--libdir=LIBDIR] [--sharedlibdir=LIBDIR]' | tee -a configure.log
|
|
||||||
echo ' [--includedir=INCLUDEDIR] [--archs="-arch i386 -arch x86_64"]' | tee -a configure.log
|
|
||||||
exit 0 ;;
|
|
||||||
-p*=* | --prefix=*) prefix=`echo $1 | sed 's/.*=//'`; shift ;;
|
|
||||||
-e*=* | --eprefix=*) exec_prefix=`echo $1 | sed 's/.*=//'`; shift ;;
|
|
||||||
-l*=* | --libdir=*) libdir=`echo $1 | sed 's/.*=//'`; shift ;;
|
|
||||||
--sharedlibdir=*) sharedlibdir=`echo $1 | sed 's/.*=//'`; shift ;;
|
|
||||||
-i*=* | --includedir=*) includedir=`echo $1 | sed 's/.*=//'`;shift ;;
|
|
||||||
-u*=* | --uname=*) uname=`echo $1 | sed 's/.*=//'`;shift ;;
|
|
||||||
-p* | --prefix) prefix="$2"; shift; shift ;;
|
|
||||||
-e* | --eprefix) exec_prefix="$2"; shift; shift ;;
|
|
||||||
-l* | --libdir) libdir="$2"; shift; shift ;;
|
|
||||||
-i* | --includedir) includedir="$2"; shift; shift ;;
|
|
||||||
-s* | --shared | --enable-shared) shared=1; shift ;;
|
|
||||||
-t | --static) shared=0; shift ;;
|
|
||||||
--zlib-compat) compat=1; shift ;;
|
|
||||||
--cover) cover=1; shift ;;
|
|
||||||
-3* | --32) build32=1; shift ;;
|
|
||||||
-6* | --64) build64=1; shift ;;
|
|
||||||
-a*=* | --archs=*) ARCHS=`echo $1 | sed 's/.*=//'`; shift ;;
|
|
||||||
--sysconfdir=*) echo "ignored option: --sysconfdir" | tee -a configure.log; shift ;;
|
|
||||||
--localstatedir=*) echo "ignored option: --localstatedir" | tee -a configure.log; shift ;;
|
|
||||||
-noopt | --without-optimizations) without_optimizations=1; shift;;
|
|
||||||
-oldstrat | --without-new-strategies) without_new_strategies=1; shift;;
|
|
||||||
*)
|
|
||||||
echo "unknown option: $1" | tee -a configure.log
|
|
||||||
echo "$0 --help for help" | tee -a configure.log
|
|
||||||
leave 1;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
# temporary file name
|
|
||||||
test=ztest$$
|
|
||||||
|
|
||||||
# put arguments in log, also put test file in log if used in arguments
|
|
||||||
show()
|
|
||||||
{
|
|
||||||
case "$*" in
|
|
||||||
*$test.c*)
|
|
||||||
echo === $test.c === >> configure.log
|
|
||||||
cat $test.c >> configure.log
|
|
||||||
echo === >> configure.log;;
|
|
||||||
esac
|
|
||||||
echo $* >> configure.log
|
|
||||||
}
|
|
||||||
|
|
||||||
# check for gcc vs. cc and set compile and link flags based on the system identified by uname
|
|
||||||
cat > $test.c <<EOF
|
|
||||||
extern int getchar();
|
|
||||||
int hello() {return getchar();}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
test -z "$CC" && echo Checking for ${CROSS_PREFIX}gcc... | tee -a configure.log
|
|
||||||
cc=${CC-${CROSS_PREFIX}gcc}
|
|
||||||
cflags=${CFLAGS-"-O3"}
|
|
||||||
case "$cc" in
|
|
||||||
*gcc*) gcc=1 ;;
|
|
||||||
*clang*) gcc=1 ;;
|
|
||||||
esac
|
|
||||||
case `$cc -v 2>&1` in
|
|
||||||
*gcc*) gcc=1 ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
show $cc -c $test.c
|
|
||||||
if test "$gcc" -eq 1 && ($cc -c $test.c) >> configure.log 2>&1; then
|
|
||||||
echo ... using gcc >> configure.log
|
|
||||||
CC="$cc"
|
|
||||||
# Re-check arch if gcc is a cross-compiler
|
|
||||||
GCC_ARCH=`$CC -dumpmachine | sed 's/-.*//g'`
|
|
||||||
case $GCC_ARCH in
|
|
||||||
i386 | i486 | i586 | i686)
|
|
||||||
# Honor user choice if gcc is multilib and 64-bit is requested
|
|
||||||
if test $build64 -eq 1; then
|
|
||||||
ARCH=x86_64
|
|
||||||
else
|
|
||||||
ARCH=$GCC_ARCH
|
|
||||||
fi ;;
|
|
||||||
# Honor user choice if gcc is multilib and 32-bit is requested
|
|
||||||
x86_64)
|
|
||||||
if test $build32 -ne 1; then
|
|
||||||
ARCH=$GCC_ARCH
|
|
||||||
fi ;;
|
|
||||||
esac
|
|
||||||
CFLAGS="${CFLAGS--O3} ${ARCHS} -Wall"
|
|
||||||
SFLAGS="${CFLAGS--O3} -fPIC"
|
|
||||||
LDFLAGS="${LDFLAGS} ${ARCHS}"
|
|
||||||
if test $build64 -eq 1; then
|
|
||||||
CFLAGS="${CFLAGS} -m64"
|
|
||||||
SFLAGS="${SFLAGS} -m64"
|
|
||||||
fi
|
|
||||||
if test "${ZLIBGCCWARN}" = "YES"; then
|
|
||||||
CFLAGS="${CFLAGS} -Wextra -pedantic"
|
|
||||||
fi
|
|
||||||
if test -z "$uname"; then
|
|
||||||
uname=`(uname -s || echo unknown) 2>/dev/null`
|
|
||||||
fi
|
|
||||||
case "$uname" in
|
|
||||||
Linux* | linux* | GNU | GNU/* | solaris*)
|
|
||||||
LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,${SRCDIR}/zlib.map"} ;;
|
|
||||||
*BSD | *bsd* | DragonFly)
|
|
||||||
LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,${SRCDIR}/zlib.map"}
|
|
||||||
LDCONFIG="ldconfig -m" ;;
|
|
||||||
CYGWIN* | Cygwin* | cygwin*)
|
|
||||||
ARFLAGS="rcs"
|
|
||||||
CFLAGS="${CFLAGS} -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
|
|
||||||
SFLAGS="${CFLAGS}"
|
|
||||||
shared_ext='.dll'
|
|
||||||
sharedlibdir='${bindir}'
|
|
||||||
SHAREDLIB=cygz$shared_ext
|
|
||||||
SHAREDLIBM=''
|
|
||||||
SHAREDLIBV=''
|
|
||||||
SHAREDTARGET=$SHAREDLIB
|
|
||||||
IMPORTLIB='libz.dll.a'
|
|
||||||
LDSHARED=${LDSHARED-"$cc -shared -Wl,--out-implib,${IMPORTLIB},--version-script,${SRCDIR}/zlib.map"}
|
|
||||||
LDSHAREDLIBC=""
|
|
||||||
DEFFILE='win32/zlib.def'
|
|
||||||
RC='windres'
|
|
||||||
RCFLAGS='--define GCC_WINDRES'
|
|
||||||
RCOBJS='zlibrc.o'
|
|
||||||
STRIP='strip'
|
|
||||||
EXE='.exe' ;;
|
|
||||||
MSYS* | msys*)
|
|
||||||
ARFLAGS="rcs"
|
|
||||||
SFLAGS="${CFLAGS}"
|
|
||||||
shared_ext='.dll'
|
|
||||||
sharedlibdir='${bindir}'
|
|
||||||
SHAREDLIB=msys-z$shared_ext
|
|
||||||
SHAREDLIBM=''
|
|
||||||
SHAREDLIBV=''
|
|
||||||
SHAREDTARGET=$SHAREDLIB
|
|
||||||
IMPORTLIB='libz.dll.a'
|
|
||||||
LDSHARED=${LDSHARED-"$cc -shared -Wl,--out-implib,${IMPORTLIB}"}
|
|
||||||
LDSHAREDLIBC=""
|
|
||||||
DEFFILE='win32/zlib.def'
|
|
||||||
RC='windres'
|
|
||||||
RCFLAGS='--define GCC_WINDRES'
|
|
||||||
RCOBJS='zlibrc.o'
|
|
||||||
STRIP='strip'
|
|
||||||
EXE='.exe' ;;
|
|
||||||
MINGW* | mingw*)
|
|
||||||
ARFLAGS="rcs"
|
|
||||||
CFLAGS="${CFLAGS} -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_POSIX_C_SOURCE=200809L -D_GNU_SOURCE=1"
|
|
||||||
SFLAGS="${CFLAGS}"
|
|
||||||
shared_ext='.dll'
|
|
||||||
sharedlibdir='${bindir}'
|
|
||||||
SHAREDLIB=libz-$VER1$shared_ext
|
|
||||||
SHAREDLIBM=''
|
|
||||||
SHAREDLIBV=''
|
|
||||||
SHAREDTARGET=$SHAREDLIB
|
|
||||||
IMPORTLIB='libz.dll.a'
|
|
||||||
LDSHARED=${LDSHARED-"$cc -shared -Wl,--out-implib=${IMPORTLIB} -Wl,--version-script=${SRCDIR}/zlib.map"}
|
|
||||||
LDSHAREDLIBC=""
|
|
||||||
DEFFILE='win32/zlib.def'
|
|
||||||
RC='windres'
|
|
||||||
RCFLAGS='--define GCC_WINDRES'
|
|
||||||
if [ "$CC" == "mingw32-gcc" ]; then
|
|
||||||
case $ARCH in
|
|
||||||
i386 | i486 | i586 | i686) RCFLAGS="${RCFLAGS} -F pe-i386";;
|
|
||||||
esac;
|
|
||||||
fi
|
|
||||||
RCOBJS='zlibrc.o'
|
|
||||||
STRIP='strip'
|
|
||||||
EXE='.exe' ;;
|
|
||||||
QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4
|
|
||||||
# (alain.bonnefoy@icbt.com)
|
|
||||||
LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"} ;;
|
|
||||||
HP-UX*)
|
|
||||||
LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"}
|
|
||||||
case `(uname -m || echo unknown) 2>/dev/null` in
|
|
||||||
ia64)
|
|
||||||
shared_ext='.so'
|
|
||||||
SHAREDLIB='libz.so' ;;
|
|
||||||
*)
|
|
||||||
shared_ext='.sl'
|
|
||||||
SHAREDLIB='libz.sl' ;;
|
|
||||||
esac ;;
|
|
||||||
Darwin* | darwin*)
|
|
||||||
shared_ext='.dylib'
|
|
||||||
SHAREDLIB=libz$shared_ext
|
|
||||||
SHAREDLIBV=libz.$VER$shared_ext
|
|
||||||
SHAREDLIBM=libz.$VER1$shared_ext
|
|
||||||
SHAREDTARGET=$SHAREDLIBV
|
|
||||||
LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER3"}
|
|
||||||
if libtool -V 2>&1 | grep Apple > /dev/null; then
|
|
||||||
AR="libtool"
|
|
||||||
else
|
|
||||||
AR="/usr/bin/libtool"
|
|
||||||
fi
|
|
||||||
ARFLAGS="-o" ;;
|
|
||||||
*) LDSHARED=${LDSHARED-"$cc -shared"} ;;
|
|
||||||
esac
|
|
||||||
else
|
|
||||||
# find system name and corresponding cc options
|
|
||||||
CC=${CC-cc}
|
|
||||||
gcc=0
|
|
||||||
echo ... using $CC >> configure.log
|
|
||||||
if test -z "$uname"; then
|
|
||||||
uname=`(uname -sr || echo unknown) 2>/dev/null`
|
|
||||||
fi
|
|
||||||
case "$uname" in
|
|
||||||
HP-UX*) SFLAGS=${CFLAGS-"-O +z"}
|
|
||||||
CFLAGS=${CFLAGS-"-O"}
|
|
||||||
# LDSHARED=${LDSHARED-"ld -b +vnocompatwarnings"}
|
|
||||||
LDSHARED=${LDSHARED-"ld -b"}
|
|
||||||
case `(uname -m || echo unknown) 2>/dev/null` in
|
|
||||||
ia64)
|
|
||||||
shared_ext='.so'
|
|
||||||
SHAREDLIB='libz.so' ;;
|
|
||||||
*)
|
|
||||||
shared_ext='.sl'
|
|
||||||
SHAREDLIB='libz.sl' ;;
|
|
||||||
esac ;;
|
|
||||||
AIX*) # Courtesy of dbakker@arrayasolutions.com
|
|
||||||
SFLAGS=${CFLAGS-"-O -qmaxmem=8192"}
|
|
||||||
CFLAGS=${CFLAGS-"-O -qmaxmem=8192"}
|
|
||||||
LDSHARED=${LDSHARED-"xlc -G"} ;;
|
|
||||||
# send working options for other systems to zlib@gzip.org
|
|
||||||
*) SFLAGS=${CFLAGS-"-O"}
|
|
||||||
CFLAGS=${CFLAGS-"-O"}
|
|
||||||
LDSHARED=${LDSHARED-"cc -shared"} ;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
|
|
||||||
# destination names for shared library if not defined above
|
|
||||||
SHAREDLIB=${SHAREDLIB-"libz$shared_ext"}
|
|
||||||
SHAREDLIBV=${SHAREDLIBV-"libz$shared_ext.$VER"}
|
|
||||||
SHAREDLIBM=${SHAREDLIBM-"libz$shared_ext.$VER1"}
|
|
||||||
SHAREDTARGET=${SHAREDTARGET-"libz$shared_ext.$VER"}
|
|
||||||
|
|
||||||
echo >> configure.log
|
|
||||||
|
|
||||||
# define functions for testing compiler and library characteristics and logging the results
|
|
||||||
|
|
||||||
cat > $test.c <<EOF
|
|
||||||
#error error
|
|
||||||
EOF
|
|
||||||
if ($CC -c $CFLAGS $test.c) 2>/dev/null; then
|
|
||||||
try()
|
|
||||||
{
|
|
||||||
show $*
|
|
||||||
test "`( $* ) 2>&1 | tee -a configure.log`" = ""
|
|
||||||
}
|
|
||||||
echo - using any output from compiler to indicate an error >> configure.log
|
|
||||||
else
|
|
||||||
try()
|
|
||||||
{
|
|
||||||
show $*
|
|
||||||
( $* ) >> configure.log 2>&1
|
|
||||||
ret=$?
|
|
||||||
if test $ret -ne 0; then
|
|
||||||
echo "(exit code "$ret")" >> configure.log
|
|
||||||
fi
|
|
||||||
return $ret
|
|
||||||
}
|
|
||||||
fi
|
|
||||||
|
|
||||||
tryboth()
|
|
||||||
{
|
|
||||||
show $*
|
|
||||||
got=`( $* ) 2>&1`
|
|
||||||
ret=$?
|
|
||||||
printf %s "$got" >> configure.log
|
|
||||||
if test $ret -ne 0; then
|
|
||||||
return $ret
|
|
||||||
fi
|
|
||||||
test "$got" = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
cat > $test.c << EOF
|
|
||||||
int foo() { return 0; }
|
|
||||||
EOF
|
|
||||||
echo "Checking for obsessive-compulsive compiler options..." >> configure.log
|
|
||||||
if try $CC -c $CFLAGS $test.c; then
|
|
||||||
:
|
|
||||||
else
|
|
||||||
echo "Compiler error reporting is too harsh for $0 (perhaps remove -Werror)." | tee -a configure.log
|
|
||||||
leave 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo >> configure.log
|
|
||||||
|
|
||||||
# see if shared library build supported
|
|
||||||
cat > $test.c <<EOF
|
|
||||||
extern int getchar();
|
|
||||||
int hello() {return getchar();}
|
|
||||||
EOF
|
|
||||||
if test $shared -eq 1; then
|
|
||||||
echo Checking for shared library support... | tee -a configure.log
|
|
||||||
# we must test in two steps (cc then ld), required at least on SunOS 4.x
|
|
||||||
if try $CC -w -c $SFLAGS $test.c &&
|
|
||||||
try $LDSHARED $SFLAGS -o $test$shared_ext $test.o; then
|
|
||||||
echo Building shared library $SHAREDTARGET with $CC. | tee -a configure.log
|
|
||||||
elif test -z "$old_cc" -a -z "$old_cflags"; then
|
|
||||||
echo No shared library support. | tee -a configure.log
|
|
||||||
shared=0;
|
|
||||||
else
|
|
||||||
echo 'No shared library support; try without defining CC and CFLAGS' | tee -a configure.log
|
|
||||||
shared=0;
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if test $shared -eq 0; then
|
|
||||||
LDSHARED="$CC"
|
|
||||||
ALL="static"
|
|
||||||
SHAREDLIB=""
|
|
||||||
SHAREDLIBV=""
|
|
||||||
SHAREDLIBM=""
|
|
||||||
SHAREDTARGET=""
|
|
||||||
INSTALLTARGETS=install-static
|
|
||||||
UNINSTALLTARGETS=uninstall-static
|
|
||||||
echo Building static library $STATICLIB version $VER with $CC. | tee -a configure.log
|
|
||||||
else
|
|
||||||
ALL="static shared"
|
|
||||||
TEST="${TEST} testshared"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo >> configure.log
|
|
||||||
|
|
||||||
# check for large file support, and if none, check for fseeko()
|
|
||||||
cat > $test.c <<EOF
|
|
||||||
#include <sys/types.h>
|
|
||||||
#ifdef __MSYS__
|
|
||||||
# define off64_t _off64_t
|
|
||||||
#endif
|
|
||||||
off64_t dummy = 0;
|
|
||||||
EOF
|
|
||||||
if try $CC -c $CFLAGS -D_LARGEFILE64_SOURCE=1 $test.c; then
|
|
||||||
CFLAGS="${CFLAGS} -D_LARGEFILE64_SOURCE=1"
|
|
||||||
SFLAGS="${SFLAGS} -D_LARGEFILE64_SOURCE=1"
|
|
||||||
ALL="${ALL} all64"
|
|
||||||
TEST="${TEST} test64"
|
|
||||||
echo "Checking for off64_t... Yes." | tee -a configure.log
|
|
||||||
echo "Checking for fseeko... Yes." | tee -a configure.log
|
|
||||||
else
|
|
||||||
echo "Checking for off64_t... No." | tee -a configure.log
|
|
||||||
echo >> configure.log
|
|
||||||
cat > $test.c <<EOF
|
|
||||||
#include <stdio.h>
|
|
||||||
int main(void) {
|
|
||||||
fseeko(NULL, 0, 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
if try $CC $CFLAGS -o $test $test.c; then
|
|
||||||
echo "Checking for fseeko... Yes." | tee -a configure.log
|
|
||||||
else
|
|
||||||
CFLAGS="${CFLAGS} -DNO_FSEEKO"
|
|
||||||
SFLAGS="${SFLAGS} -DNO_FSEEKO"
|
|
||||||
echo "Checking for fseeko... No." | tee -a configure.log
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo >> configure.log
|
|
||||||
|
|
||||||
# check for strerror() for use by gz* functions
|
|
||||||
cat > $test.c <<EOF
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
int main() { return strlen(strerror(errno)); }
|
|
||||||
EOF
|
|
||||||
if try $CC $CFLAGS -o $test $test.c; then
|
|
||||||
echo "Checking for strerror... Yes." | tee -a configure.log
|
|
||||||
else
|
|
||||||
CFLAGS="${CFLAGS} -DNO_STRERROR"
|
|
||||||
SFLAGS="${SFLAGS} -DNO_STRERROR"
|
|
||||||
echo "Checking for strerror... No." | tee -a configure.log
|
|
||||||
fi
|
|
||||||
|
|
||||||
# We need to remove zconf.h from source directory if building outside of it
|
|
||||||
if [ "$SRCDIR" != "$BUILDDIR" ]; then rm -f $SRCDIR/zconf.h; fi
|
|
||||||
|
|
||||||
# copy clean zconf.h for subsequent edits
|
|
||||||
cp -p $SRCDIR/zconf.h.in zconf.h
|
|
||||||
|
|
||||||
echo >> configure.log
|
|
||||||
|
|
||||||
# check for unistd.h and save result in zconf.h
|
|
||||||
cat > $test.c <<EOF
|
|
||||||
#include <unistd.h>
|
|
||||||
int main() { return 0; }
|
|
||||||
EOF
|
|
||||||
if try $CC -c $CFLAGS $test.c; then
|
|
||||||
sed < zconf.h "/^#ifdef HAVE_UNISTD_H.* may be/s/def HAVE_UNISTD_H\(.*\) may be/ 1\1 was/" > zconf.temp.h
|
|
||||||
mv zconf.temp.h zconf.h
|
|
||||||
echo "Checking for unistd.h... Yes." | tee -a configure.log
|
|
||||||
else
|
|
||||||
echo "Checking for unistd.h... No." | tee -a configure.log
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo >> configure.log
|
|
||||||
|
|
||||||
# check for stdarg.h and save result in zconf.h
|
|
||||||
cat > $test.c <<EOF
|
|
||||||
#include <stdarg.h>
|
|
||||||
int main() { return 0; }
|
|
||||||
EOF
|
|
||||||
if try $CC -c $CFLAGS $test.c; then
|
|
||||||
sed < zconf.h "/^#ifdef HAVE_STDARG_H.* may be/s/def HAVE_STDARG_H\(.*\) may be/ 1\1 was/" > zconf.temp.h
|
|
||||||
mv zconf.temp.h zconf.h
|
|
||||||
echo "Checking for stdarg.h... Yes." | tee -a configure.log
|
|
||||||
else
|
|
||||||
echo "Checking for stdarg.h... No." | tee -a configure.log
|
|
||||||
fi
|
|
||||||
|
|
||||||
# if --zlib-compat was requested
|
|
||||||
if test $compat -eq 1; then
|
|
||||||
CFLAGS="${CFLAGS} -DZLIB_COMPAT -DWITH_GZFILEOP"
|
|
||||||
SFLAGS="${SFLAGS} -DZLIB_COMPAT -DWITH_GZFILEOP"
|
|
||||||
OBJC="${OBJC} \$(OBJG)"
|
|
||||||
PIC_OBJC="${PIC_OBJC} \$(PIC_OBJG)"
|
|
||||||
case "$uname" in
|
|
||||||
CYGWIN* | Cygwin* | cygwin* | MSYS* | msys* | MINGW* | mingw*)
|
|
||||||
DEFFILE="win32/zlibcompat.def" ;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
|
|
||||||
# if code coverage testing was requested, use older gcc if defined, e.g. "gcc-4.2" on Mac OS X
|
|
||||||
if test $cover -eq 1; then
|
|
||||||
CFLAGS="${CFLAGS} -fprofile-arcs -ftest-coverage"
|
|
||||||
if test -n "$GCC_CLASSIC"; then
|
|
||||||
CC=$GCC_CLASSIC
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo >> configure.log
|
|
||||||
|
|
||||||
# Check for ANSI C compliant compiler
|
|
||||||
cat > $test.c <<EOF
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include "zconf.h"
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
#ifdef STDC
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
if try $CC -c $CFLAGS $test.c; then
|
|
||||||
echo "Checking for ANSI C compliant compiler... Yes." | tee -a configure.log
|
|
||||||
:
|
|
||||||
else
|
|
||||||
echo "Checking for ANSI C compliant compiler... No." | tee -a configure.log
|
|
||||||
echo "Error: ANSI C compatible compiler needed, cannot continue." | tee -a configure.log
|
|
||||||
leave 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# see if we can hide zlib internal symbols that are linked between separate source files using hidden
|
|
||||||
if test "$gcc" -eq 1; then
|
|
||||||
echo >> configure.log
|
|
||||||
cat > $test.c <<EOF
|
|
||||||
#define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
|
|
||||||
int ZLIB_INTERNAL foo;
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
if tryboth $CC -c $CFLAGS $test.c; then
|
|
||||||
CFLAGS="$CFLAGS -DHAVE_HIDDEN"
|
|
||||||
SFLAGS="$SFLAGS -DHAVE_HIDDEN"
|
|
||||||
echo >> configure.log
|
|
||||||
echo "Checking for attribute(visibility(hidden)) support... Yes." | tee -a configure.log
|
|
||||||
else
|
|
||||||
echo >> configure.log
|
|
||||||
echo "Checking for attribute(visibility(hidden)) support... No." | tee -a configure.log
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# see if we can hide zlib internal symbols that are linked between separate source files using internal
|
|
||||||
if test "$gcc" -eq 1; then
|
|
||||||
echo >> configure.log
|
|
||||||
cat > $test.c <<EOF
|
|
||||||
#define ZLIB_INTERNAL __attribute__((visibility ("internal")))
|
|
||||||
int ZLIB_INTERNAL foo;
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
if tryboth $CC -c $CFLAGS $test.c; then
|
|
||||||
CFLAGS="$CFLAGS -DHAVE_INTERNAL"
|
|
||||||
SFLAGS="$SFLAGS -DHAVE_INTERNAL"
|
|
||||||
echo >> configure.log
|
|
||||||
echo "Checking for attribute(visibility(internal)) support... Yes." | tee -a configure.log
|
|
||||||
else
|
|
||||||
echo >> configure.log
|
|
||||||
echo "Checking for attribute(visibility(internal)) support... No." | tee -a configure.log
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check for __builtin_ctzl() support in compiler
|
|
||||||
cat > $test.c << EOF
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
unsigned int zero = 0;
|
|
||||||
long test = __builtin_ctzl(zero);
|
|
||||||
(void)test;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
if try ${CC} ${CFLAGS} $test.c; then
|
|
||||||
echo "Checking for __builtin_ctzl ... Yes." | tee -a configure.log
|
|
||||||
CFLAGS="$CFLAGS -DHAVE_BUILTIN_CTZL"
|
|
||||||
SFLAGS="$SFLAGS -DHAVE_BUILTIN_CTZL"
|
|
||||||
else
|
|
||||||
echo "Checking for __builtin_ctzl ... No." | tee -a configure.log
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check for SSE2 intrinsics
|
|
||||||
cat > $test.c << EOF
|
|
||||||
#include <immintrin.h>
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
__m128i zero = _mm_setzero_si128();
|
|
||||||
(void)zero;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
if try ${CC} ${CFLAGS} -msse2 $test.c; then
|
|
||||||
echo "Checking for SSE2 intrinsics ... Yes." | tee -a configure.log
|
|
||||||
HAVE_SSE2_INTRIN=1
|
|
||||||
else
|
|
||||||
echo "Checking for SSE2 intrinsics ... No." | tee -a configure.log
|
|
||||||
HAVE_SSE2_INTRIN=0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check for PCLMULQDQ intrinsics
|
|
||||||
cat > $test.c << EOF
|
|
||||||
#include <immintrin.h>
|
|
||||||
#include <wmmintrin.h>
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
__m128i a = _mm_setzero_si128();
|
|
||||||
__m128i b = _mm_setzero_si128();
|
|
||||||
__m128i c = _mm_clmulepi64_si128(a, b, 0x10);
|
|
||||||
(void)c;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
if try ${CC} ${CFLAGS} -mpclmul $test.c; then
|
|
||||||
echo "Checking for PCLMULQDQ intrinsics ... Yes." | tee -a configure.log
|
|
||||||
HAVE_PCLMULQDQ_INTRIN=1
|
|
||||||
else
|
|
||||||
echo "Checking for PCLMULQDQ intrinsics ... No." | tee -a configure.log
|
|
||||||
HAVE_PCLMULQDQ_INTRIN=0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Enable deflate_medium at level 4-6
|
|
||||||
if test $without_new_strategies -eq 0; then
|
|
||||||
CFLAGS="${CFLAGS} -DMEDIUM_STRATEGY"
|
|
||||||
SFLAGS="${SFLAGS} -DMEDIUM_STRATEGY"
|
|
||||||
fi
|
|
||||||
|
|
||||||
ARCHDIR='arch/generic'
|
|
||||||
ARCH_STATIC_OBJS=''
|
|
||||||
ARCH_SHARED_OBJS=''
|
|
||||||
|
|
||||||
# Set ARCH specific FLAGS
|
|
||||||
case "${ARCH}" in
|
|
||||||
|
|
||||||
# x86 and x86_64 specific optimizations
|
|
||||||
i386 | i486 | i586 | i686 | x86_64)
|
|
||||||
ARCHDIR=arch/x86
|
|
||||||
|
|
||||||
case "${ARCH}" in
|
|
||||||
x86_64)
|
|
||||||
CFLAGS="${CFLAGS} -DX86_64 -DX86_NOCHECK_SSE2"
|
|
||||||
SFLAGS="${SFLAGS} -DX86_64 -DX86_NOCHECK_SSE2"
|
|
||||||
;;
|
|
||||||
i386 | i486 | i586 | i686)
|
|
||||||
CFLAGS="${CFLAGS} -DX86"
|
|
||||||
SFLAGS="${SFLAGS} -DX86"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
CFLAGS="${CFLAGS} -DUNALIGNED_OK -DUNROLL_LESS -DX86_CPUID"
|
|
||||||
SFLAGS="${SFLAGS} -DUNALIGNED_OK -DUNROLL_LESS -DX86_CPUID"
|
|
||||||
|
|
||||||
# Enable arch-specific optimizations?
|
|
||||||
if test $without_optimizations -eq 0; then
|
|
||||||
ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} x86.o"
|
|
||||||
ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} x86.lo"
|
|
||||||
|
|
||||||
if test ${HAVE_SSE2_INTRIN} -eq 1; then
|
|
||||||
CFLAGS="${CFLAGS} -DX86_SSE2_FILL_WINDOW"
|
|
||||||
SFLAGS="${SFLAGS} -DX86_SSE2_FILL_WINDOW"
|
|
||||||
ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} fill_window_sse.o"
|
|
||||||
ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} fill_window_sse.lo"
|
|
||||||
fi
|
|
||||||
|
|
||||||
CFLAGS="${CFLAGS} -DX86_SSE4_2_CRC_HASH"
|
|
||||||
SFLAGS="${SFLAGS} -DX86_SSE4_2_CRC_HASH"
|
|
||||||
ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} insert_string_sse.o"
|
|
||||||
ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} insert_string_sse.lo"
|
|
||||||
|
|
||||||
if test ${HAVE_PCLMULQDQ_INTRIN} -eq 1; then
|
|
||||||
CFLAGS="${CFLAGS} -DX86_PCLMULQDQ_CRC"
|
|
||||||
SFLAGS="${SFLAGS} -DX86_PCLMULQDQ_CRC"
|
|
||||||
ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} crc_folding.o"
|
|
||||||
ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} crc_folding.lo"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Enable deflate_quick at level 1?
|
|
||||||
# requires SSE2: code uses fill_window_sse
|
|
||||||
if test ${HAVE_SSE2_INTRIN} -eq 1 && test $without_new_strategies -eq 0; then
|
|
||||||
CFLAGS="${CFLAGS} -DX86_QUICK_STRATEGY"
|
|
||||||
SFLAGS="${SFLAGS} -DX86_QUICK_STRATEGY"
|
|
||||||
|
|
||||||
ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} deflate_quick.o"
|
|
||||||
ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} deflate_quick.lo"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
|
|
||||||
# ARM specific optimizations
|
|
||||||
armv3l | armv4b | armv4l | armv4tl | armv5tel | armv5tejl | armv6l | armv6hl | armv7l | armv7hl | armv7hnl)
|
|
||||||
ARCHDIR=arch/arm
|
|
||||||
|
|
||||||
case "${ARCH}" in
|
|
||||||
armv6l | armv6hl)
|
|
||||||
# Tests done on Raspberry pi (armv6hl) indicate that UNALIGNED_OK and UNROLL_LESS both
|
|
||||||
# provide performance improvements, totaling about 1.5% for the two.
|
|
||||||
CFLAGS="${CFLAGS} -DUNALIGNED_OK -DUNROLL_LESS"
|
|
||||||
SFLAGS="${SFLAGS} -DUNALIGNED_OK -DUNROLL_LESS"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
echo "ARCH: ${ARCH}"
|
|
||||||
echo "Using arch directory: ${ARCHDIR}"
|
|
||||||
|
|
||||||
# show the results in the log
|
|
||||||
echo >> configure.log
|
|
||||||
echo ALL = $ALL >> configure.log
|
|
||||||
echo AR = $AR >> configure.log
|
|
||||||
echo ARFLAGS = $ARFLAGS >> configure.log
|
|
||||||
echo CC = $CC >> configure.log
|
|
||||||
echo CFLAGS = $CFLAGS >> configure.log
|
|
||||||
echo EXE = $EXE >> configure.log
|
|
||||||
echo LDCONFIG = $LDCONFIG >> configure.log
|
|
||||||
echo LDFLAGS = $LDFLAGS >> configure.log
|
|
||||||
echo LDSHARED = $LDSHARED >> configure.log
|
|
||||||
echo LDSHAREDLIBC = $LDSHAREDLIBC >> configure.log
|
|
||||||
echo DEFFILE = $DEFFILE >> configure.log
|
|
||||||
echo RC = $RC >> configure.log
|
|
||||||
echo RCFLAGS = $RCFLAGS >> configure.log
|
|
||||||
echo RCOBJS = $RCOBJS >> configure.log
|
|
||||||
echo STRIP = $STRIP >> configure.log
|
|
||||||
echo OBJC = $OBJC >> configure.log
|
|
||||||
echo PIC_OBJC = $PIC_OBJC >> configure.log
|
|
||||||
echo RANLIB = $RANLIB >> configure.log
|
|
||||||
echo SFLAGS = $SFLAGS >> configure.log
|
|
||||||
echo SHAREDLIB = $SHAREDLIB >> configure.log
|
|
||||||
echo SHAREDLIBM = $SHAREDLIBM >> configure.log
|
|
||||||
echo SHAREDLIBV = $SHAREDLIBV >> configure.log
|
|
||||||
echo SHAREDTARGET = $SHAREDTARGET >> configure.log
|
|
||||||
echo IMPORTLIB = $IMPORTLIB >> configure.log
|
|
||||||
echo INSTALLTARGETS = $INSTALLTARGETS >> configure.log
|
|
||||||
echo UNINSTALLTARGETS = $UNINSTALLTARGETS >> configure.log
|
|
||||||
echo SRCDIR = $SRCDIR >> configure.log
|
|
||||||
echo BUILDDIR = $BUILDDIR >> configure.log
|
|
||||||
echo STATICLIB = $STATICLIB >> configure.log
|
|
||||||
echo TEST = $TEST >> configure.log
|
|
||||||
echo VER = $VER >> configure.log
|
|
||||||
echo exec_prefix = $exec_prefix >> configure.log
|
|
||||||
echo includedir = $includedir >> configure.log
|
|
||||||
echo bindir = $bindir >> configure.log
|
|
||||||
echo libdir = $libdir >> configure.log
|
|
||||||
echo mandir = $mandir >> configure.log
|
|
||||||
echo prefix = $prefix >> configure.log
|
|
||||||
echo sharedlibdir = $sharedlibdir >> configure.log
|
|
||||||
echo uname = $uname >> configure.log
|
|
||||||
echo ARCHDIR = ${ARCHDIR} >> configure.log
|
|
||||||
echo ARCH_STATIC_OBJS = ${ARCH_STATIC_OBJS} >> configure.log
|
|
||||||
echo ARCH_SHARED_OBJS = ${ARCH_SHARED_OBJS} >> configure.log
|
|
||||||
|
|
||||||
# update Makefile with the configure results
|
|
||||||
|
|
||||||
INCLUDES="-I$SRCDIR"
|
|
||||||
if [ "$SRCDIR" != "$BUILDDIR" ]; then INCLUDES="-I$BUILDDIR ${INCLUDES}"; fi
|
|
||||||
|
|
||||||
sed < $SRCDIR/Makefile.in "
|
|
||||||
/^CC *=/s#=.*#=$CC#
|
|
||||||
/^CFLAGS *=/s#=.*#=$CFLAGS#
|
|
||||||
/^SFLAGS *=/s#=.*#=$SFLAGS#
|
|
||||||
/^LDFLAGS *=/s#=.*#=$LDFLAGS#
|
|
||||||
/^LDSHARED *=/s#=.*#=$LDSHARED#
|
|
||||||
/^STATICLIB *=/s#=.*#=$STATICLIB#
|
|
||||||
/^SHAREDLIB *=/s#=.*#=$SHAREDLIB#
|
|
||||||
/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV#
|
|
||||||
/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM#
|
|
||||||
/^SHAREDTARGET *=/s#=.*#=$SHAREDTARGET#
|
|
||||||
/^IMPORTLIB *=/s#=.*#=$IMPORTLIB#
|
|
||||||
/^AR *=/s#=.*#=$AR#
|
|
||||||
/^ARFLAGS *=/s#=.*#=$ARFLAGS#
|
|
||||||
/^RANLIB *=/s#=.*#=$RANLIB#
|
|
||||||
/^LDCONFIG *=/s#=.*#=$LDCONFIG#
|
|
||||||
/^LDSHAREDLIBC *=/s#=.*#=$LDSHAREDLIBC#
|
|
||||||
/^DEFFILE *=/s#=.*#=$DEFFILE#
|
|
||||||
/^RC *=/s#=.*#=$RC#
|
|
||||||
/^RCFLAGS *=/s#=.*#=$RCFLAGS#
|
|
||||||
/^RCOBJS *=/s#=.*#=$RCOBJS#
|
|
||||||
/^STRIP *=/s#=.*#=$STRIP#
|
|
||||||
/^EXE *=/s#=.*#=$EXE#
|
|
||||||
/^prefix *=/s#=.*#= $prefix#
|
|
||||||
/^exec_prefix *=/s#=.*#= $exec_prefix#
|
|
||||||
/^bindir *=/s#=.*#= $bindir#
|
|
||||||
/^libdir *=/s#=.*#= $libdir#
|
|
||||||
/^sharedlibdir *=/s#=.*#= $sharedlibdir#
|
|
||||||
/^includedir *=/s#=.*#= $includedir#
|
|
||||||
/^mandir *=/s#=.*#= $mandir#
|
|
||||||
/^SRCDIR *=/s#=.*#=$SRCDIR#
|
|
||||||
/^INCLUDES *=/s#=.*#=$INCLUDES#
|
|
||||||
/^OBJC *=/s#=.*#= $OBJC#
|
|
||||||
/^PIC_OBJC *=/s#=.*#= $PIC_OBJC#
|
|
||||||
/^all: */s#:.*#: $ALL#
|
|
||||||
/^install-libs: */s#:.*#: $INSTALLTARGETS#
|
|
||||||
/^uninstall-libs: */s#:.*#: $UNINSTALLTARGETS#
|
|
||||||
/^ARCHDIR *=/s#=.*#=$ARCHDIR#
|
|
||||||
/^ARCH_STATIC_OBJS *=/s#=.*#=$ARCH_STATIC_OBJS#
|
|
||||||
/^ARCH_SHARED_OBJS *=/s#=.*#=$ARCH_SHARED_OBJS#
|
|
||||||
" > Makefile
|
|
||||||
|
|
||||||
# Generate Makefile in arch dir
|
|
||||||
mkdir -p $ARCHDIR
|
|
||||||
|
|
||||||
ARCHINCLUDES="-I$SRCDIR/$ARCHDIR -I$SRCDIR"
|
|
||||||
if [ "$SRCDIR" != "$BUILDDIR" ]; then ARCHINCLUDES="-I$BUILDDIR ${ARCHINCLUDES}"; fi
|
|
||||||
|
|
||||||
sed < $SRCDIR/$ARCHDIR/Makefile.in "
|
|
||||||
/^CC *=/s#=.*#=$CC#
|
|
||||||
/^CFLAGS *=/s#=.*#=$CFLAGS#
|
|
||||||
/^SFLAGS *=/s#=.*#=$SFLAGS#
|
|
||||||
/^INCLUDES *=/s#=.*#=$ARCHINCLUDES#
|
|
||||||
/^SRCDIR *=/s#=.*#=$SRCDIR/$ARCHDIR#
|
|
||||||
/^SRCTOP *=/s#=.*#=$SRCDIR#
|
|
||||||
" > $ARCHDIR/Makefile
|
|
||||||
|
|
||||||
# Generate Makefile in test dir
|
|
||||||
mkdir -p test
|
|
||||||
TESTINCLUDES="-I$SRCDIR"
|
|
||||||
if [ "$SRCDIR" != "$BUILDDIR" ]; then TESTINCLUDES="${TESTINCLUDES} -I$BUILDDIR"; fi
|
|
||||||
if test $compat -eq 1; then COMPATTESTS="compattests"; fi
|
|
||||||
sed < $SRCDIR/test/Makefile.in "
|
|
||||||
/^CC *=/s#=.*#=$CC#
|
|
||||||
/^CFLAGS *=/s#=.*#=$CFLAGS#
|
|
||||||
/^EXE *=/s#=.*#=$EXE#
|
|
||||||
/^oldtests: */s#:.*#: $TEST#
|
|
||||||
/^INCLUDES *=/s#=.*#=$TESTINCLUDES#
|
|
||||||
/^SRCDIR *=/s#=.*#=$SRCDIR/test#
|
|
||||||
/^SRCTOP *=/s#=.*#=$SRCDIR#
|
|
||||||
/^COMPATTESTS *=/s#=.*#=$COMPATTESTS#
|
|
||||||
" > test/Makefile
|
|
||||||
|
|
||||||
# create zlib.pc with the configure results
|
|
||||||
sed < $SRCDIR/zlib.pc.in "
|
|
||||||
/^CC *=/s#=.*#=$CC#
|
|
||||||
/^CFLAGS *=/s#=.*#=$CFLAGS#
|
|
||||||
/^LDSHARED *=/s#=.*#=$LDSHARED#
|
|
||||||
/^STATICLIB *=/s#=.*#=$STATICLIB#
|
|
||||||
/^SHAREDLIB *=/s#=.*#=$SHAREDLIB#
|
|
||||||
/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV#
|
|
||||||
/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM#
|
|
||||||
/^IMPORTLIB *=/s#=.*#=$IMPORTLIB#
|
|
||||||
/^AR *=/s#=.*#=$AR#
|
|
||||||
/^ARFLAGS *=/s#=.*#=$ARFLAGS#
|
|
||||||
/^RANLIB *=/s#=.*#=$RANLIB#
|
|
||||||
/^EXE *=/s#=.*#=$EXE#
|
|
||||||
/^prefix *=/s#=.*#=$prefix#
|
|
||||||
/^exec_prefix *=/s#=.*#=$exec_prefix#
|
|
||||||
/^bindir *=/s#=.*#=$bindir#
|
|
||||||
/^libdir *=/s#=.*#=$libdir#
|
|
||||||
/^sharedlibdir *=/s#=.*#=$sharedlibdir#
|
|
||||||
/^includedir *=/s#=.*#=$includedir#
|
|
||||||
/^mandir *=/s#=.*#=$mandir#
|
|
||||||
/^LDFLAGS *=/s#=.*#=$LDFLAGS#
|
|
||||||
" | sed -e "
|
|
||||||
s/\@VERSION\@/$VER/g;
|
|
||||||
" > zlib.pc
|
|
||||||
|
|
||||||
# done
|
|
||||||
leave 0
|
|
@ -1,458 +0,0 @@
|
|||||||
/* crc32.c -- compute the CRC-32 of a data stream
|
|
||||||
* Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*
|
|
||||||
* Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
|
|
||||||
* CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
|
|
||||||
* tables for updating the shift register in one step with three exclusive-ors
|
|
||||||
* instead of four steps with four exclusive-ors. This results in about a
|
|
||||||
* factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* @(#) $Id$ */
|
|
||||||
|
|
||||||
#ifdef __MINGW32__
|
|
||||||
# include <sys/param.h>
|
|
||||||
#elif defined(WIN32) || defined(_WIN32)
|
|
||||||
# define LITTLE_ENDIAN 1234
|
|
||||||
# define BIG_ENDIAN 4321
|
|
||||||
# if defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64)
|
|
||||||
# define BYTE_ORDER LITTLE_ENDIAN
|
|
||||||
# else
|
|
||||||
# error Unknown endianness!
|
|
||||||
# endif
|
|
||||||
#elif __APPLE__
|
|
||||||
# include <machine/endian.h>
|
|
||||||
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__)
|
|
||||||
# include <sys/endian.h>
|
|
||||||
#elif defined(__sun) || defined(sun)
|
|
||||||
# include <sys/byteorder.h>
|
|
||||||
# if !defined(LITTLE_ENDIAN)
|
|
||||||
# define LITTLE_ENDIAN 4321
|
|
||||||
# endif
|
|
||||||
# if !defined(BIG_ENDIAN)
|
|
||||||
# define BIG_ENDIAN 1234
|
|
||||||
# endif
|
|
||||||
# if !defined(BYTE_ORDER)
|
|
||||||
# if defined(_BIG_ENDIAN)
|
|
||||||
# define BYTE_ORDER BIG_ENDIAN
|
|
||||||
# else
|
|
||||||
# define BYTE_ORDER LITTLE_ENDIAN
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
# include <endian.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
|
|
||||||
protection on the static variables used to control the first-use generation
|
|
||||||
of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
|
|
||||||
first call get_crc_table() to initialize the tables before allowing more than
|
|
||||||
one thread to use crc32().
|
|
||||||
|
|
||||||
DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef MAKECRCH
|
|
||||||
# include <stdio.h>
|
|
||||||
# ifndef DYNAMIC_CRC_TABLE
|
|
||||||
# define DYNAMIC_CRC_TABLE
|
|
||||||
# endif /* !DYNAMIC_CRC_TABLE */
|
|
||||||
#endif /* MAKECRCH */
|
|
||||||
|
|
||||||
#include "deflate.h"
|
|
||||||
|
|
||||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
|
||||||
static uint32_t crc32_little(uint32_t, const unsigned char *, z_off64_t);
|
|
||||||
#elif BYTE_ORDER == BIG_ENDIAN
|
|
||||||
static uint32_t crc32_big(uint32_t, const unsigned char *, z_off64_t);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Local functions for crc concatenation */
|
|
||||||
static uint32_t gf2_matrix_times(uint32_t *mat, uint32_t vec);
|
|
||||||
static void gf2_matrix_square(uint32_t *square, uint32_t *mat);
|
|
||||||
static uint32_t crc32_combine_(uint32_t crc1, uint32_t crc2, z_off64_t len2);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef DYNAMIC_CRC_TABLE
|
|
||||||
static volatile int crc_table_empty = 1;
|
|
||||||
static uint32_t crc_table[8][256];
|
|
||||||
static void make_crc_table(void);
|
|
||||||
#ifdef MAKECRCH
|
|
||||||
static void write_table(FILE *, const uint32_t *);
|
|
||||||
#endif /* MAKECRCH */
|
|
||||||
/*
|
|
||||||
Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
|
|
||||||
x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
|
|
||||||
|
|
||||||
Polynomials over GF(2) are represented in binary, one bit per coefficient,
|
|
||||||
with the lowest powers in the most significant bit. Then adding polynomials
|
|
||||||
is just exclusive-or, and multiplying a polynomial by x is a right shift by
|
|
||||||
one. If we call the above polynomial p, and represent a byte as the
|
|
||||||
polynomial q, also with the lowest power in the most significant bit (so the
|
|
||||||
byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
|
|
||||||
where a mod b means the remainder after dividing a by b.
|
|
||||||
|
|
||||||
This calculation is done using the shift-register method of multiplying and
|
|
||||||
taking the remainder. The register is initialized to zero, and for each
|
|
||||||
incoming bit, x^32 is added mod p to the register if the bit is a one (where
|
|
||||||
x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
|
|
||||||
x (which is shifting right by one and adding x^32 mod p if the bit shifted
|
|
||||||
out is a one). We start with the highest power (least significant bit) of
|
|
||||||
q and repeat for all eight bits of q.
|
|
||||||
|
|
||||||
The first table is simply the CRC of all possible eight bit values. This is
|
|
||||||
all the information needed to generate CRCs on data a byte at a time for all
|
|
||||||
combinations of CRC register values and incoming bytes. The remaining tables
|
|
||||||
allow for word-at-a-time CRC calculation for both big-endian and little-
|
|
||||||
endian machines, where a word is four bytes.
|
|
||||||
*/
|
|
||||||
static void make_crc_table() {
|
|
||||||
uint32_t c;
|
|
||||||
int n, k;
|
|
||||||
uint32_t poly; /* polynomial exclusive-or pattern */
|
|
||||||
/* terms of polynomial defining this crc (except x^32): */
|
|
||||||
static volatile int first = 1; /* flag to limit concurrent making */
|
|
||||||
static const unsigned char p[] = {0, 1, 2, 4, 5, 7, 8, 10, 11, 12, 16, 22, 23, 26};
|
|
||||||
|
|
||||||
/* See if another task is already doing this (not thread-safe, but better
|
|
||||||
than nothing -- significantly reduces duration of vulnerability in
|
|
||||||
case the advice about DYNAMIC_CRC_TABLE is ignored) */
|
|
||||||
if (first) {
|
|
||||||
first = 0;
|
|
||||||
|
|
||||||
/* make exclusive-or pattern from polynomial (0xedb88320) */
|
|
||||||
poly = 0;
|
|
||||||
for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++)
|
|
||||||
poly |= (uint32_t)1 << (31 - p[n]);
|
|
||||||
|
|
||||||
/* generate a crc for every 8-bit value */
|
|
||||||
for (n = 0; n < 256; n++) {
|
|
||||||
c = (uint32_t)n;
|
|
||||||
for (k = 0; k < 8; k++)
|
|
||||||
c = c & 1 ? poly ^ (c >> 1) : c >> 1;
|
|
||||||
crc_table[0][n] = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* generate crc for each value followed by one, two, and three zeros,
|
|
||||||
and then the byte reversal of those as well as the first table */
|
|
||||||
for (n = 0; n < 256; n++) {
|
|
||||||
c = crc_table[0][n];
|
|
||||||
crc_table[4][n] = ZSWAP32(c);
|
|
||||||
for (k = 1; k < 4; k++) {
|
|
||||||
c = crc_table[0][c & 0xff] ^ (c >> 8);
|
|
||||||
crc_table[k][n] = c;
|
|
||||||
crc_table[k + 4][n] = ZSWAP32(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
crc_table_empty = 0;
|
|
||||||
} else { /* not first */
|
|
||||||
/* wait for the other guy to finish (not efficient, but rare) */
|
|
||||||
while (crc_table_empty)
|
|
||||||
{}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef MAKECRCH
|
|
||||||
/* write out CRC tables to crc32.h */
|
|
||||||
{
|
|
||||||
FILE *out;
|
|
||||||
|
|
||||||
out = fopen("crc32.h", "w");
|
|
||||||
if (out == NULL) return;
|
|
||||||
fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
|
|
||||||
fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
|
|
||||||
fprintf(out, "static const uint32_t ");
|
|
||||||
fprintf(out, "crc_table[8][256] =\n{\n {\n");
|
|
||||||
write_table(out, crc_table[0]);
|
|
||||||
for (k = 1; k < 8; k++) {
|
|
||||||
fprintf(out, " },\n {\n");
|
|
||||||
write_table(out, crc_table[k]);
|
|
||||||
}
|
|
||||||
fprintf(out, " }\n};\n");
|
|
||||||
fclose(out);
|
|
||||||
}
|
|
||||||
#endif /* MAKECRCH */
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef MAKECRCH
|
|
||||||
static void write_table(FILE *out, const uint32_t *table) {
|
|
||||||
int n;
|
|
||||||
|
|
||||||
for (n = 0; n < 256; n++)
|
|
||||||
fprintf(out, "%s0x%08lx%s", n % 5 ? "" : " ",
|
|
||||||
(uint32_t)(table[n]),
|
|
||||||
n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
|
|
||||||
}
|
|
||||||
#endif /* MAKECRCH */
|
|
||||||
|
|
||||||
#else /* !DYNAMIC_CRC_TABLE */
|
|
||||||
/* ========================================================================
|
|
||||||
* Tables of CRC-32s of all single-byte values, made by make_crc_table().
|
|
||||||
*/
|
|
||||||
#include "crc32.h"
|
|
||||||
#endif /* DYNAMIC_CRC_TABLE */
|
|
||||||
|
|
||||||
/* =========================================================================
|
|
||||||
* This function can be used by asm versions of crc32()
|
|
||||||
*/
|
|
||||||
const uint32_t * ZEXPORT get_crc_table(void) {
|
|
||||||
#ifdef DYNAMIC_CRC_TABLE
|
|
||||||
if (crc_table_empty)
|
|
||||||
make_crc_table();
|
|
||||||
#endif /* DYNAMIC_CRC_TABLE */
|
|
||||||
return (const uint32_t *)crc_table;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================================================================= */
|
|
||||||
#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
|
|
||||||
#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
|
|
||||||
#define DO4 DO1; DO1; DO1; DO1
|
|
||||||
|
|
||||||
/* ========================================================================= */
|
|
||||||
uint32_t ZEXPORT crc32(uint32_t crc, const unsigned char *buf, z_off64_t len) {
|
|
||||||
if (buf == Z_NULL) return 0;
|
|
||||||
|
|
||||||
#ifdef DYNAMIC_CRC_TABLE
|
|
||||||
if (crc_table_empty)
|
|
||||||
make_crc_table();
|
|
||||||
#endif /* DYNAMIC_CRC_TABLE */
|
|
||||||
|
|
||||||
if (sizeof(void *) == sizeof(ptrdiff_t)) {
|
|
||||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
|
||||||
return crc32_little(crc, buf, len);
|
|
||||||
#elif BYTE_ORDER == BIG_ENDIAN
|
|
||||||
return crc32_big(crc, buf, len);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
crc = crc ^ 0xffffffff;
|
|
||||||
|
|
||||||
#ifdef UNROLL_LESS
|
|
||||||
while (len >= 4) {
|
|
||||||
DO4;
|
|
||||||
len -= 4;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
while (len >= 8) {
|
|
||||||
DO8;
|
|
||||||
len -= 8;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (len) do {
|
|
||||||
DO1;
|
|
||||||
} while (--len);
|
|
||||||
return crc ^ 0xffffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ========================================================================= */
|
|
||||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
|
||||||
#define DOLIT4 c ^= *buf4++; \
|
|
||||||
c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
|
|
||||||
crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
|
|
||||||
#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
|
|
||||||
|
|
||||||
/* ========================================================================= */
|
|
||||||
static uint32_t crc32_little(uint32_t crc, const unsigned char *buf, z_off64_t len) {
|
|
||||||
register uint32_t c;
|
|
||||||
register const uint32_t *buf4;
|
|
||||||
|
|
||||||
c = crc;
|
|
||||||
c = ~c;
|
|
||||||
while (len && ((ptrdiff_t)buf & 3)) {
|
|
||||||
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf4 = (const uint32_t *)(const void *)buf;
|
|
||||||
|
|
||||||
#ifndef UNROLL_LESS
|
|
||||||
while (len >= 32) {
|
|
||||||
DOLIT32;
|
|
||||||
len -= 32;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while (len >= 4) {
|
|
||||||
DOLIT4;
|
|
||||||
len -= 4;
|
|
||||||
}
|
|
||||||
buf = (const unsigned char *)buf4;
|
|
||||||
|
|
||||||
if (len) do {
|
|
||||||
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
|
|
||||||
} while (--len);
|
|
||||||
c = ~c;
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
|
|
||||||
|
|
||||||
/* ========================================================================= */
|
|
||||||
#if BYTE_ORDER == BIG_ENDIAN
|
|
||||||
#define DOBIG4 c ^= *++buf4; \
|
|
||||||
c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
|
|
||||||
crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
|
|
||||||
#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
|
|
||||||
|
|
||||||
/* ========================================================================= */
|
|
||||||
static uint32_t crc32_big(uint32_t crc, const unsigned char *buf, z_off64_t len) {
|
|
||||||
register uint32_t c;
|
|
||||||
register const uint32_t *buf4;
|
|
||||||
|
|
||||||
c = ZSWAP32(crc);
|
|
||||||
c = ~c;
|
|
||||||
while (len && ((ptrdiff_t)buf & 3)) {
|
|
||||||
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf4 = (const uint32_t *)(const void *)buf;
|
|
||||||
buf4--;
|
|
||||||
|
|
||||||
#ifndef UNROLL_LESS
|
|
||||||
while (len >= 32) {
|
|
||||||
DOBIG32;
|
|
||||||
len -= 32;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while (len >= 4) {
|
|
||||||
DOBIG4;
|
|
||||||
len -= 4;
|
|
||||||
}
|
|
||||||
buf4++;
|
|
||||||
buf = (const unsigned char *)buf4;
|
|
||||||
|
|
||||||
if (len) do {
|
|
||||||
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
|
|
||||||
} while (--len);
|
|
||||||
c = ~c;
|
|
||||||
return ZSWAP32(c);
|
|
||||||
}
|
|
||||||
#endif /* BYTE_ORDER == BIG_ENDIAN */
|
|
||||||
|
|
||||||
|
|
||||||
#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
|
|
||||||
|
|
||||||
/* ========================================================================= */
|
|
||||||
static uint32_t gf2_matrix_times(uint32_t *mat, uint32_t vec) {
|
|
||||||
uint32_t sum;
|
|
||||||
|
|
||||||
sum = 0;
|
|
||||||
while (vec) {
|
|
||||||
if (vec & 1)
|
|
||||||
sum ^= *mat;
|
|
||||||
vec >>= 1;
|
|
||||||
mat++;
|
|
||||||
}
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================================================================= */
|
|
||||||
static void gf2_matrix_square(uint32_t *square, uint32_t *mat) {
|
|
||||||
int n;
|
|
||||||
|
|
||||||
for (n = 0; n < GF2_DIM; n++)
|
|
||||||
square[n] = gf2_matrix_times(mat, mat[n]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================================================================= */
|
|
||||||
static uint32_t crc32_combine_(uint32_t crc1, uint32_t crc2, z_off64_t len2) {
|
|
||||||
int n;
|
|
||||||
uint32_t row;
|
|
||||||
uint32_t even[GF2_DIM]; /* even-power-of-two zeros operator */
|
|
||||||
uint32_t odd[GF2_DIM]; /* odd-power-of-two zeros operator */
|
|
||||||
|
|
||||||
/* degenerate case (also disallow negative lengths) */
|
|
||||||
if (len2 <= 0)
|
|
||||||
return crc1;
|
|
||||||
|
|
||||||
/* put operator for one zero bit in odd */
|
|
||||||
odd[0] = 0xedb88320; /* CRC-32 polynomial */
|
|
||||||
row = 1;
|
|
||||||
for (n = 1; n < GF2_DIM; n++) {
|
|
||||||
odd[n] = row;
|
|
||||||
row <<= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* put operator for two zero bits in even */
|
|
||||||
gf2_matrix_square(even, odd);
|
|
||||||
|
|
||||||
/* put operator for four zero bits in odd */
|
|
||||||
gf2_matrix_square(odd, even);
|
|
||||||
|
|
||||||
/* apply len2 zeros to crc1 (first square will put the operator for one
|
|
||||||
zero byte, eight zero bits, in even) */
|
|
||||||
do {
|
|
||||||
/* apply zeros operator for this bit of len2 */
|
|
||||||
gf2_matrix_square(even, odd);
|
|
||||||
if (len2 & 1)
|
|
||||||
crc1 = gf2_matrix_times(even, crc1);
|
|
||||||
len2 >>= 1;
|
|
||||||
|
|
||||||
/* if no more bits set, then done */
|
|
||||||
if (len2 == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* another iteration of the loop with odd and even swapped */
|
|
||||||
gf2_matrix_square(odd, even);
|
|
||||||
if (len2 & 1)
|
|
||||||
crc1 = gf2_matrix_times(odd, crc1);
|
|
||||||
len2 >>= 1;
|
|
||||||
|
|
||||||
/* if no more bits set, then done */
|
|
||||||
} while (len2 != 0);
|
|
||||||
|
|
||||||
/* return combined crc */
|
|
||||||
crc1 ^= crc2;
|
|
||||||
return crc1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================================================================= */
|
|
||||||
uint32_t ZEXPORT crc32_combine(uint32_t crc1, uint32_t crc2, z_off_t len2) {
|
|
||||||
return crc32_combine_(crc1, crc2, len2);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t ZEXPORT crc32_combine64(uint32_t crc1, uint32_t crc2, z_off64_t len2) {
|
|
||||||
return crc32_combine_(crc1, crc2, len2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef X86_PCLMULQDQ_CRC
|
|
||||||
#include "arch/x86/x86.h"
|
|
||||||
extern void ZLIB_INTERNAL crc_fold_init(deflate_state *const s);
|
|
||||||
extern void ZLIB_INTERNAL crc_fold_copy(deflate_state *const s,
|
|
||||||
unsigned char *dst, const unsigned char *src, long len);
|
|
||||||
extern uint32_t ZLIB_INTERNAL crc_fold_512to32(deflate_state *const s);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ZLIB_INTERNAL void crc_reset(deflate_state *const s) {
|
|
||||||
#ifdef X86_PCLMULQDQ_CRC
|
|
||||||
if (x86_cpu_has_pclmulqdq) {
|
|
||||||
crc_fold_init(s);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
s->strm->adler = crc32(0L, Z_NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ZLIB_INTERNAL void crc_finalize(deflate_state *const s) {
|
|
||||||
#ifdef X86_PCLMULQDQ_CRC
|
|
||||||
if (x86_cpu_has_pclmulqdq)
|
|
||||||
s->strm->adler = crc_fold_512to32(s);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
ZLIB_INTERNAL void copy_with_crc(z_stream *strm, unsigned char *dst, long size) {
|
|
||||||
#ifdef X86_PCLMULQDQ_CRC
|
|
||||||
if (x86_cpu_has_pclmulqdq) {
|
|
||||||
crc_fold_copy(strm->state, dst, strm->next_in, size);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
memcpy(dst, strm->next_in, size);
|
|
||||||
strm->adler = crc32(strm->adler, dst, size);
|
|
||||||
}
|
|
||||||
|
|
@ -1,444 +0,0 @@
|
|||||||
#ifndef CRC32_H_
|
|
||||||
#define CRC32_H_
|
|
||||||
|
|
||||||
/* crc32.h -- tables for rapid CRC calculation
|
|
||||||
* Generated automatically by crc32.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
static const uint32_t crc_table[8][256] =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
|
|
||||||
0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
|
|
||||||
0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
|
|
||||||
0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
|
|
||||||
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
|
|
||||||
0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
|
||||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
|
|
||||||
0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
|
||||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
|
|
||||||
0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
|
|
||||||
0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
|
|
||||||
0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
|
||||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
|
|
||||||
0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
|
|
||||||
0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
|
|
||||||
0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
|
||||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
|
|
||||||
0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
|
||||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
|
|
||||||
0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
|
|
||||||
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
|
|
||||||
0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
|
|
||||||
0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
|
|
||||||
0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
|
||||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
|
|
||||||
0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
|
|
||||||
0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
|
|
||||||
0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
|
|
||||||
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
|
|
||||||
0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
|
||||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
|
|
||||||
0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
|
||||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
|
|
||||||
0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
|
|
||||||
0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
|
|
||||||
0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
|
||||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
|
|
||||||
0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
|
|
||||||
0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
|
|
||||||
0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
|
||||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
|
|
||||||
0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
|
||||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
|
|
||||||
0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
|
|
||||||
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
|
|
||||||
0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
|
|
||||||
0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
|
|
||||||
0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
|
||||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
|
|
||||||
0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
|
|
||||||
0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
|
|
||||||
0x2d02ef8d
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504,
|
|
||||||
0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49,
|
|
||||||
0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e,
|
|
||||||
0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192,
|
|
||||||
0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859,
|
|
||||||
0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c,
|
|
||||||
0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620,
|
|
||||||
0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265,
|
|
||||||
0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae,
|
|
||||||
0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2,
|
|
||||||
0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175,
|
|
||||||
0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38,
|
|
||||||
0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05,
|
|
||||||
0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40,
|
|
||||||
0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f,
|
|
||||||
0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca,
|
|
||||||
0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850,
|
|
||||||
0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d,
|
|
||||||
0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da,
|
|
||||||
0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864,
|
|
||||||
0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af,
|
|
||||||
0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea,
|
|
||||||
0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74,
|
|
||||||
0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31,
|
|
||||||
0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa,
|
|
||||||
0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a,
|
|
||||||
0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd,
|
|
||||||
0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180,
|
|
||||||
0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a,
|
|
||||||
0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f,
|
|
||||||
0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290,
|
|
||||||
0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5,
|
|
||||||
0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed,
|
|
||||||
0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0,
|
|
||||||
0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167,
|
|
||||||
0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b,
|
|
||||||
0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0,
|
|
||||||
0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5,
|
|
||||||
0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc,
|
|
||||||
0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189,
|
|
||||||
0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842,
|
|
||||||
0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e,
|
|
||||||
0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299,
|
|
||||||
0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4,
|
|
||||||
0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec,
|
|
||||||
0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9,
|
|
||||||
0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66,
|
|
||||||
0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23,
|
|
||||||
0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9,
|
|
||||||
0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4,
|
|
||||||
0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33,
|
|
||||||
0x9324fd72
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc,
|
|
||||||
0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f,
|
|
||||||
0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a,
|
|
||||||
0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29,
|
|
||||||
0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8,
|
|
||||||
0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023,
|
|
||||||
0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e,
|
|
||||||
0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065,
|
|
||||||
0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84,
|
|
||||||
0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7,
|
|
||||||
0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922,
|
|
||||||
0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71,
|
|
||||||
0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0,
|
|
||||||
0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b,
|
|
||||||
0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816,
|
|
||||||
0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd,
|
|
||||||
0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c,
|
|
||||||
0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f,
|
|
||||||
0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba,
|
|
||||||
0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579,
|
|
||||||
0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98,
|
|
||||||
0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873,
|
|
||||||
0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e,
|
|
||||||
0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5,
|
|
||||||
0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134,
|
|
||||||
0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7,
|
|
||||||
0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732,
|
|
||||||
0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461,
|
|
||||||
0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0,
|
|
||||||
0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b,
|
|
||||||
0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26,
|
|
||||||
0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd,
|
|
||||||
0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc,
|
|
||||||
0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef,
|
|
||||||
0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a,
|
|
||||||
0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049,
|
|
||||||
0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8,
|
|
||||||
0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43,
|
|
||||||
0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e,
|
|
||||||
0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5,
|
|
||||||
0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24,
|
|
||||||
0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07,
|
|
||||||
0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982,
|
|
||||||
0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1,
|
|
||||||
0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0,
|
|
||||||
0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b,
|
|
||||||
0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576,
|
|
||||||
0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d,
|
|
||||||
0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c,
|
|
||||||
0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f,
|
|
||||||
0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda,
|
|
||||||
0xbe9834ed
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757,
|
|
||||||
0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a,
|
|
||||||
0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733,
|
|
||||||
0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871,
|
|
||||||
0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70,
|
|
||||||
0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42,
|
|
||||||
0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5,
|
|
||||||
0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787,
|
|
||||||
0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086,
|
|
||||||
0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4,
|
|
||||||
0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d,
|
|
||||||
0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0,
|
|
||||||
0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d,
|
|
||||||
0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f,
|
|
||||||
0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859,
|
|
||||||
0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b,
|
|
||||||
0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5,
|
|
||||||
0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028,
|
|
||||||
0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891,
|
|
||||||
0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed,
|
|
||||||
0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec,
|
|
||||||
0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde,
|
|
||||||
0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817,
|
|
||||||
0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825,
|
|
||||||
0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24,
|
|
||||||
0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e,
|
|
||||||
0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7,
|
|
||||||
0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a,
|
|
||||||
0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4,
|
|
||||||
0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196,
|
|
||||||
0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0,
|
|
||||||
0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2,
|
|
||||||
0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52,
|
|
||||||
0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f,
|
|
||||||
0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36,
|
|
||||||
0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174,
|
|
||||||
0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675,
|
|
||||||
0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647,
|
|
||||||
0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d,
|
|
||||||
0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf,
|
|
||||||
0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be,
|
|
||||||
0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc,
|
|
||||||
0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645,
|
|
||||||
0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98,
|
|
||||||
0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138,
|
|
||||||
0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a,
|
|
||||||
0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c,
|
|
||||||
0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e,
|
|
||||||
0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0,
|
|
||||||
0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d,
|
|
||||||
0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194,
|
|
||||||
0xde0506f1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07,
|
|
||||||
0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79,
|
|
||||||
0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7,
|
|
||||||
0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84,
|
|
||||||
0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13,
|
|
||||||
0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663,
|
|
||||||
0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5,
|
|
||||||
0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5,
|
|
||||||
0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832,
|
|
||||||
0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51,
|
|
||||||
0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf,
|
|
||||||
0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1,
|
|
||||||
0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76,
|
|
||||||
0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606,
|
|
||||||
0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996,
|
|
||||||
0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6,
|
|
||||||
0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c,
|
|
||||||
0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712,
|
|
||||||
0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c,
|
|
||||||
0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4,
|
|
||||||
0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943,
|
|
||||||
0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333,
|
|
||||||
0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe,
|
|
||||||
0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce,
|
|
||||||
0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359,
|
|
||||||
0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a,
|
|
||||||
0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04,
|
|
||||||
0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a,
|
|
||||||
0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0,
|
|
||||||
0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580,
|
|
||||||
0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10,
|
|
||||||
0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060,
|
|
||||||
0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1,
|
|
||||||
0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf,
|
|
||||||
0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31,
|
|
||||||
0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852,
|
|
||||||
0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5,
|
|
||||||
0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5,
|
|
||||||
0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75,
|
|
||||||
0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005,
|
|
||||||
0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292,
|
|
||||||
0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1,
|
|
||||||
0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f,
|
|
||||||
0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111,
|
|
||||||
0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0,
|
|
||||||
0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0,
|
|
||||||
0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40,
|
|
||||||
0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530,
|
|
||||||
0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba,
|
|
||||||
0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4,
|
|
||||||
0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a,
|
|
||||||
0x8def022d
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x00000000, 0x41311b19, 0x82623632, 0xc3532d2b, 0x04c56c64,
|
|
||||||
0x45f4777d, 0x86a75a56, 0xc796414f, 0x088ad9c8, 0x49bbc2d1,
|
|
||||||
0x8ae8effa, 0xcbd9f4e3, 0x0c4fb5ac, 0x4d7eaeb5, 0x8e2d839e,
|
|
||||||
0xcf1c9887, 0x5112c24a, 0x1023d953, 0xd370f478, 0x9241ef61,
|
|
||||||
0x55d7ae2e, 0x14e6b537, 0xd7b5981c, 0x96848305, 0x59981b82,
|
|
||||||
0x18a9009b, 0xdbfa2db0, 0x9acb36a9, 0x5d5d77e6, 0x1c6c6cff,
|
|
||||||
0xdf3f41d4, 0x9e0e5acd, 0xa2248495, 0xe3159f8c, 0x2046b2a7,
|
|
||||||
0x6177a9be, 0xa6e1e8f1, 0xe7d0f3e8, 0x2483dec3, 0x65b2c5da,
|
|
||||||
0xaaae5d5d, 0xeb9f4644, 0x28cc6b6f, 0x69fd7076, 0xae6b3139,
|
|
||||||
0xef5a2a20, 0x2c09070b, 0x6d381c12, 0xf33646df, 0xb2075dc6,
|
|
||||||
0x715470ed, 0x30656bf4, 0xf7f32abb, 0xb6c231a2, 0x75911c89,
|
|
||||||
0x34a00790, 0xfbbc9f17, 0xba8d840e, 0x79dea925, 0x38efb23c,
|
|
||||||
0xff79f373, 0xbe48e86a, 0x7d1bc541, 0x3c2ade58, 0x054f79f0,
|
|
||||||
0x447e62e9, 0x872d4fc2, 0xc61c54db, 0x018a1594, 0x40bb0e8d,
|
|
||||||
0x83e823a6, 0xc2d938bf, 0x0dc5a038, 0x4cf4bb21, 0x8fa7960a,
|
|
||||||
0xce968d13, 0x0900cc5c, 0x4831d745, 0x8b62fa6e, 0xca53e177,
|
|
||||||
0x545dbbba, 0x156ca0a3, 0xd63f8d88, 0x970e9691, 0x5098d7de,
|
|
||||||
0x11a9ccc7, 0xd2fae1ec, 0x93cbfaf5, 0x5cd76272, 0x1de6796b,
|
|
||||||
0xdeb55440, 0x9f844f59, 0x58120e16, 0x1923150f, 0xda703824,
|
|
||||||
0x9b41233d, 0xa76bfd65, 0xe65ae67c, 0x2509cb57, 0x6438d04e,
|
|
||||||
0xa3ae9101, 0xe29f8a18, 0x21cca733, 0x60fdbc2a, 0xafe124ad,
|
|
||||||
0xeed03fb4, 0x2d83129f, 0x6cb20986, 0xab2448c9, 0xea1553d0,
|
|
||||||
0x29467efb, 0x687765e2, 0xf6793f2f, 0xb7482436, 0x741b091d,
|
|
||||||
0x352a1204, 0xf2bc534b, 0xb38d4852, 0x70de6579, 0x31ef7e60,
|
|
||||||
0xfef3e6e7, 0xbfc2fdfe, 0x7c91d0d5, 0x3da0cbcc, 0xfa368a83,
|
|
||||||
0xbb07919a, 0x7854bcb1, 0x3965a7a8, 0x4b98833b, 0x0aa99822,
|
|
||||||
0xc9fab509, 0x88cbae10, 0x4f5def5f, 0x0e6cf446, 0xcd3fd96d,
|
|
||||||
0x8c0ec274, 0x43125af3, 0x022341ea, 0xc1706cc1, 0x804177d8,
|
|
||||||
0x47d73697, 0x06e62d8e, 0xc5b500a5, 0x84841bbc, 0x1a8a4171,
|
|
||||||
0x5bbb5a68, 0x98e87743, 0xd9d96c5a, 0x1e4f2d15, 0x5f7e360c,
|
|
||||||
0x9c2d1b27, 0xdd1c003e, 0x120098b9, 0x533183a0, 0x9062ae8b,
|
|
||||||
0xd153b592, 0x16c5f4dd, 0x57f4efc4, 0x94a7c2ef, 0xd596d9f6,
|
|
||||||
0xe9bc07ae, 0xa88d1cb7, 0x6bde319c, 0x2aef2a85, 0xed796bca,
|
|
||||||
0xac4870d3, 0x6f1b5df8, 0x2e2a46e1, 0xe136de66, 0xa007c57f,
|
|
||||||
0x6354e854, 0x2265f34d, 0xe5f3b202, 0xa4c2a91b, 0x67918430,
|
|
||||||
0x26a09f29, 0xb8aec5e4, 0xf99fdefd, 0x3accf3d6, 0x7bfde8cf,
|
|
||||||
0xbc6ba980, 0xfd5ab299, 0x3e099fb2, 0x7f3884ab, 0xb0241c2c,
|
|
||||||
0xf1150735, 0x32462a1e, 0x73773107, 0xb4e17048, 0xf5d06b51,
|
|
||||||
0x3683467a, 0x77b25d63, 0x4ed7facb, 0x0fe6e1d2, 0xccb5ccf9,
|
|
||||||
0x8d84d7e0, 0x4a1296af, 0x0b238db6, 0xc870a09d, 0x8941bb84,
|
|
||||||
0x465d2303, 0x076c381a, 0xc43f1531, 0x850e0e28, 0x42984f67,
|
|
||||||
0x03a9547e, 0xc0fa7955, 0x81cb624c, 0x1fc53881, 0x5ef42398,
|
|
||||||
0x9da70eb3, 0xdc9615aa, 0x1b0054e5, 0x5a314ffc, 0x996262d7,
|
|
||||||
0xd85379ce, 0x174fe149, 0x567efa50, 0x952dd77b, 0xd41ccc62,
|
|
||||||
0x138a8d2d, 0x52bb9634, 0x91e8bb1f, 0xd0d9a006, 0xecf37e5e,
|
|
||||||
0xadc26547, 0x6e91486c, 0x2fa05375, 0xe836123a, 0xa9070923,
|
|
||||||
0x6a542408, 0x2b653f11, 0xe479a796, 0xa548bc8f, 0x661b91a4,
|
|
||||||
0x272a8abd, 0xe0bccbf2, 0xa18dd0eb, 0x62defdc0, 0x23efe6d9,
|
|
||||||
0xbde1bc14, 0xfcd0a70d, 0x3f838a26, 0x7eb2913f, 0xb924d070,
|
|
||||||
0xf815cb69, 0x3b46e642, 0x7a77fd5b, 0xb56b65dc, 0xf45a7ec5,
|
|
||||||
0x370953ee, 0x763848f7, 0xb1ae09b8, 0xf09f12a1, 0x33cc3f8a,
|
|
||||||
0x72fd2493
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x00000000, 0x376ac201, 0x6ed48403, 0x59be4602, 0xdca80907,
|
|
||||||
0xebc2cb06, 0xb27c8d04, 0x85164f05, 0xb851130e, 0x8f3bd10f,
|
|
||||||
0xd685970d, 0xe1ef550c, 0x64f91a09, 0x5393d808, 0x0a2d9e0a,
|
|
||||||
0x3d475c0b, 0x70a3261c, 0x47c9e41d, 0x1e77a21f, 0x291d601e,
|
|
||||||
0xac0b2f1b, 0x9b61ed1a, 0xc2dfab18, 0xf5b56919, 0xc8f23512,
|
|
||||||
0xff98f713, 0xa626b111, 0x914c7310, 0x145a3c15, 0x2330fe14,
|
|
||||||
0x7a8eb816, 0x4de47a17, 0xe0464d38, 0xd72c8f39, 0x8e92c93b,
|
|
||||||
0xb9f80b3a, 0x3cee443f, 0x0b84863e, 0x523ac03c, 0x6550023d,
|
|
||||||
0x58175e36, 0x6f7d9c37, 0x36c3da35, 0x01a91834, 0x84bf5731,
|
|
||||||
0xb3d59530, 0xea6bd332, 0xdd011133, 0x90e56b24, 0xa78fa925,
|
|
||||||
0xfe31ef27, 0xc95b2d26, 0x4c4d6223, 0x7b27a022, 0x2299e620,
|
|
||||||
0x15f32421, 0x28b4782a, 0x1fdeba2b, 0x4660fc29, 0x710a3e28,
|
|
||||||
0xf41c712d, 0xc376b32c, 0x9ac8f52e, 0xada2372f, 0xc08d9a70,
|
|
||||||
0xf7e75871, 0xae591e73, 0x9933dc72, 0x1c259377, 0x2b4f5176,
|
|
||||||
0x72f11774, 0x459bd575, 0x78dc897e, 0x4fb64b7f, 0x16080d7d,
|
|
||||||
0x2162cf7c, 0xa4748079, 0x931e4278, 0xcaa0047a, 0xfdcac67b,
|
|
||||||
0xb02ebc6c, 0x87447e6d, 0xdefa386f, 0xe990fa6e, 0x6c86b56b,
|
|
||||||
0x5bec776a, 0x02523168, 0x3538f369, 0x087faf62, 0x3f156d63,
|
|
||||||
0x66ab2b61, 0x51c1e960, 0xd4d7a665, 0xe3bd6464, 0xba032266,
|
|
||||||
0x8d69e067, 0x20cbd748, 0x17a11549, 0x4e1f534b, 0x7975914a,
|
|
||||||
0xfc63de4f, 0xcb091c4e, 0x92b75a4c, 0xa5dd984d, 0x989ac446,
|
|
||||||
0xaff00647, 0xf64e4045, 0xc1248244, 0x4432cd41, 0x73580f40,
|
|
||||||
0x2ae64942, 0x1d8c8b43, 0x5068f154, 0x67023355, 0x3ebc7557,
|
|
||||||
0x09d6b756, 0x8cc0f853, 0xbbaa3a52, 0xe2147c50, 0xd57ebe51,
|
|
||||||
0xe839e25a, 0xdf53205b, 0x86ed6659, 0xb187a458, 0x3491eb5d,
|
|
||||||
0x03fb295c, 0x5a456f5e, 0x6d2fad5f, 0x801b35e1, 0xb771f7e0,
|
|
||||||
0xeecfb1e2, 0xd9a573e3, 0x5cb33ce6, 0x6bd9fee7, 0x3267b8e5,
|
|
||||||
0x050d7ae4, 0x384a26ef, 0x0f20e4ee, 0x569ea2ec, 0x61f460ed,
|
|
||||||
0xe4e22fe8, 0xd388ede9, 0x8a36abeb, 0xbd5c69ea, 0xf0b813fd,
|
|
||||||
0xc7d2d1fc, 0x9e6c97fe, 0xa90655ff, 0x2c101afa, 0x1b7ad8fb,
|
|
||||||
0x42c49ef9, 0x75ae5cf8, 0x48e900f3, 0x7f83c2f2, 0x263d84f0,
|
|
||||||
0x115746f1, 0x944109f4, 0xa32bcbf5, 0xfa958df7, 0xcdff4ff6,
|
|
||||||
0x605d78d9, 0x5737bad8, 0x0e89fcda, 0x39e33edb, 0xbcf571de,
|
|
||||||
0x8b9fb3df, 0xd221f5dd, 0xe54b37dc, 0xd80c6bd7, 0xef66a9d6,
|
|
||||||
0xb6d8efd4, 0x81b22dd5, 0x04a462d0, 0x33cea0d1, 0x6a70e6d3,
|
|
||||||
0x5d1a24d2, 0x10fe5ec5, 0x27949cc4, 0x7e2adac6, 0x494018c7,
|
|
||||||
0xcc5657c2, 0xfb3c95c3, 0xa282d3c1, 0x95e811c0, 0xa8af4dcb,
|
|
||||||
0x9fc58fca, 0xc67bc9c8, 0xf1110bc9, 0x740744cc, 0x436d86cd,
|
|
||||||
0x1ad3c0cf, 0x2db902ce, 0x4096af91, 0x77fc6d90, 0x2e422b92,
|
|
||||||
0x1928e993, 0x9c3ea696, 0xab546497, 0xf2ea2295, 0xc580e094,
|
|
||||||
0xf8c7bc9f, 0xcfad7e9e, 0x9613389c, 0xa179fa9d, 0x246fb598,
|
|
||||||
0x13057799, 0x4abb319b, 0x7dd1f39a, 0x3035898d, 0x075f4b8c,
|
|
||||||
0x5ee10d8e, 0x698bcf8f, 0xec9d808a, 0xdbf7428b, 0x82490489,
|
|
||||||
0xb523c688, 0x88649a83, 0xbf0e5882, 0xe6b01e80, 0xd1dadc81,
|
|
||||||
0x54cc9384, 0x63a65185, 0x3a181787, 0x0d72d586, 0xa0d0e2a9,
|
|
||||||
0x97ba20a8, 0xce0466aa, 0xf96ea4ab, 0x7c78ebae, 0x4b1229af,
|
|
||||||
0x12ac6fad, 0x25c6adac, 0x1881f1a7, 0x2feb33a6, 0x765575a4,
|
|
||||||
0x413fb7a5, 0xc429f8a0, 0xf3433aa1, 0xaafd7ca3, 0x9d97bea2,
|
|
||||||
0xd073c4b5, 0xe71906b4, 0xbea740b6, 0x89cd82b7, 0x0cdbcdb2,
|
|
||||||
0x3bb10fb3, 0x620f49b1, 0x55658bb0, 0x6822d7bb, 0x5f4815ba,
|
|
||||||
0x06f653b8, 0x319c91b9, 0xb48adebc, 0x83e01cbd, 0xda5e5abf,
|
|
||||||
0xed3498be
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x00000000, 0x6567bcb8, 0x8bc809aa, 0xeeafb512, 0x5797628f,
|
|
||||||
0x32f0de37, 0xdc5f6b25, 0xb938d79d, 0xef28b4c5, 0x8a4f087d,
|
|
||||||
0x64e0bd6f, 0x018701d7, 0xb8bfd64a, 0xddd86af2, 0x3377dfe0,
|
|
||||||
0x56106358, 0x9f571950, 0xfa30a5e8, 0x149f10fa, 0x71f8ac42,
|
|
||||||
0xc8c07bdf, 0xada7c767, 0x43087275, 0x266fcecd, 0x707fad95,
|
|
||||||
0x1518112d, 0xfbb7a43f, 0x9ed01887, 0x27e8cf1a, 0x428f73a2,
|
|
||||||
0xac20c6b0, 0xc9477a08, 0x3eaf32a0, 0x5bc88e18, 0xb5673b0a,
|
|
||||||
0xd00087b2, 0x6938502f, 0x0c5fec97, 0xe2f05985, 0x8797e53d,
|
|
||||||
0xd1878665, 0xb4e03add, 0x5a4f8fcf, 0x3f283377, 0x8610e4ea,
|
|
||||||
0xe3775852, 0x0dd8ed40, 0x68bf51f8, 0xa1f82bf0, 0xc49f9748,
|
|
||||||
0x2a30225a, 0x4f579ee2, 0xf66f497f, 0x9308f5c7, 0x7da740d5,
|
|
||||||
0x18c0fc6d, 0x4ed09f35, 0x2bb7238d, 0xc518969f, 0xa07f2a27,
|
|
||||||
0x1947fdba, 0x7c204102, 0x928ff410, 0xf7e848a8, 0x3d58149b,
|
|
||||||
0x583fa823, 0xb6901d31, 0xd3f7a189, 0x6acf7614, 0x0fa8caac,
|
|
||||||
0xe1077fbe, 0x8460c306, 0xd270a05e, 0xb7171ce6, 0x59b8a9f4,
|
|
||||||
0x3cdf154c, 0x85e7c2d1, 0xe0807e69, 0x0e2fcb7b, 0x6b4877c3,
|
|
||||||
0xa20f0dcb, 0xc768b173, 0x29c70461, 0x4ca0b8d9, 0xf5986f44,
|
|
||||||
0x90ffd3fc, 0x7e5066ee, 0x1b37da56, 0x4d27b90e, 0x284005b6,
|
|
||||||
0xc6efb0a4, 0xa3880c1c, 0x1ab0db81, 0x7fd76739, 0x9178d22b,
|
|
||||||
0xf41f6e93, 0x03f7263b, 0x66909a83, 0x883f2f91, 0xed589329,
|
|
||||||
0x546044b4, 0x3107f80c, 0xdfa84d1e, 0xbacff1a6, 0xecdf92fe,
|
|
||||||
0x89b82e46, 0x67179b54, 0x027027ec, 0xbb48f071, 0xde2f4cc9,
|
|
||||||
0x3080f9db, 0x55e74563, 0x9ca03f6b, 0xf9c783d3, 0x176836c1,
|
|
||||||
0x720f8a79, 0xcb375de4, 0xae50e15c, 0x40ff544e, 0x2598e8f6,
|
|
||||||
0x73888bae, 0x16ef3716, 0xf8408204, 0x9d273ebc, 0x241fe921,
|
|
||||||
0x41785599, 0xafd7e08b, 0xcab05c33, 0x3bb659ed, 0x5ed1e555,
|
|
||||||
0xb07e5047, 0xd519ecff, 0x6c213b62, 0x094687da, 0xe7e932c8,
|
|
||||||
0x828e8e70, 0xd49eed28, 0xb1f95190, 0x5f56e482, 0x3a31583a,
|
|
||||||
0x83098fa7, 0xe66e331f, 0x08c1860d, 0x6da63ab5, 0xa4e140bd,
|
|
||||||
0xc186fc05, 0x2f294917, 0x4a4ef5af, 0xf3762232, 0x96119e8a,
|
|
||||||
0x78be2b98, 0x1dd99720, 0x4bc9f478, 0x2eae48c0, 0xc001fdd2,
|
|
||||||
0xa566416a, 0x1c5e96f7, 0x79392a4f, 0x97969f5d, 0xf2f123e5,
|
|
||||||
0x05196b4d, 0x607ed7f5, 0x8ed162e7, 0xebb6de5f, 0x528e09c2,
|
|
||||||
0x37e9b57a, 0xd9460068, 0xbc21bcd0, 0xea31df88, 0x8f566330,
|
|
||||||
0x61f9d622, 0x049e6a9a, 0xbda6bd07, 0xd8c101bf, 0x366eb4ad,
|
|
||||||
0x53090815, 0x9a4e721d, 0xff29cea5, 0x11867bb7, 0x74e1c70f,
|
|
||||||
0xcdd91092, 0xa8beac2a, 0x46111938, 0x2376a580, 0x7566c6d8,
|
|
||||||
0x10017a60, 0xfeaecf72, 0x9bc973ca, 0x22f1a457, 0x479618ef,
|
|
||||||
0xa939adfd, 0xcc5e1145, 0x06ee4d76, 0x6389f1ce, 0x8d2644dc,
|
|
||||||
0xe841f864, 0x51792ff9, 0x341e9341, 0xdab12653, 0xbfd69aeb,
|
|
||||||
0xe9c6f9b3, 0x8ca1450b, 0x620ef019, 0x07694ca1, 0xbe519b3c,
|
|
||||||
0xdb362784, 0x35999296, 0x50fe2e2e, 0x99b95426, 0xfcdee89e,
|
|
||||||
0x12715d8c, 0x7716e134, 0xce2e36a9, 0xab498a11, 0x45e63f03,
|
|
||||||
0x208183bb, 0x7691e0e3, 0x13f65c5b, 0xfd59e949, 0x983e55f1,
|
|
||||||
0x2106826c, 0x44613ed4, 0xaace8bc6, 0xcfa9377e, 0x38417fd6,
|
|
||||||
0x5d26c36e, 0xb389767c, 0xd6eecac4, 0x6fd61d59, 0x0ab1a1e1,
|
|
||||||
0xe41e14f3, 0x8179a84b, 0xd769cb13, 0xb20e77ab, 0x5ca1c2b9,
|
|
||||||
0x39c67e01, 0x80fea99c, 0xe5991524, 0x0b36a036, 0x6e511c8e,
|
|
||||||
0xa7166686, 0xc271da3e, 0x2cde6f2c, 0x49b9d394, 0xf0810409,
|
|
||||||
0x95e6b8b1, 0x7b490da3, 0x1e2eb11b, 0x483ed243, 0x2d596efb,
|
|
||||||
0xc3f6dbe9, 0xa6916751, 0x1fa9b0cc, 0x7ace0c74, 0x9461b966,
|
|
||||||
0xf10605de
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* CRC32_H_ */
|
|
File diff suppressed because it is too large
Load Diff
@ -1,459 +0,0 @@
|
|||||||
#ifndef DEFLATE_H_
|
|
||||||
#define DEFLATE_H_
|
|
||||||
/* deflate.h -- internal compression state
|
|
||||||
* Copyright (C) 1995-2012 Jean-loup Gailly
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* WARNING: this file should *not* be used by applications. It is
|
|
||||||
part of the implementation of the compression library and is
|
|
||||||
subject to change. Applications should only use zlib.h.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* @(#) $Id$ */
|
|
||||||
|
|
||||||
#include "zutil.h"
|
|
||||||
|
|
||||||
/* define NO_GZIP when compiling if you want to disable gzip header and
|
|
||||||
trailer creation by deflate(). NO_GZIP would be used to avoid linking in
|
|
||||||
the crc code when it is not needed. For shared libraries, gzip encoding
|
|
||||||
should be left enabled. */
|
|
||||||
#ifndef NO_GZIP
|
|
||||||
# define GZIP
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define NIL 0
|
|
||||||
/* Tail of hash chains */
|
|
||||||
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Internal compression state.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define LENGTH_CODES 29
|
|
||||||
/* number of length codes, not counting the special END_BLOCK code */
|
|
||||||
|
|
||||||
#define LITERALS 256
|
|
||||||
/* number of literal bytes 0..255 */
|
|
||||||
|
|
||||||
#define L_CODES (LITERALS+1+LENGTH_CODES)
|
|
||||||
/* number of Literal or Length codes, including the END_BLOCK code */
|
|
||||||
|
|
||||||
#define D_CODES 30
|
|
||||||
/* number of distance codes */
|
|
||||||
|
|
||||||
#define BL_CODES 19
|
|
||||||
/* number of codes used to transfer the bit lengths */
|
|
||||||
|
|
||||||
#define HEAP_SIZE (2*L_CODES+1)
|
|
||||||
/* maximum heap size */
|
|
||||||
|
|
||||||
#define MAX_BITS 15
|
|
||||||
/* All codes must not exceed MAX_BITS bits */
|
|
||||||
|
|
||||||
#define Buf_size 16
|
|
||||||
/* size of bit buffer in bi_buf */
|
|
||||||
|
|
||||||
#define END_BLOCK 256
|
|
||||||
/* end of block literal code */
|
|
||||||
|
|
||||||
#define INIT_STATE 42
|
|
||||||
#define EXTRA_STATE 69
|
|
||||||
#define NAME_STATE 73
|
|
||||||
#define COMMENT_STATE 91
|
|
||||||
#define HCRC_STATE 103
|
|
||||||
#define BUSY_STATE 113
|
|
||||||
#define FINISH_STATE 666
|
|
||||||
/* Stream status */
|
|
||||||
|
|
||||||
|
|
||||||
/* Data structure describing a single value and its code string. */
|
|
||||||
typedef struct ct_data_s {
|
|
||||||
union {
|
|
||||||
uint16_t freq; /* frequency count */
|
|
||||||
uint16_t code; /* bit string */
|
|
||||||
} fc;
|
|
||||||
union {
|
|
||||||
uint16_t dad; /* father node in Huffman tree */
|
|
||||||
uint16_t len; /* length of bit string */
|
|
||||||
} dl;
|
|
||||||
} ct_data;
|
|
||||||
|
|
||||||
#define Freq fc.freq
|
|
||||||
#define Code fc.code
|
|
||||||
#define Dad dl.dad
|
|
||||||
#define Len dl.len
|
|
||||||
|
|
||||||
typedef struct static_tree_desc_s static_tree_desc;
|
|
||||||
|
|
||||||
typedef struct tree_desc_s {
|
|
||||||
ct_data *dyn_tree; /* the dynamic tree */
|
|
||||||
int max_code; /* largest code with non zero frequency */
|
|
||||||
const static_tree_desc *stat_desc; /* the corresponding static tree */
|
|
||||||
} tree_desc;
|
|
||||||
|
|
||||||
typedef uint16_t Pos;
|
|
||||||
typedef unsigned IPos;
|
|
||||||
|
|
||||||
/* A Pos is an index in the character window. We use short instead of int to
|
|
||||||
* save space in the various tables. IPos is used only for parameter passing.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct internal_state {
|
|
||||||
z_stream *strm; /* pointer back to this zlib stream */
|
|
||||||
int status; /* as the name implies */
|
|
||||||
unsigned char *pending_buf; /* output still pending */
|
|
||||||
unsigned long pending_buf_size; /* size of pending_buf */
|
|
||||||
unsigned char *pending_out; /* next pending byte to output to the stream */
|
|
||||||
unsigned int pending; /* nb of bytes in the pending buffer */
|
|
||||||
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
|
|
||||||
gz_headerp gzhead; /* gzip header information to write */
|
|
||||||
unsigned int gzindex; /* where in extra, name, or comment */
|
|
||||||
unsigned char method; /* can only be DEFLATED */
|
|
||||||
int last_flush; /* value of flush param for previous deflate call */
|
|
||||||
|
|
||||||
#ifdef X86_PCLMULQDQ_CRC
|
|
||||||
unsigned ALIGNED_(16) crc0[4 * 5];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* used by deflate.c: */
|
|
||||||
|
|
||||||
unsigned int w_size; /* LZ77 window size (32K by default) */
|
|
||||||
unsigned int w_bits; /* log2(w_size) (8..16) */
|
|
||||||
unsigned int w_mask; /* w_size - 1 */
|
|
||||||
|
|
||||||
unsigned char *window;
|
|
||||||
/* Sliding window. Input bytes are read into the second half of the window,
|
|
||||||
* and move to the first half later to keep a dictionary of at least wSize
|
|
||||||
* bytes. With this organization, matches are limited to a distance of
|
|
||||||
* wSize-MAX_MATCH bytes, but this ensures that IO is always
|
|
||||||
* performed with a length multiple of the block size. Also, it limits
|
|
||||||
* the window size to 64K, which is quite useful on MSDOS.
|
|
||||||
* To do: use the user input buffer as sliding window.
|
|
||||||
*/
|
|
||||||
|
|
||||||
unsigned long window_size;
|
|
||||||
/* Actual size of window: 2*wSize, except when the user input buffer
|
|
||||||
* is directly used as sliding window.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Pos *prev;
|
|
||||||
/* Link to older string with same hash index. To limit the size of this
|
|
||||||
* array to 64K, this link is maintained only for the last 32K strings.
|
|
||||||
* An index in this array is thus a window index modulo 32K.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Pos *head; /* Heads of the hash chains or NIL. */
|
|
||||||
|
|
||||||
unsigned int ins_h; /* hash index of string to be inserted */
|
|
||||||
unsigned int hash_size; /* number of elements in hash table */
|
|
||||||
unsigned int hash_bits; /* log2(hash_size) */
|
|
||||||
unsigned int hash_mask; /* hash_size-1 */
|
|
||||||
|
|
||||||
unsigned int hash_shift;
|
|
||||||
/* Number of bits by which ins_h must be shifted at each input
|
|
||||||
* step. It must be such that after MIN_MATCH steps, the oldest
|
|
||||||
* byte no longer takes part in the hash key, that is:
|
|
||||||
* hash_shift * MIN_MATCH >= hash_bits
|
|
||||||
*/
|
|
||||||
|
|
||||||
long block_start;
|
|
||||||
/* Window position at the beginning of the current output block. Gets
|
|
||||||
* negative when the window is moved backwards.
|
|
||||||
*/
|
|
||||||
|
|
||||||
unsigned int match_length; /* length of best match */
|
|
||||||
IPos prev_match; /* previous match */
|
|
||||||
int match_available; /* set if previous match exists */
|
|
||||||
unsigned int strstart; /* start of string to insert */
|
|
||||||
unsigned int match_start; /* start of matching string */
|
|
||||||
unsigned int lookahead; /* number of valid bytes ahead in window */
|
|
||||||
|
|
||||||
unsigned int prev_length;
|
|
||||||
/* Length of the best match at previous step. Matches not greater than this
|
|
||||||
* are discarded. This is used in the lazy match evaluation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
unsigned int max_chain_length;
|
|
||||||
/* To speed up deflation, hash chains are never searched beyond this
|
|
||||||
* length. A higher limit improves compression ratio but degrades the
|
|
||||||
* speed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
unsigned int max_lazy_match;
|
|
||||||
/* Attempt to find a better match only when the current match is strictly
|
|
||||||
* smaller than this value. This mechanism is used only for compression
|
|
||||||
* levels >= 4.
|
|
||||||
*/
|
|
||||||
# define max_insert_length max_lazy_match
|
|
||||||
/* Insert new strings in the hash table only if the match length is not
|
|
||||||
* greater than this length. This saves time but degrades compression.
|
|
||||||
* max_insert_length is used only for compression levels <= 3.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int level; /* compression level (1..9) */
|
|
||||||
int strategy; /* favor or force Huffman coding*/
|
|
||||||
|
|
||||||
unsigned int good_match;
|
|
||||||
/* Use a faster search when the previous match is longer than this */
|
|
||||||
|
|
||||||
int nice_match; /* Stop searching when current match exceeds this */
|
|
||||||
|
|
||||||
/* used by trees.c: */
|
|
||||||
/* Didn't use ct_data typedef below to suppress compiler warning */
|
|
||||||
struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
|
|
||||||
struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
|
|
||||||
struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
|
|
||||||
|
|
||||||
struct tree_desc_s l_desc; /* desc. for literal tree */
|
|
||||||
struct tree_desc_s d_desc; /* desc. for distance tree */
|
|
||||||
struct tree_desc_s bl_desc; /* desc. for bit length tree */
|
|
||||||
|
|
||||||
uint16_t bl_count[MAX_BITS+1];
|
|
||||||
/* number of codes at each bit length for an optimal tree */
|
|
||||||
|
|
||||||
int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
|
|
||||||
int heap_len; /* number of elements in the heap */
|
|
||||||
int heap_max; /* element of largest frequency */
|
|
||||||
/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
|
|
||||||
* The same heap array is used to build all trees.
|
|
||||||
*/
|
|
||||||
|
|
||||||
unsigned char depth[2*L_CODES+1];
|
|
||||||
/* Depth of each subtree used as tie breaker for trees of equal frequency
|
|
||||||
*/
|
|
||||||
|
|
||||||
unsigned char *l_buf; /* buffer for literals or lengths */
|
|
||||||
|
|
||||||
unsigned int lit_bufsize;
|
|
||||||
/* Size of match buffer for literals/lengths. There are 4 reasons for
|
|
||||||
* limiting lit_bufsize to 64K:
|
|
||||||
* - frequencies can be kept in 16 bit counters
|
|
||||||
* - if compression is not successful for the first block, all input
|
|
||||||
* data is still in the window so we can still emit a stored block even
|
|
||||||
* when input comes from standard input. (This can also be done for
|
|
||||||
* all blocks if lit_bufsize is not greater than 32K.)
|
|
||||||
* - if compression is not successful for a file smaller than 64K, we can
|
|
||||||
* even emit a stored file instead of a stored block (saving 5 bytes).
|
|
||||||
* This is applicable only for zip (not gzip or zlib).
|
|
||||||
* - creating new Huffman trees less frequently may not provide fast
|
|
||||||
* adaptation to changes in the input data statistics. (Take for
|
|
||||||
* example a binary file with poorly compressible code followed by
|
|
||||||
* a highly compressible string table.) Smaller buffer sizes give
|
|
||||||
* fast adaptation but have of course the overhead of transmitting
|
|
||||||
* trees more frequently.
|
|
||||||
* - I can't count above 4
|
|
||||||
*/
|
|
||||||
|
|
||||||
unsigned int last_lit; /* running index in l_buf */
|
|
||||||
|
|
||||||
uint16_t *d_buf;
|
|
||||||
/* Buffer for distances. To simplify the code, d_buf and l_buf have
|
|
||||||
* the same number of elements. To use different lengths, an extra flag
|
|
||||||
* array would be necessary.
|
|
||||||
*/
|
|
||||||
|
|
||||||
unsigned long opt_len; /* bit length of current block with optimal trees */
|
|
||||||
unsigned long static_len; /* bit length of current block with static trees */
|
|
||||||
unsigned int matches; /* number of string matches in current block */
|
|
||||||
unsigned int insert; /* bytes at end of window left to insert */
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
unsigned long compressed_len; /* total bit length of compressed file mod 2^32 */
|
|
||||||
unsigned long bits_sent; /* bit length of compressed data sent mod 2^32 */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint16_t bi_buf;
|
|
||||||
/* Output buffer. bits are inserted starting at the bottom (least
|
|
||||||
* significant bits).
|
|
||||||
*/
|
|
||||||
int bi_valid;
|
|
||||||
/* Number of valid bits in bi_buf. All bits above the last valid bit
|
|
||||||
* are always zero.
|
|
||||||
*/
|
|
||||||
|
|
||||||
unsigned long high_water;
|
|
||||||
/* High water mark offset in window for initialized bytes -- bytes above
|
|
||||||
* this are set to zero in order to avoid memory check warnings when
|
|
||||||
* longest match routines access bytes past the input. This is then
|
|
||||||
* updated to the new high water mark.
|
|
||||||
*/
|
|
||||||
} deflate_state;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
need_more, /* block not completed, need more input or more output */
|
|
||||||
block_done, /* block flush performed */
|
|
||||||
finish_started, /* finish started, need only more output at next deflate */
|
|
||||||
finish_done /* finish done, accept no more input or output */
|
|
||||||
} block_state;
|
|
||||||
|
|
||||||
/* Output a byte on the stream.
|
|
||||||
* IN assertion: there is enough room in pending_buf.
|
|
||||||
*/
|
|
||||||
#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Output a short LSB first on the stream.
|
|
||||||
* IN assertion: there is enough room in pendingBuf.
|
|
||||||
*/
|
|
||||||
#if defined(__x86_64) || defined(__i386_)
|
|
||||||
/* Compared to the else-clause's implementation, there are few advantages:
|
|
||||||
* - s->pending is loaded only once (else-clause's implementation needs to
|
|
||||||
* load s->pending twice due to the alias between s->pending and
|
|
||||||
* s->pending_buf[].
|
|
||||||
* - no instructions for extracting bytes from short.
|
|
||||||
* - needs less registers
|
|
||||||
* - stores to adjacent bytes are merged into a single store, albeit at the
|
|
||||||
* cost of penalty of potentially unaligned access.
|
|
||||||
*/
|
|
||||||
#define put_short(s, w) { \
|
|
||||||
s->pending += 2; \
|
|
||||||
*(uint16_t*)(&s->pending_buf[s->pending - 2]) = (w) ; \
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define put_short(s, w) { \
|
|
||||||
put_byte(s, (unsigned char)((w) & 0xff)); \
|
|
||||||
put_byte(s, (unsigned char)((uint16_t)(w) >> 8)); \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
|
|
||||||
/* Minimum amount of lookahead, except at the end of the input file.
|
|
||||||
* See deflate.c for comments about the MIN_MATCH+1.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
|
|
||||||
/* In order to simplify the code, particularly on 16 bit machines, match
|
|
||||||
* distances are limited to MAX_DIST instead of WSIZE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define WIN_INIT MAX_MATCH
|
|
||||||
/* Number of bytes after end of data in window to initialize in order to avoid
|
|
||||||
memory checker errors from longest match routines */
|
|
||||||
|
|
||||||
/* in trees.c */
|
|
||||||
void ZLIB_INTERNAL _tr_init(deflate_state *s);
|
|
||||||
int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc);
|
|
||||||
void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, char *buf, unsigned long stored_len, int last);
|
|
||||||
void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s);
|
|
||||||
void ZLIB_INTERNAL _tr_align(deflate_state *s);
|
|
||||||
void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, char *buf, unsigned long stored_len, int last);
|
|
||||||
void ZLIB_INTERNAL bi_windup(deflate_state *s);
|
|
||||||
|
|
||||||
#define d_code(dist) ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
|
|
||||||
/* Mapping from a distance to a distance code. dist is the distance - 1 and
|
|
||||||
* must not have side effects. _dist_code[256] and _dist_code[257] are never
|
|
||||||
* used.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef DEBUG
|
|
||||||
/* Inline versions of _tr_tally for speed: */
|
|
||||||
|
|
||||||
# if defined(GEN_TREES_H)
|
|
||||||
extern unsigned char ZLIB_INTERNAL _length_code[];
|
|
||||||
extern unsigned char ZLIB_INTERNAL _dist_code[];
|
|
||||||
# else
|
|
||||||
extern const unsigned char ZLIB_INTERNAL _length_code[];
|
|
||||||
extern const unsigned char ZLIB_INTERNAL _dist_code[];
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# define _tr_tally_lit(s, c, flush) \
|
|
||||||
{ unsigned char cc = (c); \
|
|
||||||
s->d_buf[s->last_lit] = 0; \
|
|
||||||
s->l_buf[s->last_lit++] = cc; \
|
|
||||||
s->dyn_ltree[cc].Freq++; \
|
|
||||||
flush = (s->last_lit == s->lit_bufsize-1); \
|
|
||||||
}
|
|
||||||
# define _tr_tally_dist(s, distance, length, flush) \
|
|
||||||
{ unsigned char len = (length); \
|
|
||||||
uint16_t dist = (distance); \
|
|
||||||
s->d_buf[s->last_lit] = dist; \
|
|
||||||
s->l_buf[s->last_lit++] = len; \
|
|
||||||
dist--; \
|
|
||||||
s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
|
|
||||||
s->dyn_dtree[d_code(dist)].Freq++; \
|
|
||||||
flush = (s->last_lit == s->lit_bufsize-1); \
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
|
|
||||||
# define _tr_tally_dist(s, distance, length, flush) \
|
|
||||||
flush = _tr_tally(s, distance, length)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Update a hash value with the given input byte
|
|
||||||
* IN assertion: all calls to to UPDATE_HASH are made with consecutive
|
|
||||||
* input characters, so that a running hash key can be computed from the
|
|
||||||
* previous key instead of complete recalculation each time.
|
|
||||||
*/
|
|
||||||
#ifdef X86_SSE4_2_CRC_HASH
|
|
||||||
#define UPDATE_HASH(s, h, i) \
|
|
||||||
do {\
|
|
||||||
if (s->level < 6) \
|
|
||||||
h = (3483 * (s->window[i]) +\
|
|
||||||
23081* (s->window[i+1]) +\
|
|
||||||
6954 * (s->window[i+2]) +\
|
|
||||||
20947* (s->window[i+3])) & s->hash_mask;\
|
|
||||||
else\
|
|
||||||
h = (25881* (s->window[i]) +\
|
|
||||||
24674* (s->window[i+1]) +\
|
|
||||||
25811* (s->window[i+2])) & s->hash_mask;\
|
|
||||||
} while (0)
|
|
||||||
#else
|
|
||||||
# define UPDATE_HASH(s, h, i) (h = (((h) << s->hash_shift) ^ (s->window[i + (MIN_MATCH-1)])) & s->hash_mask)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef DEBUG
|
|
||||||
# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
|
|
||||||
/* Send a code of the given tree. c and tree must not have side effects */
|
|
||||||
|
|
||||||
#else /* DEBUG */
|
|
||||||
# define send_code(s, c, tree) \
|
|
||||||
{ if (z_verbose > 2) { \
|
|
||||||
fprintf(stderr, "\ncd %3d ", (c)); \
|
|
||||||
} \
|
|
||||||
send_bits(s, tree[c].Code, tree[c].Len); \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
/* ===========================================================================
|
|
||||||
* Send a value on a given number of bits.
|
|
||||||
* IN assertion: length <= 16 and value fits in length bits.
|
|
||||||
*/
|
|
||||||
local void send_bits(deflate_state *s, int value, int length) {
|
|
||||||
Tracevv((stderr, " l %2d v %4x ", length, value));
|
|
||||||
Assert(length > 0 && length <= 15, "invalid length");
|
|
||||||
s->bits_sent += (unsigned long)length;
|
|
||||||
|
|
||||||
/* If not enough room in bi_buf, use (valid) bits from bi_buf and
|
|
||||||
* (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
|
|
||||||
* unused bits in value.
|
|
||||||
*/
|
|
||||||
if (s->bi_valid > (int)Buf_size - length) {
|
|
||||||
s->bi_buf |= (uint16_t)value << s->bi_valid;
|
|
||||||
put_short(s, s->bi_buf);
|
|
||||||
s->bi_buf = (uint16_t)value >> (Buf_size - s->bi_valid);
|
|
||||||
s->bi_valid += length - Buf_size;
|
|
||||||
} else {
|
|
||||||
s->bi_buf |= (uint16_t)value << s->bi_valid;
|
|
||||||
s->bi_valid += length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define send_bits(s, value, length) \
|
|
||||||
{ int len = length;\
|
|
||||||
if (s->bi_valid > (int)Buf_size - len) {\
|
|
||||||
int val = value;\
|
|
||||||
s->bi_buf |= (uint16_t)val << s->bi_valid;\
|
|
||||||
put_short(s, s->bi_buf);\
|
|
||||||
s->bi_buf = (uint16_t)val >> (Buf_size - s->bi_valid);\
|
|
||||||
s->bi_valid += len - Buf_size;\
|
|
||||||
} else {\
|
|
||||||
s->bi_buf |= (uint16_t)(value) << s->bi_valid;\
|
|
||||||
s->bi_valid += len;\
|
|
||||||
}\
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* DEFLATE_H_ */
|
|
@ -1,114 +0,0 @@
|
|||||||
/* deflate_fast.c -- compress data using the fast strategy of deflation algorithm
|
|
||||||
*
|
|
||||||
* Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "deflate.h"
|
|
||||||
#include "deflate_p.h"
|
|
||||||
#include "match.h"
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Compress as much as possible from the input stream, return the current
|
|
||||||
* block state.
|
|
||||||
* This function does not perform lazy evaluation of matches and inserts
|
|
||||||
* new strings in the dictionary only for unmatched strings or for short
|
|
||||||
* matches. It is used only for the fast compression options.
|
|
||||||
*/
|
|
||||||
block_state deflate_fast(deflate_state *s, int flush) {
|
|
||||||
IPos hash_head; /* head of the hash chain */
|
|
||||||
int bflush; /* set if current block must be flushed */
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
/* Make sure that we always have enough lookahead, except
|
|
||||||
* at the end of the input file. We need MAX_MATCH bytes
|
|
||||||
* for the next match, plus MIN_MATCH bytes to insert the
|
|
||||||
* string following the next match.
|
|
||||||
*/
|
|
||||||
if (s->lookahead < MIN_LOOKAHEAD) {
|
|
||||||
fill_window(s);
|
|
||||||
if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
|
|
||||||
return need_more;
|
|
||||||
}
|
|
||||||
if (s->lookahead == 0)
|
|
||||||
break; /* flush the current block */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Insert the string window[strstart .. strstart+2] in the
|
|
||||||
* dictionary, and set hash_head to the head of the hash chain:
|
|
||||||
*/
|
|
||||||
hash_head = NIL;
|
|
||||||
if (s->lookahead >= MIN_MATCH) {
|
|
||||||
hash_head = insert_string(s, s->strstart);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the longest match, discarding those <= prev_length.
|
|
||||||
* At this point we have always match_length < MIN_MATCH
|
|
||||||
*/
|
|
||||||
if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
|
|
||||||
/* To simplify the code, we prevent matches with the string
|
|
||||||
* of window index 0 (in particular we have to avoid a match
|
|
||||||
* of the string with itself at the start of the input file).
|
|
||||||
*/
|
|
||||||
s->match_length = longest_match(s, hash_head);
|
|
||||||
/* longest_match() sets match_start */
|
|
||||||
}
|
|
||||||
if (s->match_length >= MIN_MATCH) {
|
|
||||||
check_match(s, s->strstart, s->match_start, s->match_length);
|
|
||||||
|
|
||||||
_tr_tally_dist(s, s->strstart - s->match_start, s->match_length - MIN_MATCH, bflush);
|
|
||||||
|
|
||||||
s->lookahead -= s->match_length;
|
|
||||||
|
|
||||||
/* Insert new strings in the hash table only if the match length
|
|
||||||
* is not too large. This saves time but degrades compression.
|
|
||||||
*/
|
|
||||||
if (s->match_length <= s->max_insert_length && s->lookahead >= MIN_MATCH) {
|
|
||||||
s->match_length--; /* string at strstart already in table */
|
|
||||||
s->strstart++;
|
|
||||||
#ifdef NOT_TWEAK_COMPILER
|
|
||||||
do {
|
|
||||||
insert_string(s, s->strstart);
|
|
||||||
s->strstart++;
|
|
||||||
/* strstart never exceeds WSIZE-MAX_MATCH, so there are
|
|
||||||
* always MIN_MATCH bytes ahead.
|
|
||||||
*/
|
|
||||||
} while (--s->match_length != 0);
|
|
||||||
#else
|
|
||||||
{
|
|
||||||
bulk_insert_str(s, s->strstart, s->match_length);
|
|
||||||
s->strstart += s->match_length;
|
|
||||||
s->match_length = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
s->strstart += s->match_length;
|
|
||||||
s->match_length = 0;
|
|
||||||
s->ins_h = s->window[s->strstart];
|
|
||||||
UPDATE_HASH(s, s->ins_h, s->strstart+2 - (MIN_MATCH));
|
|
||||||
#if MIN_MATCH != 3
|
|
||||||
Call UPDATE_HASH() MIN_MATCH-3 more times
|
|
||||||
#endif
|
|
||||||
/* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
|
|
||||||
* matter since it will be recomputed at next deflate call.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* No match, output a literal byte */
|
|
||||||
Tracevv((stderr, "%c", s->window[s->strstart]));
|
|
||||||
_tr_tally_lit(s, s->window[s->strstart], bflush);
|
|
||||||
s->lookahead--;
|
|
||||||
s->strstart++;
|
|
||||||
}
|
|
||||||
if (bflush)
|
|
||||||
FLUSH_BLOCK(s, 0);
|
|
||||||
}
|
|
||||||
s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
|
|
||||||
if (flush == Z_FINISH) {
|
|
||||||
FLUSH_BLOCK(s, 1);
|
|
||||||
return finish_done;
|
|
||||||
}
|
|
||||||
if (s->last_lit)
|
|
||||||
FLUSH_BLOCK(s, 0);
|
|
||||||
return block_done;
|
|
||||||
}
|
|
@ -1,322 +0,0 @@
|
|||||||
/* deflate_medium.c -- The deflate_medium deflate strategy
|
|
||||||
*
|
|
||||||
* Copyright (C) 2013 Intel Corporation. All rights reserved.
|
|
||||||
* Authors:
|
|
||||||
* Arjan van de Ven <arjan@linux.intel.com>
|
|
||||||
*
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
#ifdef MEDIUM_STRATEGY
|
|
||||||
#include "deflate.h"
|
|
||||||
#include "deflate_p.h"
|
|
||||||
#include "match.h"
|
|
||||||
|
|
||||||
struct match {
|
|
||||||
unsigned int match_start;
|
|
||||||
unsigned int match_length;
|
|
||||||
unsigned int strstart;
|
|
||||||
unsigned int orgstart;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MAX_DIST2 ((1 << MAX_WBITS) - MIN_LOOKAHEAD)
|
|
||||||
|
|
||||||
static int tr_tally_dist(deflate_state *s, int distance, int length) {
|
|
||||||
return _tr_tally(s, distance, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tr_tally_lit(deflate_state *s, int c) {
|
|
||||||
return _tr_tally(s, 0, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int emit_match(deflate_state *s, struct match match) {
|
|
||||||
int flush = 0;
|
|
||||||
|
|
||||||
/* matches that are not long enough we need to emit as litterals */
|
|
||||||
if (match.match_length < MIN_MATCH) {
|
|
||||||
while (match.match_length) {
|
|
||||||
flush += tr_tally_lit(s, s->window[match.strstart]);
|
|
||||||
s->lookahead--;
|
|
||||||
match.strstart++;
|
|
||||||
match.match_length--;
|
|
||||||
}
|
|
||||||
return flush;
|
|
||||||
}
|
|
||||||
|
|
||||||
check_match(s, match.strstart, match.match_start, match.match_length);
|
|
||||||
|
|
||||||
flush += tr_tally_dist(s, match.strstart - match.match_start, match.match_length - MIN_MATCH);
|
|
||||||
|
|
||||||
s->lookahead -= match.match_length;
|
|
||||||
return flush;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void insert_match(deflate_state *s, struct match match) {
|
|
||||||
if (unlikely(s->lookahead <= match.match_length + MIN_MATCH))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* matches that are not long enough we need to emit as litterals */
|
|
||||||
if (match.match_length < MIN_MATCH) {
|
|
||||||
#ifdef NOT_TWEAK_COMPILER
|
|
||||||
while (match.match_length) {
|
|
||||||
match.strstart++;
|
|
||||||
match.match_length--;
|
|
||||||
|
|
||||||
if (match.match_length) {
|
|
||||||
if (match.strstart >= match.orgstart) {
|
|
||||||
insert_string(s, match.strstart);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (likely(match.match_length == 1)) {
|
|
||||||
match.strstart++;
|
|
||||||
match.match_length = 0;
|
|
||||||
}else{
|
|
||||||
match.strstart++;
|
|
||||||
match.match_length--;
|
|
||||||
if (match.strstart >= match.orgstart) {
|
|
||||||
bulk_insert_str(s, match.strstart, match.match_length);
|
|
||||||
}
|
|
||||||
match.strstart += match.match_length;
|
|
||||||
match.match_length = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Insert new strings in the hash table only if the match length
|
|
||||||
* is not too large. This saves time but degrades compression.
|
|
||||||
*/
|
|
||||||
if (match.match_length <= 16* s->max_insert_length && s->lookahead >= MIN_MATCH) {
|
|
||||||
match.match_length--; /* string at strstart already in table */
|
|
||||||
match.strstart++;
|
|
||||||
#ifdef NOT_TWEAK_COMPILER
|
|
||||||
do {
|
|
||||||
if (likely(match.strstart >= match.orgstart)) {
|
|
||||||
insert_string(s, match.strstart);
|
|
||||||
}
|
|
||||||
match.strstart++;
|
|
||||||
/* strstart never exceeds WSIZE-MAX_MATCH, so there are
|
|
||||||
* always MIN_MATCH bytes ahead.
|
|
||||||
*/
|
|
||||||
} while (--match.match_length != 0);
|
|
||||||
#else
|
|
||||||
if (likely(match.strstart >= match.orgstart)) {
|
|
||||||
bulk_insert_str(s, match.strstart, match.match_length);
|
|
||||||
}
|
|
||||||
match.strstart += match.match_length;
|
|
||||||
match.match_length = 0;
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
match.strstart += match.match_length;
|
|
||||||
match.match_length = 0;
|
|
||||||
s->ins_h = s->window[match.strstart];
|
|
||||||
if (match.strstart >= 1)
|
|
||||||
UPDATE_HASH(s, s->ins_h, match.strstart+2-MIN_MATCH);
|
|
||||||
#if MIN_MATCH != 3
|
|
||||||
#warning Call UPDATE_HASH() MIN_MATCH-3 more times
|
|
||||||
#endif
|
|
||||||
/* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
|
|
||||||
* matter since it will be recomputed at next deflate call.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fizzle_matches(deflate_state *s, struct match *current, struct match *next) {
|
|
||||||
IPos limit;
|
|
||||||
unsigned char *match, *orig;
|
|
||||||
int changed = 0;
|
|
||||||
struct match c, n;
|
|
||||||
/* step zero: sanity checks */
|
|
||||||
|
|
||||||
if (current->match_length <= 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (unlikely(current->match_length > 1 + next->match_start))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (unlikely(current->match_length > 1 + next->strstart))
|
|
||||||
return;
|
|
||||||
|
|
||||||
match = s->window - current->match_length + 1 + next->match_start;
|
|
||||||
orig = s->window - current->match_length + 1 + next->strstart;
|
|
||||||
|
|
||||||
/* quick exit check.. if this fails then don't bother with anything else */
|
|
||||||
if (likely(*match != *orig))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* check the overlap case and just give up. We can do better in theory,
|
|
||||||
* but unlikely to be worth it
|
|
||||||
*/
|
|
||||||
if (next->match_start + next->match_length >= current->strstart)
|
|
||||||
return;
|
|
||||||
|
|
||||||
c = *current;
|
|
||||||
n = *next;
|
|
||||||
|
|
||||||
/* step one: try to move the "next" match to the left as much as possible */
|
|
||||||
limit = next->strstart > MAX_DIST2 ? next->strstart - MAX_DIST2 : 0;
|
|
||||||
|
|
||||||
match = s->window + n.match_start - 1;
|
|
||||||
orig = s->window + n.strstart - 1;
|
|
||||||
|
|
||||||
while (*match == *orig) {
|
|
||||||
if (c.match_length < 1)
|
|
||||||
break;
|
|
||||||
if (n.strstart <= limit)
|
|
||||||
break;
|
|
||||||
if (n.match_length >= 256)
|
|
||||||
break;
|
|
||||||
if (n.match_start <= 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
n.strstart--;
|
|
||||||
n.match_start--;
|
|
||||||
n.match_length++;
|
|
||||||
c.match_length--;
|
|
||||||
match--;
|
|
||||||
orig--;
|
|
||||||
changed++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!changed)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (c.match_length <= 1 && n.match_length != 2) {
|
|
||||||
n.orgstart++;
|
|
||||||
*current = c;
|
|
||||||
*next = n;
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
block_state deflate_medium(deflate_state *s, int flush) {
|
|
||||||
struct match current_match, next_match;
|
|
||||||
|
|
||||||
memset(¤t_match, 0, sizeof(struct match));
|
|
||||||
memset(&next_match, 0, sizeof(struct match));
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
IPos hash_head = 0; /* head of the hash chain */
|
|
||||||
int bflush; /* set if current block must be flushed */
|
|
||||||
|
|
||||||
/* Make sure that we always have enough lookahead, except
|
|
||||||
* at the end of the input file. We need MAX_MATCH bytes
|
|
||||||
* for the next match, plus MIN_MATCH bytes to insert the
|
|
||||||
* string following the next current_match.
|
|
||||||
*/
|
|
||||||
if (s->lookahead < MIN_LOOKAHEAD) {
|
|
||||||
fill_window(s);
|
|
||||||
if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
|
|
||||||
return need_more;
|
|
||||||
}
|
|
||||||
if (s->lookahead == 0)
|
|
||||||
break; /* flush the current block */
|
|
||||||
next_match.match_length = 0;
|
|
||||||
}
|
|
||||||
s->prev_length = 2;
|
|
||||||
|
|
||||||
/* Insert the string window[strstart .. strstart+2] in the
|
|
||||||
* dictionary, and set hash_head to the head of the hash chain:
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* If we already have a future match from a previous round, just use that */
|
|
||||||
if (next_match.match_length > 0) {
|
|
||||||
current_match = next_match;
|
|
||||||
next_match.match_length = 0;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
hash_head = 0;
|
|
||||||
if (s->lookahead >= MIN_MATCH) {
|
|
||||||
hash_head = insert_string(s, s->strstart);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set up the initial match to be a 1 byte literal */
|
|
||||||
current_match.match_start = 0;
|
|
||||||
current_match.match_length = 1;
|
|
||||||
current_match.strstart = s->strstart;
|
|
||||||
current_match.orgstart = current_match.strstart;
|
|
||||||
|
|
||||||
/* Find the longest match, discarding those <= prev_length.
|
|
||||||
* At this point we have always match_length < MIN_MATCH
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (hash_head != 0 && s->strstart - hash_head <= MAX_DIST2) {
|
|
||||||
/* To simplify the code, we prevent matches with the string
|
|
||||||
* of window index 0 (in particular we have to avoid a match
|
|
||||||
* of the string with itself at the start of the input file).
|
|
||||||
*/
|
|
||||||
current_match.match_length = longest_match(s, hash_head);
|
|
||||||
current_match.match_start = s->match_start;
|
|
||||||
if (current_match.match_length < MIN_MATCH)
|
|
||||||
current_match.match_length = 1;
|
|
||||||
if (current_match.match_start >= current_match.strstart) {
|
|
||||||
/* this can happen due to some restarts */
|
|
||||||
current_match.match_length = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
insert_match(s, current_match);
|
|
||||||
|
|
||||||
/* now, look ahead one */
|
|
||||||
if (s->lookahead > MIN_LOOKAHEAD) {
|
|
||||||
s->strstart = current_match.strstart + current_match.match_length;
|
|
||||||
hash_head = insert_string(s, s->strstart);
|
|
||||||
|
|
||||||
/* set up the initial match to be a 1 byte literal */
|
|
||||||
next_match.match_start = 0;
|
|
||||||
next_match.match_length = 1;
|
|
||||||
next_match.strstart = s->strstart;
|
|
||||||
next_match.orgstart = next_match.strstart;
|
|
||||||
|
|
||||||
/* Find the longest match, discarding those <= prev_length.
|
|
||||||
* At this point we have always match_length < MIN_MATCH
|
|
||||||
*/
|
|
||||||
if (hash_head != 0 && s->strstart - hash_head <= MAX_DIST2) {
|
|
||||||
/* To simplify the code, we prevent matches with the string
|
|
||||||
* of window index 0 (in particular we have to avoid a match
|
|
||||||
* of the string with itself at the start of the input file).
|
|
||||||
*/
|
|
||||||
next_match.match_length = longest_match(s, hash_head);
|
|
||||||
next_match.match_start = s->match_start;
|
|
||||||
if (next_match.match_start >= next_match.strstart) {
|
|
||||||
/* this can happen due to some restarts */
|
|
||||||
next_match.match_length = 1;
|
|
||||||
}
|
|
||||||
if (next_match.match_length < MIN_MATCH)
|
|
||||||
next_match.match_length = 1;
|
|
||||||
else
|
|
||||||
fizzle_matches(s, ¤t_match, &next_match);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* short matches with a very long distance are rarely a good idea encoding wise */
|
|
||||||
if (next_match.match_length == 3 && (next_match.strstart - next_match.match_start) > 12000)
|
|
||||||
next_match.match_length = 1;
|
|
||||||
s->strstart = current_match.strstart;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
next_match.match_length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* now emit the current match */
|
|
||||||
bflush = emit_match(s, current_match);
|
|
||||||
|
|
||||||
/* move the "cursor" forward */
|
|
||||||
s->strstart += current_match.match_length;
|
|
||||||
|
|
||||||
if (bflush)
|
|
||||||
FLUSH_BLOCK(s, 0);
|
|
||||||
}
|
|
||||||
s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
|
|
||||||
if (flush == Z_FINISH) {
|
|
||||||
FLUSH_BLOCK(s, 1);
|
|
||||||
return finish_done;
|
|
||||||
}
|
|
||||||
if (s->last_lit)
|
|
||||||
FLUSH_BLOCK(s, 0);
|
|
||||||
|
|
||||||
return block_done;
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,96 +0,0 @@
|
|||||||
/* deflate_p.h -- Private inline functions and macros shared with more than
|
|
||||||
* one deflate method
|
|
||||||
*
|
|
||||||
* Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef DEFLATE_P_H
|
|
||||||
#define DEFLATE_P_H
|
|
||||||
|
|
||||||
#if defined(X86_CPUID)
|
|
||||||
# include "arch/x86/x86.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Forward declare common non-inlined functions declared in deflate.c */
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
void check_match(deflate_state *s, IPos start, IPos match, int length);
|
|
||||||
#else
|
|
||||||
#define check_match(s, start, match, length)
|
|
||||||
#endif
|
|
||||||
void fill_window(deflate_state *s);
|
|
||||||
void flush_pending(z_stream *strm);
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Insert string str in the dictionary and set match_head to the previous head
|
|
||||||
* of the hash chain (the most recent string with same hash key). Return
|
|
||||||
* the previous length of the hash chain.
|
|
||||||
* IN assertion: all calls to to INSERT_STRING are made with consecutive
|
|
||||||
* input characters and the first MIN_MATCH bytes of str are valid
|
|
||||||
* (except for the last MIN_MATCH-1 bytes of the input file).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef X86_SSE4_2_CRC_HASH
|
|
||||||
extern Pos insert_string_sse(deflate_state *const s, const Pos str, uInt count);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
local inline Pos insert_string_c(deflate_state *const s, const Pos str, uInt count) {
|
|
||||||
Pos ret = 0;
|
|
||||||
uInt idx;
|
|
||||||
|
|
||||||
for (idx = 0; idx < count; idx++) {
|
|
||||||
UPDATE_HASH(s, s->ins_h, str+idx);
|
|
||||||
if (s->head[s->ins_h] != str+idx) {
|
|
||||||
s->prev[(str+idx) & s->w_mask] = s->head[s->ins_h];
|
|
||||||
s->head[s->ins_h] = str+idx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret = s->prev[(str+count-1) & s->w_mask];
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
local inline Pos insert_string(deflate_state *const s, const Pos str) {
|
|
||||||
#ifdef X86_SSE4_2_CRC_HASH
|
|
||||||
if (x86_cpu_has_sse42)
|
|
||||||
return insert_string_sse(s, str, 1);
|
|
||||||
#endif
|
|
||||||
return insert_string_c(s, str, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NOT_TWEAK_COMPILER
|
|
||||||
local inline void bulk_insert_str(deflate_state *const s, Pos startpos, uInt count) {
|
|
||||||
# ifdef X86_SSE4_2_CRC_HASH
|
|
||||||
if (x86_cpu_has_sse42) {
|
|
||||||
insert_string_sse(s, startpos, count);
|
|
||||||
} else
|
|
||||||
# endif
|
|
||||||
{
|
|
||||||
insert_string_c(s, startpos, count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* NOT_TWEAK_COMPILER */
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Flush the current block, with given end-of-file flag.
|
|
||||||
* IN assertion: strstart is set to the end of the current match.
|
|
||||||
*/
|
|
||||||
#define FLUSH_BLOCK_ONLY(s, last) { \
|
|
||||||
_tr_flush_block(s, (s->block_start >= 0L ? \
|
|
||||||
(char *)&s->window[(unsigned)s->block_start] : \
|
|
||||||
(char *)Z_NULL), \
|
|
||||||
(ulg)((long)s->strstart - s->block_start), \
|
|
||||||
(last)); \
|
|
||||||
s->block_start = s->strstart; \
|
|
||||||
flush_pending(s->strm); \
|
|
||||||
Tracev((stderr, "[FLUSH]")); \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Same but force premature exit if necessary. */
|
|
||||||
#define FLUSH_BLOCK(s, last) { \
|
|
||||||
FLUSH_BLOCK_ONLY(s, last); \
|
|
||||||
if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,160 +0,0 @@
|
|||||||
/* deflate_slow.c -- compress data using the slow strategy of deflation algorithm
|
|
||||||
*
|
|
||||||
* Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "deflate.h"
|
|
||||||
#include "deflate_p.h"
|
|
||||||
#include "match.h"
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Local data
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TOO_FAR
|
|
||||||
# define TOO_FAR 4096
|
|
||||||
#endif
|
|
||||||
/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Same as deflate_medium, but achieves better compression. We use a lazy
|
|
||||||
* evaluation for matches: a match is finally adopted only if there is
|
|
||||||
* no better match at the next window position.
|
|
||||||
*/
|
|
||||||
block_state deflate_slow(deflate_state *s, int flush) {
|
|
||||||
IPos hash_head; /* head of hash chain */
|
|
||||||
int bflush; /* set if current block must be flushed */
|
|
||||||
|
|
||||||
/* Process the input block. */
|
|
||||||
for (;;) {
|
|
||||||
/* Make sure that we always have enough lookahead, except
|
|
||||||
* at the end of the input file. We need MAX_MATCH bytes
|
|
||||||
* for the next match, plus MIN_MATCH bytes to insert the
|
|
||||||
* string following the next match.
|
|
||||||
*/
|
|
||||||
if (s->lookahead < MIN_LOOKAHEAD) {
|
|
||||||
fill_window(s);
|
|
||||||
if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
|
|
||||||
return need_more;
|
|
||||||
}
|
|
||||||
if (s->lookahead == 0)
|
|
||||||
break; /* flush the current block */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Insert the string window[strstart .. strstart+2] in the
|
|
||||||
* dictionary, and set hash_head to the head of the hash chain:
|
|
||||||
*/
|
|
||||||
hash_head = NIL;
|
|
||||||
if (s->lookahead >= MIN_MATCH) {
|
|
||||||
hash_head = insert_string(s, s->strstart);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the longest match, discarding those <= prev_length.
|
|
||||||
*/
|
|
||||||
s->prev_length = s->match_length, s->prev_match = s->match_start;
|
|
||||||
s->match_length = MIN_MATCH-1;
|
|
||||||
|
|
||||||
if (hash_head != NIL && s->prev_length < s->max_lazy_match && s->strstart - hash_head <= MAX_DIST(s)) {
|
|
||||||
/* To simplify the code, we prevent matches with the string
|
|
||||||
* of window index 0 (in particular we have to avoid a match
|
|
||||||
* of the string with itself at the start of the input file).
|
|
||||||
*/
|
|
||||||
s->match_length = longest_match(s, hash_head);
|
|
||||||
/* longest_match() sets match_start */
|
|
||||||
|
|
||||||
if (s->match_length <= 5 && (s->strategy == Z_FILTERED
|
|
||||||
#if TOO_FAR <= 32767
|
|
||||||
|| (s->match_length == MIN_MATCH && s->strstart - s->match_start > TOO_FAR)
|
|
||||||
#endif
|
|
||||||
)) {
|
|
||||||
|
|
||||||
/* If prev_match is also MIN_MATCH, match_start is garbage
|
|
||||||
* but we will ignore the current match anyway.
|
|
||||||
*/
|
|
||||||
s->match_length = MIN_MATCH-1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* If there was a match at the previous step and the current
|
|
||||||
* match is not better, output the previous match:
|
|
||||||
*/
|
|
||||||
if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
|
|
||||||
uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
|
|
||||||
/* Do not insert strings in hash table beyond this. */
|
|
||||||
|
|
||||||
check_match(s, s->strstart-1, s->prev_match, s->prev_length);
|
|
||||||
|
|
||||||
_tr_tally_dist(s, s->strstart -1 - s->prev_match, s->prev_length - MIN_MATCH, bflush);
|
|
||||||
|
|
||||||
/* Insert in hash table all strings up to the end of the match.
|
|
||||||
* strstart-1 and strstart are already inserted. If there is not
|
|
||||||
* enough lookahead, the last two strings are not inserted in
|
|
||||||
* the hash table.
|
|
||||||
*/
|
|
||||||
s->lookahead -= s->prev_length-1;
|
|
||||||
|
|
||||||
#ifdef NOT_TWEAK_COMPILER
|
|
||||||
s->prev_length -= 2;
|
|
||||||
do {
|
|
||||||
if (++s->strstart <= max_insert) {
|
|
||||||
insert_string(s, s->strstart);
|
|
||||||
}
|
|
||||||
} while (--s->prev_length != 0);
|
|
||||||
s->match_available = 0;
|
|
||||||
s->match_length = MIN_MATCH-1;
|
|
||||||
s->strstart++;
|
|
||||||
#else
|
|
||||||
{
|
|
||||||
uInt mov_fwd = s->prev_length - 2;
|
|
||||||
uInt insert_cnt = mov_fwd;
|
|
||||||
if (unlikely(insert_cnt > max_insert - s->strstart))
|
|
||||||
insert_cnt = max_insert - s->strstart;
|
|
||||||
|
|
||||||
bulk_insert_str(s, s->strstart + 1, insert_cnt);
|
|
||||||
s->prev_length = 0;
|
|
||||||
s->match_available = 0;
|
|
||||||
s->match_length = MIN_MATCH-1;
|
|
||||||
s->strstart += mov_fwd + 1;
|
|
||||||
}
|
|
||||||
#endif /*NOT_TWEAK_COMPILER*/
|
|
||||||
|
|
||||||
if (bflush) FLUSH_BLOCK(s, 0);
|
|
||||||
|
|
||||||
} else if (s->match_available) {
|
|
||||||
/* If there was no match at the previous position, output a
|
|
||||||
* single literal. If there was a match but the current match
|
|
||||||
* is longer, truncate the previous match to a single literal.
|
|
||||||
*/
|
|
||||||
Tracevv((stderr, "%c", s->window[s->strstart-1]));
|
|
||||||
_tr_tally_lit(s, s->window[s->strstart-1], bflush);
|
|
||||||
if (bflush) {
|
|
||||||
FLUSH_BLOCK_ONLY(s, 0);
|
|
||||||
}
|
|
||||||
s->strstart++;
|
|
||||||
s->lookahead--;
|
|
||||||
if (s->strm->avail_out == 0)
|
|
||||||
return need_more;
|
|
||||||
} else {
|
|
||||||
/* There is no previous match to compare with, wait for
|
|
||||||
* the next step to decide.
|
|
||||||
*/
|
|
||||||
s->match_available = 1;
|
|
||||||
s->strstart++;
|
|
||||||
s->lookahead--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Assert(flush != Z_NO_FLUSH, "no flush?");
|
|
||||||
if (s->match_available) {
|
|
||||||
Tracevv((stderr, "%c", s->window[s->strstart-1]));
|
|
||||||
_tr_tally_lit(s, s->window[s->strstart-1], bflush);
|
|
||||||
s->match_available = 0;
|
|
||||||
}
|
|
||||||
s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
|
|
||||||
if (flush == Z_FINISH) {
|
|
||||||
FLUSH_BLOCK(s, 1);
|
|
||||||
return finish_done;
|
|
||||||
}
|
|
||||||
if (s->last_lit)
|
|
||||||
FLUSH_BLOCK(s, 0);
|
|
||||||
return block_done;
|
|
||||||
}
|
|
@ -1,209 +0,0 @@
|
|||||||
1. Compression algorithm (deflate)
|
|
||||||
|
|
||||||
The deflation algorithm used by gzip (also zip and zlib) is a variation of
|
|
||||||
LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in
|
|
||||||
the input data. The second occurrence of a string is replaced by a
|
|
||||||
pointer to the previous string, in the form of a pair (distance,
|
|
||||||
length). Distances are limited to 32K bytes, and lengths are limited
|
|
||||||
to 258 bytes. When a string does not occur anywhere in the previous
|
|
||||||
32K bytes, it is emitted as a sequence of literal bytes. (In this
|
|
||||||
description, `string' must be taken as an arbitrary sequence of bytes,
|
|
||||||
and is not restricted to printable characters.)
|
|
||||||
|
|
||||||
Literals or match lengths are compressed with one Huffman tree, and
|
|
||||||
match distances are compressed with another tree. The trees are stored
|
|
||||||
in a compact form at the start of each block. The blocks can have any
|
|
||||||
size (except that the compressed data for one block must fit in
|
|
||||||
available memory). A block is terminated when deflate() determines that
|
|
||||||
it would be useful to start another block with fresh trees. (This is
|
|
||||||
somewhat similar to the behavior of LZW-based _compress_.)
|
|
||||||
|
|
||||||
Duplicated strings are found using a hash table. All input strings of
|
|
||||||
length 3 are inserted in the hash table. A hash index is computed for
|
|
||||||
the next 3 bytes. If the hash chain for this index is not empty, all
|
|
||||||
strings in the chain are compared with the current input string, and
|
|
||||||
the longest match is selected.
|
|
||||||
|
|
||||||
The hash chains are searched starting with the most recent strings, to
|
|
||||||
favor small distances and thus take advantage of the Huffman encoding.
|
|
||||||
The hash chains are singly linked. There are no deletions from the
|
|
||||||
hash chains, the algorithm simply discards matches that are too old.
|
|
||||||
|
|
||||||
To avoid a worst-case situation, very long hash chains are arbitrarily
|
|
||||||
truncated at a certain length, determined by a runtime option (level
|
|
||||||
parameter of deflateInit). So deflate() does not always find the longest
|
|
||||||
possible match but generally finds a match which is long enough.
|
|
||||||
|
|
||||||
deflate() also defers the selection of matches with a lazy evaluation
|
|
||||||
mechanism. After a match of length N has been found, deflate() searches for
|
|
||||||
a longer match at the next input byte. If a longer match is found, the
|
|
||||||
previous match is truncated to a length of one (thus producing a single
|
|
||||||
literal byte) and the process of lazy evaluation begins again. Otherwise,
|
|
||||||
the original match is kept, and the next match search is attempted only N
|
|
||||||
steps later.
|
|
||||||
|
|
||||||
The lazy match evaluation is also subject to a runtime parameter. If
|
|
||||||
the current match is long enough, deflate() reduces the search for a longer
|
|
||||||
match, thus speeding up the whole process. If compression ratio is more
|
|
||||||
important than speed, deflate() attempts a complete second search even if
|
|
||||||
the first match is already long enough.
|
|
||||||
|
|
||||||
The lazy match evaluation is not performed for the fastest compression
|
|
||||||
modes (level parameter 1 to 3). For these fast modes, new strings
|
|
||||||
are inserted in the hash table only when no match was found, or
|
|
||||||
when the match is not too long. This degrades the compression ratio
|
|
||||||
but saves time since there are both fewer insertions and fewer searches.
|
|
||||||
|
|
||||||
|
|
||||||
2. Decompression algorithm (inflate)
|
|
||||||
|
|
||||||
2.1 Introduction
|
|
||||||
|
|
||||||
The key question is how to represent a Huffman code (or any prefix code) so
|
|
||||||
that you can decode fast. The most important characteristic is that shorter
|
|
||||||
codes are much more common than longer codes, so pay attention to decoding the
|
|
||||||
short codes fast, and let the long codes take longer to decode.
|
|
||||||
|
|
||||||
inflate() sets up a first level table that covers some number of bits of
|
|
||||||
input less than the length of longest code. It gets that many bits from the
|
|
||||||
stream, and looks it up in the table. The table will tell if the next
|
|
||||||
code is that many bits or less and how many, and if it is, it will tell
|
|
||||||
the value, else it will point to the next level table for which inflate()
|
|
||||||
grabs more bits and tries to decode a longer code.
|
|
||||||
|
|
||||||
How many bits to make the first lookup is a tradeoff between the time it
|
|
||||||
takes to decode and the time it takes to build the table. If building the
|
|
||||||
table took no time (and if you had infinite memory), then there would only
|
|
||||||
be a first level table to cover all the way to the longest code. However,
|
|
||||||
building the table ends up taking a lot longer for more bits since short
|
|
||||||
codes are replicated many times in such a table. What inflate() does is
|
|
||||||
simply to make the number of bits in the first table a variable, and then
|
|
||||||
to set that variable for the maximum speed.
|
|
||||||
|
|
||||||
For inflate, which has 286 possible codes for the literal/length tree, the size
|
|
||||||
of the first table is nine bits. Also the distance trees have 30 possible
|
|
||||||
values, and the size of the first table is six bits. Note that for each of
|
|
||||||
those cases, the table ended up one bit longer than the ``average'' code
|
|
||||||
length, i.e. the code length of an approximately flat code which would be a
|
|
||||||
little more than eight bits for 286 symbols and a little less than five bits
|
|
||||||
for 30 symbols.
|
|
||||||
|
|
||||||
|
|
||||||
2.2 More details on the inflate table lookup
|
|
||||||
|
|
||||||
Ok, you want to know what this cleverly obfuscated inflate tree actually
|
|
||||||
looks like. You are correct that it's not a Huffman tree. It is simply a
|
|
||||||
lookup table for the first, let's say, nine bits of a Huffman symbol. The
|
|
||||||
symbol could be as short as one bit or as long as 15 bits. If a particular
|
|
||||||
symbol is shorter than nine bits, then that symbol's translation is duplicated
|
|
||||||
in all those entries that start with that symbol's bits. For example, if the
|
|
||||||
symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a
|
|
||||||
symbol is nine bits long, it appears in the table once.
|
|
||||||
|
|
||||||
If the symbol is longer than nine bits, then that entry in the table points
|
|
||||||
to another similar table for the remaining bits. Again, there are duplicated
|
|
||||||
entries as needed. The idea is that most of the time the symbol will be short
|
|
||||||
and there will only be one table look up. (That's whole idea behind data
|
|
||||||
compression in the first place.) For the less frequent long symbols, there
|
|
||||||
will be two lookups. If you had a compression method with really long
|
|
||||||
symbols, you could have as many levels of lookups as is efficient. For
|
|
||||||
inflate, two is enough.
|
|
||||||
|
|
||||||
So a table entry either points to another table (in which case nine bits in
|
|
||||||
the above example are gobbled), or it contains the translation for the symbol
|
|
||||||
and the number of bits to gobble. Then you start again with the next
|
|
||||||
ungobbled bit.
|
|
||||||
|
|
||||||
You may wonder: why not just have one lookup table for how ever many bits the
|
|
||||||
longest symbol is? The reason is that if you do that, you end up spending
|
|
||||||
more time filling in duplicate symbol entries than you do actually decoding.
|
|
||||||
At least for deflate's output that generates new trees every several 10's of
|
|
||||||
kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code
|
|
||||||
would take too long if you're only decoding several thousand symbols. At the
|
|
||||||
other extreme, you could make a new table for every bit in the code. In fact,
|
|
||||||
that's essentially a Huffman tree. But then you spend too much time
|
|
||||||
traversing the tree while decoding, even for short symbols.
|
|
||||||
|
|
||||||
So the number of bits for the first lookup table is a trade of the time to
|
|
||||||
fill out the table vs. the time spent looking at the second level and above of
|
|
||||||
the table.
|
|
||||||
|
|
||||||
Here is an example, scaled down:
|
|
||||||
|
|
||||||
The code being decoded, with 10 symbols, from 1 to 6 bits long:
|
|
||||||
|
|
||||||
A: 0
|
|
||||||
B: 10
|
|
||||||
C: 1100
|
|
||||||
D: 11010
|
|
||||||
E: 11011
|
|
||||||
F: 11100
|
|
||||||
G: 11101
|
|
||||||
H: 11110
|
|
||||||
I: 111110
|
|
||||||
J: 111111
|
|
||||||
|
|
||||||
Let's make the first table three bits long (eight entries):
|
|
||||||
|
|
||||||
000: A,1
|
|
||||||
001: A,1
|
|
||||||
010: A,1
|
|
||||||
011: A,1
|
|
||||||
100: B,2
|
|
||||||
101: B,2
|
|
||||||
110: -> table X (gobble 3 bits)
|
|
||||||
111: -> table Y (gobble 3 bits)
|
|
||||||
|
|
||||||
Each entry is what the bits decode as and how many bits that is, i.e. how
|
|
||||||
many bits to gobble. Or the entry points to another table, with the number of
|
|
||||||
bits to gobble implicit in the size of the table.
|
|
||||||
|
|
||||||
Table X is two bits long since the longest code starting with 110 is five bits
|
|
||||||
long:
|
|
||||||
|
|
||||||
00: C,1
|
|
||||||
01: C,1
|
|
||||||
10: D,2
|
|
||||||
11: E,2
|
|
||||||
|
|
||||||
Table Y is three bits long since the longest code starting with 111 is six
|
|
||||||
bits long:
|
|
||||||
|
|
||||||
000: F,2
|
|
||||||
001: F,2
|
|
||||||
010: G,2
|
|
||||||
011: G,2
|
|
||||||
100: H,2
|
|
||||||
101: H,2
|
|
||||||
110: I,3
|
|
||||||
111: J,3
|
|
||||||
|
|
||||||
So what we have here are three tables with a total of 20 entries that had to
|
|
||||||
be constructed. That's compared to 64 entries for a single table. Or
|
|
||||||
compared to 16 entries for a Huffman tree (six two entry tables and one four
|
|
||||||
entry table). Assuming that the code ideally represents the probability of
|
|
||||||
the symbols, it takes on the average 1.25 lookups per symbol. That's compared
|
|
||||||
to one lookup for the single table, or 1.66 lookups per symbol for the
|
|
||||||
Huffman tree.
|
|
||||||
|
|
||||||
There, I think that gives you a picture of what's going on. For inflate, the
|
|
||||||
meaning of a particular symbol is often more than just a letter. It can be a
|
|
||||||
byte (a "literal"), or it can be either a length or a distance which
|
|
||||||
indicates a base value and a number of bits to fetch after the code that is
|
|
||||||
added to the base value. Or it might be the special end-of-block code. The
|
|
||||||
data structures created in inftrees.c try to encode all that information
|
|
||||||
compactly in the tables.
|
|
||||||
|
|
||||||
|
|
||||||
Jean-loup Gailly Mark Adler
|
|
||||||
jloup@gzip.org madler@alumni.caltech.edu
|
|
||||||
|
|
||||||
|
|
||||||
References:
|
|
||||||
|
|
||||||
[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data
|
|
||||||
Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3,
|
|
||||||
pp. 337-343.
|
|
||||||
|
|
||||||
``DEFLATE Compressed Data Format Specification'' available in
|
|
||||||
http://tools.ietf.org/html/rfc1951
|
|
@ -1,619 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Network Working Group P. Deutsch
|
|
||||||
Request for Comments: 1950 Aladdin Enterprises
|
|
||||||
Category: Informational J-L. Gailly
|
|
||||||
Info-ZIP
|
|
||||||
May 1996
|
|
||||||
|
|
||||||
|
|
||||||
ZLIB Compressed Data Format Specification version 3.3
|
|
||||||
|
|
||||||
Status of This Memo
|
|
||||||
|
|
||||||
This memo provides information for the Internet community. This memo
|
|
||||||
does not specify an Internet standard of any kind. Distribution of
|
|
||||||
this memo is unlimited.
|
|
||||||
|
|
||||||
IESG Note:
|
|
||||||
|
|
||||||
The IESG takes no position on the validity of any Intellectual
|
|
||||||
Property Rights statements contained in this document.
|
|
||||||
|
|
||||||
Notices
|
|
||||||
|
|
||||||
Copyright (c) 1996 L. Peter Deutsch and Jean-Loup Gailly
|
|
||||||
|
|
||||||
Permission is granted to copy and distribute this document for any
|
|
||||||
purpose and without charge, including translations into other
|
|
||||||
languages and incorporation into compilations, provided that the
|
|
||||||
copyright notice and this notice are preserved, and that any
|
|
||||||
substantive changes or deletions from the original are clearly
|
|
||||||
marked.
|
|
||||||
|
|
||||||
A pointer to the latest version of this and related documentation in
|
|
||||||
HTML format can be found at the URL
|
|
||||||
<ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html>.
|
|
||||||
|
|
||||||
Abstract
|
|
||||||
|
|
||||||
This specification defines a lossless compressed data format. The
|
|
||||||
data can be produced or consumed, even for an arbitrarily long
|
|
||||||
sequentially presented input data stream, using only an a priori
|
|
||||||
bounded amount of intermediate storage. The format presently uses
|
|
||||||
the DEFLATE compression method but can be easily extended to use
|
|
||||||
other compression methods. It can be implemented readily in a manner
|
|
||||||
not covered by patents. This specification also defines the ADLER-32
|
|
||||||
checksum (an extension and improvement of the Fletcher checksum),
|
|
||||||
used for detection of data corruption, and provides an algorithm for
|
|
||||||
computing it.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch & Gailly Informational [Page 1]
|
|
||||||
|
|
||||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
Table of Contents
|
|
||||||
|
|
||||||
1. Introduction ................................................... 2
|
|
||||||
1.1. Purpose ................................................... 2
|
|
||||||
1.2. Intended audience ......................................... 3
|
|
||||||
1.3. Scope ..................................................... 3
|
|
||||||
1.4. Compliance ................................................ 3
|
|
||||||
1.5. Definitions of terms and conventions used ................ 3
|
|
||||||
1.6. Changes from previous versions ............................ 3
|
|
||||||
2. Detailed specification ......................................... 3
|
|
||||||
2.1. Overall conventions ....................................... 3
|
|
||||||
2.2. Data format ............................................... 4
|
|
||||||
2.3. Compliance ................................................ 7
|
|
||||||
3. References ..................................................... 7
|
|
||||||
4. Source code .................................................... 8
|
|
||||||
5. Security Considerations ........................................ 8
|
|
||||||
6. Acknowledgements ............................................... 8
|
|
||||||
7. Authors' Addresses ............................................. 8
|
|
||||||
8. Appendix: Rationale ............................................ 9
|
|
||||||
9. Appendix: Sample code ..........................................10
|
|
||||||
|
|
||||||
1. Introduction
|
|
||||||
|
|
||||||
1.1. Purpose
|
|
||||||
|
|
||||||
The purpose of this specification is to define a lossless
|
|
||||||
compressed data format that:
|
|
||||||
|
|
||||||
* Is independent of CPU type, operating system, file system,
|
|
||||||
and character set, and hence can be used for interchange;
|
|
||||||
|
|
||||||
* Can be produced or consumed, even for an arbitrarily long
|
|
||||||
sequentially presented input data stream, using only an a
|
|
||||||
priori bounded amount of intermediate storage, and hence can
|
|
||||||
be used in data communications or similar structures such as
|
|
||||||
Unix filters;
|
|
||||||
|
|
||||||
* Can use a number of different compression methods;
|
|
||||||
|
|
||||||
* Can be implemented readily in a manner not covered by
|
|
||||||
patents, and hence can be practiced freely.
|
|
||||||
|
|
||||||
The data format defined by this specification does not attempt to
|
|
||||||
allow random access to compressed data.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch & Gailly Informational [Page 2]
|
|
||||||
|
|
||||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
1.2. Intended audience
|
|
||||||
|
|
||||||
This specification is intended for use by implementors of software
|
|
||||||
to compress data into zlib format and/or decompress data from zlib
|
|
||||||
format.
|
|
||||||
|
|
||||||
The text of the specification assumes a basic background in
|
|
||||||
programming at the level of bits and other primitive data
|
|
||||||
representations.
|
|
||||||
|
|
||||||
1.3. Scope
|
|
||||||
|
|
||||||
The specification specifies a compressed data format that can be
|
|
||||||
used for in-memory compression of a sequence of arbitrary bytes.
|
|
||||||
|
|
||||||
1.4. Compliance
|
|
||||||
|
|
||||||
Unless otherwise indicated below, a compliant decompressor must be
|
|
||||||
able to accept and decompress any data set that conforms to all
|
|
||||||
the specifications presented here; a compliant compressor must
|
|
||||||
produce data sets that conform to all the specifications presented
|
|
||||||
here.
|
|
||||||
|
|
||||||
1.5. Definitions of terms and conventions used
|
|
||||||
|
|
||||||
byte: 8 bits stored or transmitted as a unit (same as an octet).
|
|
||||||
(For this specification, a byte is exactly 8 bits, even on
|
|
||||||
machines which store a character on a number of bits different
|
|
||||||
from 8.) See below, for the numbering of bits within a byte.
|
|
||||||
|
|
||||||
1.6. Changes from previous versions
|
|
||||||
|
|
||||||
Version 3.1 was the first public release of this specification.
|
|
||||||
In version 3.2, some terminology was changed and the Adler-32
|
|
||||||
sample code was rewritten for clarity. In version 3.3, the
|
|
||||||
support for a preset dictionary was introduced, and the
|
|
||||||
specification was converted to RFC style.
|
|
||||||
|
|
||||||
2. Detailed specification
|
|
||||||
|
|
||||||
2.1. Overall conventions
|
|
||||||
|
|
||||||
In the diagrams below, a box like this:
|
|
||||||
|
|
||||||
+---+
|
|
||||||
| | <-- the vertical bars might be missing
|
|
||||||
+---+
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch & Gailly Informational [Page 3]
|
|
||||||
|
|
||||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
represents one byte; a box like this:
|
|
||||||
|
|
||||||
+==============+
|
|
||||||
| |
|
|
||||||
+==============+
|
|
||||||
|
|
||||||
represents a variable number of bytes.
|
|
||||||
|
|
||||||
Bytes stored within a computer do not have a "bit order", since
|
|
||||||
they are always treated as a unit. However, a byte considered as
|
|
||||||
an integer between 0 and 255 does have a most- and least-
|
|
||||||
significant bit, and since we write numbers with the most-
|
|
||||||
significant digit on the left, we also write bytes with the most-
|
|
||||||
significant bit on the left. In the diagrams below, we number the
|
|
||||||
bits of a byte so that bit 0 is the least-significant bit, i.e.,
|
|
||||||
the bits are numbered:
|
|
||||||
|
|
||||||
+--------+
|
|
||||||
|76543210|
|
|
||||||
+--------+
|
|
||||||
|
|
||||||
Within a computer, a number may occupy multiple bytes. All
|
|
||||||
multi-byte numbers in the format described here are stored with
|
|
||||||
the MOST-significant byte first (at the lower memory address).
|
|
||||||
For example, the decimal number 520 is stored as:
|
|
||||||
|
|
||||||
0 1
|
|
||||||
+--------+--------+
|
|
||||||
|00000010|00001000|
|
|
||||||
+--------+--------+
|
|
||||||
^ ^
|
|
||||||
| |
|
|
||||||
| + less significant byte = 8
|
|
||||||
+ more significant byte = 2 x 256
|
|
||||||
|
|
||||||
2.2. Data format
|
|
||||||
|
|
||||||
A zlib stream has the following structure:
|
|
||||||
|
|
||||||
0 1
|
|
||||||
+---+---+
|
|
||||||
|CMF|FLG| (more-->)
|
|
||||||
+---+---+
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch & Gailly Informational [Page 4]
|
|
||||||
|
|
||||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
(if FLG.FDICT set)
|
|
||||||
|
|
||||||
0 1 2 3
|
|
||||||
+---+---+---+---+
|
|
||||||
| DICTID | (more-->)
|
|
||||||
+---+---+---+---+
|
|
||||||
|
|
||||||
+=====================+---+---+---+---+
|
|
||||||
|...compressed data...| ADLER32 |
|
|
||||||
+=====================+---+---+---+---+
|
|
||||||
|
|
||||||
Any data which may appear after ADLER32 are not part of the zlib
|
|
||||||
stream.
|
|
||||||
|
|
||||||
CMF (Compression Method and flags)
|
|
||||||
This byte is divided into a 4-bit compression method and a 4-
|
|
||||||
bit information field depending on the compression method.
|
|
||||||
|
|
||||||
bits 0 to 3 CM Compression method
|
|
||||||
bits 4 to 7 CINFO Compression info
|
|
||||||
|
|
||||||
CM (Compression method)
|
|
||||||
This identifies the compression method used in the file. CM = 8
|
|
||||||
denotes the "deflate" compression method with a window size up
|
|
||||||
to 32K. This is the method used by gzip and PNG (see
|
|
||||||
references [1] and [2] in Chapter 3, below, for the reference
|
|
||||||
documents). CM = 15 is reserved. It might be used in a future
|
|
||||||
version of this specification to indicate the presence of an
|
|
||||||
extra field before the compressed data.
|
|
||||||
|
|
||||||
CINFO (Compression info)
|
|
||||||
For CM = 8, CINFO is the base-2 logarithm of the LZ77 window
|
|
||||||
size, minus eight (CINFO=7 indicates a 32K window size). Values
|
|
||||||
of CINFO above 7 are not allowed in this version of the
|
|
||||||
specification. CINFO is not defined in this specification for
|
|
||||||
CM not equal to 8.
|
|
||||||
|
|
||||||
FLG (FLaGs)
|
|
||||||
This flag byte is divided as follows:
|
|
||||||
|
|
||||||
bits 0 to 4 FCHECK (check bits for CMF and FLG)
|
|
||||||
bit 5 FDICT (preset dictionary)
|
|
||||||
bits 6 to 7 FLEVEL (compression level)
|
|
||||||
|
|
||||||
The FCHECK value must be such that CMF and FLG, when viewed as
|
|
||||||
a 16-bit unsigned integer stored in MSB order (CMF*256 + FLG),
|
|
||||||
is a multiple of 31.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch & Gailly Informational [Page 5]
|
|
||||||
|
|
||||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
FDICT (Preset dictionary)
|
|
||||||
If FDICT is set, a DICT dictionary identifier is present
|
|
||||||
immediately after the FLG byte. The dictionary is a sequence of
|
|
||||||
bytes which are initially fed to the compressor without
|
|
||||||
producing any compressed output. DICT is the Adler-32 checksum
|
|
||||||
of this sequence of bytes (see the definition of ADLER32
|
|
||||||
below). The decompressor can use this identifier to determine
|
|
||||||
which dictionary has been used by the compressor.
|
|
||||||
|
|
||||||
FLEVEL (Compression level)
|
|
||||||
These flags are available for use by specific compression
|
|
||||||
methods. The "deflate" method (CM = 8) sets these flags as
|
|
||||||
follows:
|
|
||||||
|
|
||||||
0 - compressor used fastest algorithm
|
|
||||||
1 - compressor used fast algorithm
|
|
||||||
2 - compressor used default algorithm
|
|
||||||
3 - compressor used maximum compression, slowest algorithm
|
|
||||||
|
|
||||||
The information in FLEVEL is not needed for decompression; it
|
|
||||||
is there to indicate if recompression might be worthwhile.
|
|
||||||
|
|
||||||
compressed data
|
|
||||||
For compression method 8, the compressed data is stored in the
|
|
||||||
deflate compressed data format as described in the document
|
|
||||||
"DEFLATE Compressed Data Format Specification" by L. Peter
|
|
||||||
Deutsch. (See reference [3] in Chapter 3, below)
|
|
||||||
|
|
||||||
Other compressed data formats are not specified in this version
|
|
||||||
of the zlib specification.
|
|
||||||
|
|
||||||
ADLER32 (Adler-32 checksum)
|
|
||||||
This contains a checksum value of the uncompressed data
|
|
||||||
(excluding any dictionary data) computed according to Adler-32
|
|
||||||
algorithm. This algorithm is a 32-bit extension and improvement
|
|
||||||
of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073
|
|
||||||
standard. See references [4] and [5] in Chapter 3, below)
|
|
||||||
|
|
||||||
Adler-32 is composed of two sums accumulated per byte: s1 is
|
|
||||||
the sum of all bytes, s2 is the sum of all s1 values. Both sums
|
|
||||||
are done modulo 65521. s1 is initialized to 1, s2 to zero. The
|
|
||||||
Adler-32 checksum is stored as s2*65536 + s1 in most-
|
|
||||||
significant-byte first (network) order.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch & Gailly Informational [Page 6]
|
|
||||||
|
|
||||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
2.3. Compliance
|
|
||||||
|
|
||||||
A compliant compressor must produce streams with correct CMF, FLG
|
|
||||||
and ADLER32, but need not support preset dictionaries. When the
|
|
||||||
zlib data format is used as part of another standard data format,
|
|
||||||
the compressor may use only preset dictionaries that are specified
|
|
||||||
by this other data format. If this other format does not use the
|
|
||||||
preset dictionary feature, the compressor must not set the FDICT
|
|
||||||
flag.
|
|
||||||
|
|
||||||
A compliant decompressor must check CMF, FLG, and ADLER32, and
|
|
||||||
provide an error indication if any of these have incorrect values.
|
|
||||||
A compliant decompressor must give an error indication if CM is
|
|
||||||
not one of the values defined in this specification (only the
|
|
||||||
value 8 is permitted in this version), since another value could
|
|
||||||
indicate the presence of new features that would cause subsequent
|
|
||||||
data to be interpreted incorrectly. A compliant decompressor must
|
|
||||||
give an error indication if FDICT is set and DICTID is not the
|
|
||||||
identifier of a known preset dictionary. A decompressor may
|
|
||||||
ignore FLEVEL and still be compliant. When the zlib data format
|
|
||||||
is being used as a part of another standard format, a compliant
|
|
||||||
decompressor must support all the preset dictionaries specified by
|
|
||||||
the other format. When the other format does not use the preset
|
|
||||||
dictionary feature, a compliant decompressor must reject any
|
|
||||||
stream in which the FDICT flag is set.
|
|
||||||
|
|
||||||
3. References
|
|
||||||
|
|
||||||
[1] Deutsch, L.P.,"GZIP Compressed Data Format Specification",
|
|
||||||
available in ftp://ftp.uu.net/pub/archiving/zip/doc/
|
|
||||||
|
|
||||||
[2] Thomas Boutell, "PNG (Portable Network Graphics) specification",
|
|
||||||
available in ftp://ftp.uu.net/graphics/png/documents/
|
|
||||||
|
|
||||||
[3] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification",
|
|
||||||
available in ftp://ftp.uu.net/pub/archiving/zip/doc/
|
|
||||||
|
|
||||||
[4] Fletcher, J. G., "An Arithmetic Checksum for Serial
|
|
||||||
Transmissions," IEEE Transactions on Communications, Vol. COM-30,
|
|
||||||
No. 1, January 1982, pp. 247-252.
|
|
||||||
|
|
||||||
[5] ITU-T Recommendation X.224, Annex D, "Checksum Algorithms,"
|
|
||||||
November, 1993, pp. 144, 145. (Available from
|
|
||||||
gopher://info.itu.ch). ITU-T X.244 is also the same as ISO 8073.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch & Gailly Informational [Page 7]
|
|
||||||
|
|
||||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
4. Source code
|
|
||||||
|
|
||||||
Source code for a C language implementation of a "zlib" compliant
|
|
||||||
library is available at ftp://ftp.uu.net/pub/archiving/zip/zlib/.
|
|
||||||
|
|
||||||
5. Security Considerations
|
|
||||||
|
|
||||||
A decoder that fails to check the ADLER32 checksum value may be
|
|
||||||
subject to undetected data corruption.
|
|
||||||
|
|
||||||
6. Acknowledgements
|
|
||||||
|
|
||||||
Trademarks cited in this document are the property of their
|
|
||||||
respective owners.
|
|
||||||
|
|
||||||
Jean-Loup Gailly and Mark Adler designed the zlib format and wrote
|
|
||||||
the related software described in this specification. Glenn
|
|
||||||
Randers-Pehrson converted this document to RFC and HTML format.
|
|
||||||
|
|
||||||
7. Authors' Addresses
|
|
||||||
|
|
||||||
L. Peter Deutsch
|
|
||||||
Aladdin Enterprises
|
|
||||||
203 Santa Margarita Ave.
|
|
||||||
Menlo Park, CA 94025
|
|
||||||
|
|
||||||
Phone: (415) 322-0103 (AM only)
|
|
||||||
FAX: (415) 322-1734
|
|
||||||
EMail: <ghost@aladdin.com>
|
|
||||||
|
|
||||||
|
|
||||||
Jean-Loup Gailly
|
|
||||||
|
|
||||||
EMail: <gzip@prep.ai.mit.edu>
|
|
||||||
|
|
||||||
Questions about the technical content of this specification can be
|
|
||||||
sent by email to
|
|
||||||
|
|
||||||
Jean-Loup Gailly <gzip@prep.ai.mit.edu> and
|
|
||||||
Mark Adler <madler@alumni.caltech.edu>
|
|
||||||
|
|
||||||
Editorial comments on this specification can be sent by email to
|
|
||||||
|
|
||||||
L. Peter Deutsch <ghost@aladdin.com> and
|
|
||||||
Glenn Randers-Pehrson <randeg@alumni.rpi.edu>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch & Gailly Informational [Page 8]
|
|
||||||
|
|
||||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
8. Appendix: Rationale
|
|
||||||
|
|
||||||
8.1. Preset dictionaries
|
|
||||||
|
|
||||||
A preset dictionary is specially useful to compress short input
|
|
||||||
sequences. The compressor can take advantage of the dictionary
|
|
||||||
context to encode the input in a more compact manner. The
|
|
||||||
decompressor can be initialized with the appropriate context by
|
|
||||||
virtually decompressing a compressed version of the dictionary
|
|
||||||
without producing any output. However for certain compression
|
|
||||||
algorithms such as the deflate algorithm this operation can be
|
|
||||||
achieved without actually performing any decompression.
|
|
||||||
|
|
||||||
The compressor and the decompressor must use exactly the same
|
|
||||||
dictionary. The dictionary may be fixed or may be chosen among a
|
|
||||||
certain number of predefined dictionaries, according to the kind
|
|
||||||
of input data. The decompressor can determine which dictionary has
|
|
||||||
been chosen by the compressor by checking the dictionary
|
|
||||||
identifier. This document does not specify the contents of
|
|
||||||
predefined dictionaries, since the optimal dictionaries are
|
|
||||||
application specific. Standard data formats using this feature of
|
|
||||||
the zlib specification must precisely define the allowed
|
|
||||||
dictionaries.
|
|
||||||
|
|
||||||
8.2. The Adler-32 algorithm
|
|
||||||
|
|
||||||
The Adler-32 algorithm is much faster than the CRC32 algorithm yet
|
|
||||||
still provides an extremely low probability of undetected errors.
|
|
||||||
|
|
||||||
The modulo on unsigned long accumulators can be delayed for 5552
|
|
||||||
bytes, so the modulo operation time is negligible. If the bytes
|
|
||||||
are a, b, c, the second sum is 3a + 2b + c + 3, and so is position
|
|
||||||
and order sensitive, unlike the first sum, which is just a
|
|
||||||
checksum. That 65521 is prime is important to avoid a possible
|
|
||||||
large class of two-byte errors that leave the check unchanged.
|
|
||||||
(The Fletcher checksum uses 255, which is not prime and which also
|
|
||||||
makes the Fletcher check insensitive to single byte changes 0 <->
|
|
||||||
255.)
|
|
||||||
|
|
||||||
The sum s1 is initialized to 1 instead of zero to make the length
|
|
||||||
of the sequence part of s2, so that the length does not have to be
|
|
||||||
checked separately. (Any sequence of zeroes has a Fletcher
|
|
||||||
checksum of zero.)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch & Gailly Informational [Page 9]
|
|
||||||
|
|
||||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
9. Appendix: Sample code
|
|
||||||
|
|
||||||
The following C code computes the Adler-32 checksum of a data buffer.
|
|
||||||
It is written for clarity, not for speed. The sample code is in the
|
|
||||||
ANSI C programming language. Non C users may find it easier to read
|
|
||||||
with these hints:
|
|
||||||
|
|
||||||
& Bitwise AND operator.
|
|
||||||
>> Bitwise right shift operator. When applied to an
|
|
||||||
unsigned quantity, as here, right shift inserts zero bit(s)
|
|
||||||
at the left.
|
|
||||||
<< Bitwise left shift operator. Left shift inserts zero
|
|
||||||
bit(s) at the right.
|
|
||||||
++ "n++" increments the variable n.
|
|
||||||
% modulo operator: a % b is the remainder of a divided by b.
|
|
||||||
|
|
||||||
#define BASE 65521 /* largest prime smaller than 65536 */
|
|
||||||
|
|
||||||
/*
|
|
||||||
Update a running Adler-32 checksum with the bytes buf[0..len-1]
|
|
||||||
and return the updated checksum. The Adler-32 checksum should be
|
|
||||||
initialized to 1.
|
|
||||||
|
|
||||||
Usage example:
|
|
||||||
|
|
||||||
unsigned long adler = 1L;
|
|
||||||
|
|
||||||
while (read_buffer(buffer, length) != EOF) {
|
|
||||||
adler = update_adler32(adler, buffer, length);
|
|
||||||
}
|
|
||||||
if (adler != original_adler) error();
|
|
||||||
*/
|
|
||||||
unsigned long update_adler32(unsigned long adler,
|
|
||||||
unsigned char *buf, int len)
|
|
||||||
{
|
|
||||||
unsigned long s1 = adler & 0xffff;
|
|
||||||
unsigned long s2 = (adler >> 16) & 0xffff;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
for (n = 0; n < len; n++) {
|
|
||||||
s1 = (s1 + buf[n]) % BASE;
|
|
||||||
s2 = (s2 + s1) % BASE;
|
|
||||||
}
|
|
||||||
return (s2 << 16) + s1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the adler32 of the bytes buf[0..len-1] */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch & Gailly Informational [Page 10]
|
|
||||||
|
|
||||||
RFC 1950 ZLIB Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
unsigned long adler32(unsigned char *buf, int len)
|
|
||||||
{
|
|
||||||
return update_adler32(1L, buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch & Gailly Informational [Page 11]
|
|
||||||
|
|
@ -1,955 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Network Working Group P. Deutsch
|
|
||||||
Request for Comments: 1951 Aladdin Enterprises
|
|
||||||
Category: Informational May 1996
|
|
||||||
|
|
||||||
|
|
||||||
DEFLATE Compressed Data Format Specification version 1.3
|
|
||||||
|
|
||||||
Status of This Memo
|
|
||||||
|
|
||||||
This memo provides information for the Internet community. This memo
|
|
||||||
does not specify an Internet standard of any kind. Distribution of
|
|
||||||
this memo is unlimited.
|
|
||||||
|
|
||||||
IESG Note:
|
|
||||||
|
|
||||||
The IESG takes no position on the validity of any Intellectual
|
|
||||||
Property Rights statements contained in this document.
|
|
||||||
|
|
||||||
Notices
|
|
||||||
|
|
||||||
Copyright (c) 1996 L. Peter Deutsch
|
|
||||||
|
|
||||||
Permission is granted to copy and distribute this document for any
|
|
||||||
purpose and without charge, including translations into other
|
|
||||||
languages and incorporation into compilations, provided that the
|
|
||||||
copyright notice and this notice are preserved, and that any
|
|
||||||
substantive changes or deletions from the original are clearly
|
|
||||||
marked.
|
|
||||||
|
|
||||||
A pointer to the latest version of this and related documentation in
|
|
||||||
HTML format can be found at the URL
|
|
||||||
<ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html>.
|
|
||||||
|
|
||||||
Abstract
|
|
||||||
|
|
||||||
This specification defines a lossless compressed data format that
|
|
||||||
compresses data using a combination of the LZ77 algorithm and Huffman
|
|
||||||
coding, with efficiency comparable to the best currently available
|
|
||||||
general-purpose compression methods. The data can be produced or
|
|
||||||
consumed, even for an arbitrarily long sequentially presented input
|
|
||||||
data stream, using only an a priori bounded amount of intermediate
|
|
||||||
storage. The format can be implemented readily in a manner not
|
|
||||||
covered by patents.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 1]
|
|
||||||
|
|
||||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
Table of Contents
|
|
||||||
|
|
||||||
1. Introduction ................................................... 2
|
|
||||||
1.1. Purpose ................................................... 2
|
|
||||||
1.2. Intended audience ......................................... 3
|
|
||||||
1.3. Scope ..................................................... 3
|
|
||||||
1.4. Compliance ................................................ 3
|
|
||||||
1.5. Definitions of terms and conventions used ................ 3
|
|
||||||
1.6. Changes from previous versions ............................ 4
|
|
||||||
2. Compressed representation overview ............................. 4
|
|
||||||
3. Detailed specification ......................................... 5
|
|
||||||
3.1. Overall conventions ....................................... 5
|
|
||||||
3.1.1. Packing into bytes .................................. 5
|
|
||||||
3.2. Compressed block format ................................... 6
|
|
||||||
3.2.1. Synopsis of prefix and Huffman coding ............... 6
|
|
||||||
3.2.2. Use of Huffman coding in the "deflate" format ....... 7
|
|
||||||
3.2.3. Details of block format ............................. 9
|
|
||||||
3.2.4. Non-compressed blocks (BTYPE=00) ................... 11
|
|
||||||
3.2.5. Compressed blocks (length and distance codes) ...... 11
|
|
||||||
3.2.6. Compression with fixed Huffman codes (BTYPE=01) .... 12
|
|
||||||
3.2.7. Compression with dynamic Huffman codes (BTYPE=10) .. 13
|
|
||||||
3.3. Compliance ............................................... 14
|
|
||||||
4. Compression algorithm details ................................. 14
|
|
||||||
5. References .................................................... 16
|
|
||||||
6. Security Considerations ....................................... 16
|
|
||||||
7. Source code ................................................... 16
|
|
||||||
8. Acknowledgements .............................................. 16
|
|
||||||
9. Author's Address .............................................. 17
|
|
||||||
|
|
||||||
1. Introduction
|
|
||||||
|
|
||||||
1.1. Purpose
|
|
||||||
|
|
||||||
The purpose of this specification is to define a lossless
|
|
||||||
compressed data format that:
|
|
||||||
* Is independent of CPU type, operating system, file system,
|
|
||||||
and character set, and hence can be used for interchange;
|
|
||||||
* Can be produced or consumed, even for an arbitrarily long
|
|
||||||
sequentially presented input data stream, using only an a
|
|
||||||
priori bounded amount of intermediate storage, and hence
|
|
||||||
can be used in data communications or similar structures
|
|
||||||
such as Unix filters;
|
|
||||||
* Compresses data with efficiency comparable to the best
|
|
||||||
currently available general-purpose compression methods,
|
|
||||||
and in particular considerably better than the "compress"
|
|
||||||
program;
|
|
||||||
* Can be implemented readily in a manner not covered by
|
|
||||||
patents, and hence can be practiced freely;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 2]
|
|
||||||
|
|
||||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
* Is compatible with the file format produced by the current
|
|
||||||
widely used gzip utility, in that conforming decompressors
|
|
||||||
will be able to read data produced by the existing gzip
|
|
||||||
compressor.
|
|
||||||
|
|
||||||
The data format defined by this specification does not attempt to:
|
|
||||||
|
|
||||||
* Allow random access to compressed data;
|
|
||||||
* Compress specialized data (e.g., raster graphics) as well
|
|
||||||
as the best currently available specialized algorithms.
|
|
||||||
|
|
||||||
A simple counting argument shows that no lossless compression
|
|
||||||
algorithm can compress every possible input data set. For the
|
|
||||||
format defined here, the worst case expansion is 5 bytes per 32K-
|
|
||||||
byte block, i.e., a size increase of 0.015% for large data sets.
|
|
||||||
English text usually compresses by a factor of 2.5 to 3;
|
|
||||||
executable files usually compress somewhat less; graphical data
|
|
||||||
such as raster images may compress much more.
|
|
||||||
|
|
||||||
1.2. Intended audience
|
|
||||||
|
|
||||||
This specification is intended for use by implementors of software
|
|
||||||
to compress data into "deflate" format and/or decompress data from
|
|
||||||
"deflate" format.
|
|
||||||
|
|
||||||
The text of the specification assumes a basic background in
|
|
||||||
programming at the level of bits and other primitive data
|
|
||||||
representations. Familiarity with the technique of Huffman coding
|
|
||||||
is helpful but not required.
|
|
||||||
|
|
||||||
1.3. Scope
|
|
||||||
|
|
||||||
The specification specifies a method for representing a sequence
|
|
||||||
of bytes as a (usually shorter) sequence of bits, and a method for
|
|
||||||
packing the latter bit sequence into bytes.
|
|
||||||
|
|
||||||
1.4. Compliance
|
|
||||||
|
|
||||||
Unless otherwise indicated below, a compliant decompressor must be
|
|
||||||
able to accept and decompress any data set that conforms to all
|
|
||||||
the specifications presented here; a compliant compressor must
|
|
||||||
produce data sets that conform to all the specifications presented
|
|
||||||
here.
|
|
||||||
|
|
||||||
1.5. Definitions of terms and conventions used
|
|
||||||
|
|
||||||
Byte: 8 bits stored or transmitted as a unit (same as an octet).
|
|
||||||
For this specification, a byte is exactly 8 bits, even on machines
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 3]
|
|
||||||
|
|
||||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
which store a character on a number of bits different from eight.
|
|
||||||
See below, for the numbering of bits within a byte.
|
|
||||||
|
|
||||||
String: a sequence of arbitrary bytes.
|
|
||||||
|
|
||||||
1.6. Changes from previous versions
|
|
||||||
|
|
||||||
There have been no technical changes to the deflate format since
|
|
||||||
version 1.1 of this specification. In version 1.2, some
|
|
||||||
terminology was changed. Version 1.3 is a conversion of the
|
|
||||||
specification to RFC style.
|
|
||||||
|
|
||||||
2. Compressed representation overview
|
|
||||||
|
|
||||||
A compressed data set consists of a series of blocks, corresponding
|
|
||||||
to successive blocks of input data. The block sizes are arbitrary,
|
|
||||||
except that non-compressible blocks are limited to 65,535 bytes.
|
|
||||||
|
|
||||||
Each block is compressed using a combination of the LZ77 algorithm
|
|
||||||
and Huffman coding. The Huffman trees for each block are independent
|
|
||||||
of those for previous or subsequent blocks; the LZ77 algorithm may
|
|
||||||
use a reference to a duplicated string occurring in a previous block,
|
|
||||||
up to 32K input bytes before.
|
|
||||||
|
|
||||||
Each block consists of two parts: a pair of Huffman code trees that
|
|
||||||
describe the representation of the compressed data part, and a
|
|
||||||
compressed data part. (The Huffman trees themselves are compressed
|
|
||||||
using Huffman encoding.) The compressed data consists of a series of
|
|
||||||
elements of two types: literal bytes (of strings that have not been
|
|
||||||
detected as duplicated within the previous 32K input bytes), and
|
|
||||||
pointers to duplicated strings, where a pointer is represented as a
|
|
||||||
pair <length, backward distance>. The representation used in the
|
|
||||||
"deflate" format limits distances to 32K bytes and lengths to 258
|
|
||||||
bytes, but does not limit the size of a block, except for
|
|
||||||
uncompressible blocks, which are limited as noted above.
|
|
||||||
|
|
||||||
Each type of value (literals, distances, and lengths) in the
|
|
||||||
compressed data is represented using a Huffman code, using one code
|
|
||||||
tree for literals and lengths and a separate code tree for distances.
|
|
||||||
The code trees for each block appear in a compact form just before
|
|
||||||
the compressed data for that block.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 4]
|
|
||||||
|
|
||||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
3. Detailed specification
|
|
||||||
|
|
||||||
3.1. Overall conventions In the diagrams below, a box like this:
|
|
||||||
|
|
||||||
+---+
|
|
||||||
| | <-- the vertical bars might be missing
|
|
||||||
+---+
|
|
||||||
|
|
||||||
represents one byte; a box like this:
|
|
||||||
|
|
||||||
+==============+
|
|
||||||
| |
|
|
||||||
+==============+
|
|
||||||
|
|
||||||
represents a variable number of bytes.
|
|
||||||
|
|
||||||
Bytes stored within a computer do not have a "bit order", since
|
|
||||||
they are always treated as a unit. However, a byte considered as
|
|
||||||
an integer between 0 and 255 does have a most- and least-
|
|
||||||
significant bit, and since we write numbers with the most-
|
|
||||||
significant digit on the left, we also write bytes with the most-
|
|
||||||
significant bit on the left. In the diagrams below, we number the
|
|
||||||
bits of a byte so that bit 0 is the least-significant bit, i.e.,
|
|
||||||
the bits are numbered:
|
|
||||||
|
|
||||||
+--------+
|
|
||||||
|76543210|
|
|
||||||
+--------+
|
|
||||||
|
|
||||||
Within a computer, a number may occupy multiple bytes. All
|
|
||||||
multi-byte numbers in the format described here are stored with
|
|
||||||
the least-significant byte first (at the lower memory address).
|
|
||||||
For example, the decimal number 520 is stored as:
|
|
||||||
|
|
||||||
0 1
|
|
||||||
+--------+--------+
|
|
||||||
|00001000|00000010|
|
|
||||||
+--------+--------+
|
|
||||||
^ ^
|
|
||||||
| |
|
|
||||||
| + more significant byte = 2 x 256
|
|
||||||
+ less significant byte = 8
|
|
||||||
|
|
||||||
3.1.1. Packing into bytes
|
|
||||||
|
|
||||||
This document does not address the issue of the order in which
|
|
||||||
bits of a byte are transmitted on a bit-sequential medium,
|
|
||||||
since the final data format described here is byte- rather than
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 5]
|
|
||||||
|
|
||||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
bit-oriented. However, we describe the compressed block format
|
|
||||||
in below, as a sequence of data elements of various bit
|
|
||||||
lengths, not a sequence of bytes. We must therefore specify
|
|
||||||
how to pack these data elements into bytes to form the final
|
|
||||||
compressed byte sequence:
|
|
||||||
|
|
||||||
* Data elements are packed into bytes in order of
|
|
||||||
increasing bit number within the byte, i.e., starting
|
|
||||||
with the least-significant bit of the byte.
|
|
||||||
* Data elements other than Huffman codes are packed
|
|
||||||
starting with the least-significant bit of the data
|
|
||||||
element.
|
|
||||||
* Huffman codes are packed starting with the most-
|
|
||||||
significant bit of the code.
|
|
||||||
|
|
||||||
In other words, if one were to print out the compressed data as
|
|
||||||
a sequence of bytes, starting with the first byte at the
|
|
||||||
*right* margin and proceeding to the *left*, with the most-
|
|
||||||
significant bit of each byte on the left as usual, one would be
|
|
||||||
able to parse the result from right to left, with fixed-width
|
|
||||||
elements in the correct MSB-to-LSB order and Huffman codes in
|
|
||||||
bit-reversed order (i.e., with the first bit of the code in the
|
|
||||||
relative LSB position).
|
|
||||||
|
|
||||||
3.2. Compressed block format
|
|
||||||
|
|
||||||
3.2.1. Synopsis of prefix and Huffman coding
|
|
||||||
|
|
||||||
Prefix coding represents symbols from an a priori known
|
|
||||||
alphabet by bit sequences (codes), one code for each symbol, in
|
|
||||||
a manner such that different symbols may be represented by bit
|
|
||||||
sequences of different lengths, but a parser can always parse
|
|
||||||
an encoded string unambiguously symbol-by-symbol.
|
|
||||||
|
|
||||||
We define a prefix code in terms of a binary tree in which the
|
|
||||||
two edges descending from each non-leaf node are labeled 0 and
|
|
||||||
1 and in which the leaf nodes correspond one-for-one with (are
|
|
||||||
labeled with) the symbols of the alphabet; then the code for a
|
|
||||||
symbol is the sequence of 0's and 1's on the edges leading from
|
|
||||||
the root to the leaf labeled with that symbol. For example:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 6]
|
|
||||||
|
|
||||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
/\ Symbol Code
|
|
||||||
0 1 ------ ----
|
|
||||||
/ \ A 00
|
|
||||||
/\ B B 1
|
|
||||||
0 1 C 011
|
|
||||||
/ \ D 010
|
|
||||||
A /\
|
|
||||||
0 1
|
|
||||||
/ \
|
|
||||||
D C
|
|
||||||
|
|
||||||
A parser can decode the next symbol from an encoded input
|
|
||||||
stream by walking down the tree from the root, at each step
|
|
||||||
choosing the edge corresponding to the next input bit.
|
|
||||||
|
|
||||||
Given an alphabet with known symbol frequencies, the Huffman
|
|
||||||
algorithm allows the construction of an optimal prefix code
|
|
||||||
(one which represents strings with those symbol frequencies
|
|
||||||
using the fewest bits of any possible prefix codes for that
|
|
||||||
alphabet). Such a code is called a Huffman code. (See
|
|
||||||
reference [1] in Chapter 5, references for additional
|
|
||||||
information on Huffman codes.)
|
|
||||||
|
|
||||||
Note that in the "deflate" format, the Huffman codes for the
|
|
||||||
various alphabets must not exceed certain maximum code lengths.
|
|
||||||
This constraint complicates the algorithm for computing code
|
|
||||||
lengths from symbol frequencies. Again, see Chapter 5,
|
|
||||||
references for details.
|
|
||||||
|
|
||||||
3.2.2. Use of Huffman coding in the "deflate" format
|
|
||||||
|
|
||||||
The Huffman codes used for each alphabet in the "deflate"
|
|
||||||
format have two additional rules:
|
|
||||||
|
|
||||||
* All codes of a given bit length have lexicographically
|
|
||||||
consecutive values, in the same order as the symbols
|
|
||||||
they represent;
|
|
||||||
|
|
||||||
* Shorter codes lexicographically precede longer codes.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 7]
|
|
||||||
|
|
||||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
We could recode the example above to follow this rule as
|
|
||||||
follows, assuming that the order of the alphabet is ABCD:
|
|
||||||
|
|
||||||
Symbol Code
|
|
||||||
------ ----
|
|
||||||
A 10
|
|
||||||
B 0
|
|
||||||
C 110
|
|
||||||
D 111
|
|
||||||
|
|
||||||
I.e., 0 precedes 10 which precedes 11x, and 110 and 111 are
|
|
||||||
lexicographically consecutive.
|
|
||||||
|
|
||||||
Given this rule, we can define the Huffman code for an alphabet
|
|
||||||
just by giving the bit lengths of the codes for each symbol of
|
|
||||||
the alphabet in order; this is sufficient to determine the
|
|
||||||
actual codes. In our example, the code is completely defined
|
|
||||||
by the sequence of bit lengths (2, 1, 3, 3). The following
|
|
||||||
algorithm generates the codes as integers, intended to be read
|
|
||||||
from most- to least-significant bit. The code lengths are
|
|
||||||
initially in tree[I].Len; the codes are produced in
|
|
||||||
tree[I].Code.
|
|
||||||
|
|
||||||
1) Count the number of codes for each code length. Let
|
|
||||||
bl_count[N] be the number of codes of length N, N >= 1.
|
|
||||||
|
|
||||||
2) Find the numerical value of the smallest code for each
|
|
||||||
code length:
|
|
||||||
|
|
||||||
code = 0;
|
|
||||||
bl_count[0] = 0;
|
|
||||||
for (bits = 1; bits <= MAX_BITS; bits++) {
|
|
||||||
code = (code + bl_count[bits-1]) << 1;
|
|
||||||
next_code[bits] = code;
|
|
||||||
}
|
|
||||||
|
|
||||||
3) Assign numerical values to all codes, using consecutive
|
|
||||||
values for all codes of the same length with the base
|
|
||||||
values determined at step 2. Codes that are never used
|
|
||||||
(which have a bit length of zero) must not be assigned a
|
|
||||||
value.
|
|
||||||
|
|
||||||
for (n = 0; n <= max_code; n++) {
|
|
||||||
len = tree[n].Len;
|
|
||||||
if (len != 0) {
|
|
||||||
tree[n].Code = next_code[len];
|
|
||||||
next_code[len]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 8]
|
|
||||||
|
|
||||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
Consider the alphabet ABCDEFGH, with bit lengths (3, 3, 3, 3,
|
|
||||||
3, 2, 4, 4). After step 1, we have:
|
|
||||||
|
|
||||||
N bl_count[N]
|
|
||||||
- -----------
|
|
||||||
2 1
|
|
||||||
3 5
|
|
||||||
4 2
|
|
||||||
|
|
||||||
Step 2 computes the following next_code values:
|
|
||||||
|
|
||||||
N next_code[N]
|
|
||||||
- ------------
|
|
||||||
1 0
|
|
||||||
2 0
|
|
||||||
3 2
|
|
||||||
4 14
|
|
||||||
|
|
||||||
Step 3 produces the following code values:
|
|
||||||
|
|
||||||
Symbol Length Code
|
|
||||||
------ ------ ----
|
|
||||||
A 3 010
|
|
||||||
B 3 011
|
|
||||||
C 3 100
|
|
||||||
D 3 101
|
|
||||||
E 3 110
|
|
||||||
F 2 00
|
|
||||||
G 4 1110
|
|
||||||
H 4 1111
|
|
||||||
|
|
||||||
3.2.3. Details of block format
|
|
||||||
|
|
||||||
Each block of compressed data begins with 3 header bits
|
|
||||||
containing the following data:
|
|
||||||
|
|
||||||
first bit BFINAL
|
|
||||||
next 2 bits BTYPE
|
|
||||||
|
|
||||||
Note that the header bits do not necessarily begin on a byte
|
|
||||||
boundary, since a block does not necessarily occupy an integral
|
|
||||||
number of bytes.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 9]
|
|
||||||
|
|
||||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
BFINAL is set if and only if this is the last block of the data
|
|
||||||
set.
|
|
||||||
|
|
||||||
BTYPE specifies how the data are compressed, as follows:
|
|
||||||
|
|
||||||
00 - no compression
|
|
||||||
01 - compressed with fixed Huffman codes
|
|
||||||
10 - compressed with dynamic Huffman codes
|
|
||||||
11 - reserved (error)
|
|
||||||
|
|
||||||
The only difference between the two compressed cases is how the
|
|
||||||
Huffman codes for the literal/length and distance alphabets are
|
|
||||||
defined.
|
|
||||||
|
|
||||||
In all cases, the decoding algorithm for the actual data is as
|
|
||||||
follows:
|
|
||||||
|
|
||||||
do
|
|
||||||
read block header from input stream.
|
|
||||||
if stored with no compression
|
|
||||||
skip any remaining bits in current partially
|
|
||||||
processed byte
|
|
||||||
read LEN and NLEN (see next section)
|
|
||||||
copy LEN bytes of data to output
|
|
||||||
otherwise
|
|
||||||
if compressed with dynamic Huffman codes
|
|
||||||
read representation of code trees (see
|
|
||||||
subsection below)
|
|
||||||
loop (until end of block code recognized)
|
|
||||||
decode literal/length value from input stream
|
|
||||||
if value < 256
|
|
||||||
copy value (literal byte) to output stream
|
|
||||||
otherwise
|
|
||||||
if value = end of block (256)
|
|
||||||
break from loop
|
|
||||||
otherwise (value = 257..285)
|
|
||||||
decode distance from input stream
|
|
||||||
|
|
||||||
move backwards distance bytes in the output
|
|
||||||
stream, and copy length bytes from this
|
|
||||||
position to the output stream.
|
|
||||||
end loop
|
|
||||||
while not last block
|
|
||||||
|
|
||||||
Note that a duplicated string reference may refer to a string
|
|
||||||
in a previous block; i.e., the backward distance may cross one
|
|
||||||
or more block boundaries. However a distance cannot refer past
|
|
||||||
the beginning of the output stream. (An application using a
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 10]
|
|
||||||
|
|
||||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
preset dictionary might discard part of the output stream; a
|
|
||||||
distance can refer to that part of the output stream anyway)
|
|
||||||
Note also that the referenced string may overlap the current
|
|
||||||
position; for example, if the last 2 bytes decoded have values
|
|
||||||
X and Y, a string reference with <length = 5, distance = 2>
|
|
||||||
adds X,Y,X,Y,X to the output stream.
|
|
||||||
|
|
||||||
We now specify each compression method in turn.
|
|
||||||
|
|
||||||
3.2.4. Non-compressed blocks (BTYPE=00)
|
|
||||||
|
|
||||||
Any bits of input up to the next byte boundary are ignored.
|
|
||||||
The rest of the block consists of the following information:
|
|
||||||
|
|
||||||
0 1 2 3 4...
|
|
||||||
+---+---+---+---+================================+
|
|
||||||
| LEN | NLEN |... LEN bytes of literal data...|
|
|
||||||
+---+---+---+---+================================+
|
|
||||||
|
|
||||||
LEN is the number of data bytes in the block. NLEN is the
|
|
||||||
one's complement of LEN.
|
|
||||||
|
|
||||||
3.2.5. Compressed blocks (length and distance codes)
|
|
||||||
|
|
||||||
As noted above, encoded data blocks in the "deflate" format
|
|
||||||
consist of sequences of symbols drawn from three conceptually
|
|
||||||
distinct alphabets: either literal bytes, from the alphabet of
|
|
||||||
byte values (0..255), or <length, backward distance> pairs,
|
|
||||||
where the length is drawn from (3..258) and the distance is
|
|
||||||
drawn from (1..32,768). In fact, the literal and length
|
|
||||||
alphabets are merged into a single alphabet (0..285), where
|
|
||||||
values 0..255 represent literal bytes, the value 256 indicates
|
|
||||||
end-of-block, and values 257..285 represent length codes
|
|
||||||
(possibly in conjunction with extra bits following the symbol
|
|
||||||
code) as follows:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 11]
|
|
||||||
|
|
||||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
Extra Extra Extra
|
|
||||||
Code Bits Length(s) Code Bits Lengths Code Bits Length(s)
|
|
||||||
---- ---- ------ ---- ---- ------- ---- ---- -------
|
|
||||||
257 0 3 267 1 15,16 277 4 67-82
|
|
||||||
258 0 4 268 1 17,18 278 4 83-98
|
|
||||||
259 0 5 269 2 19-22 279 4 99-114
|
|
||||||
260 0 6 270 2 23-26 280 4 115-130
|
|
||||||
261 0 7 271 2 27-30 281 5 131-162
|
|
||||||
262 0 8 272 2 31-34 282 5 163-194
|
|
||||||
263 0 9 273 3 35-42 283 5 195-226
|
|
||||||
264 0 10 274 3 43-50 284 5 227-257
|
|
||||||
265 1 11,12 275 3 51-58 285 0 258
|
|
||||||
266 1 13,14 276 3 59-66
|
|
||||||
|
|
||||||
The extra bits should be interpreted as a machine integer
|
|
||||||
stored with the most-significant bit first, e.g., bits 1110
|
|
||||||
represent the value 14.
|
|
||||||
|
|
||||||
Extra Extra Extra
|
|
||||||
Code Bits Dist Code Bits Dist Code Bits Distance
|
|
||||||
---- ---- ---- ---- ---- ------ ---- ---- --------
|
|
||||||
0 0 1 10 4 33-48 20 9 1025-1536
|
|
||||||
1 0 2 11 4 49-64 21 9 1537-2048
|
|
||||||
2 0 3 12 5 65-96 22 10 2049-3072
|
|
||||||
3 0 4 13 5 97-128 23 10 3073-4096
|
|
||||||
4 1 5,6 14 6 129-192 24 11 4097-6144
|
|
||||||
5 1 7,8 15 6 193-256 25 11 6145-8192
|
|
||||||
6 2 9-12 16 7 257-384 26 12 8193-12288
|
|
||||||
7 2 13-16 17 7 385-512 27 12 12289-16384
|
|
||||||
8 3 17-24 18 8 513-768 28 13 16385-24576
|
|
||||||
9 3 25-32 19 8 769-1024 29 13 24577-32768
|
|
||||||
|
|
||||||
3.2.6. Compression with fixed Huffman codes (BTYPE=01)
|
|
||||||
|
|
||||||
The Huffman codes for the two alphabets are fixed, and are not
|
|
||||||
represented explicitly in the data. The Huffman code lengths
|
|
||||||
for the literal/length alphabet are:
|
|
||||||
|
|
||||||
Lit Value Bits Codes
|
|
||||||
--------- ---- -----
|
|
||||||
0 - 143 8 00110000 through
|
|
||||||
10111111
|
|
||||||
144 - 255 9 110010000 through
|
|
||||||
111111111
|
|
||||||
256 - 279 7 0000000 through
|
|
||||||
0010111
|
|
||||||
280 - 287 8 11000000 through
|
|
||||||
11000111
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 12]
|
|
||||||
|
|
||||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
The code lengths are sufficient to generate the actual codes,
|
|
||||||
as described above; we show the codes in the table for added
|
|
||||||
clarity. Literal/length values 286-287 will never actually
|
|
||||||
occur in the compressed data, but participate in the code
|
|
||||||
construction.
|
|
||||||
|
|
||||||
Distance codes 0-31 are represented by (fixed-length) 5-bit
|
|
||||||
codes, with possible additional bits as shown in the table
|
|
||||||
shown in Paragraph 3.2.5, above. Note that distance codes 30-
|
|
||||||
31 will never actually occur in the compressed data.
|
|
||||||
|
|
||||||
3.2.7. Compression with dynamic Huffman codes (BTYPE=10)
|
|
||||||
|
|
||||||
The Huffman codes for the two alphabets appear in the block
|
|
||||||
immediately after the header bits and before the actual
|
|
||||||
compressed data, first the literal/length code and then the
|
|
||||||
distance code. Each code is defined by a sequence of code
|
|
||||||
lengths, as discussed in Paragraph 3.2.2, above. For even
|
|
||||||
greater compactness, the code length sequences themselves are
|
|
||||||
compressed using a Huffman code. The alphabet for code lengths
|
|
||||||
is as follows:
|
|
||||||
|
|
||||||
0 - 15: Represent code lengths of 0 - 15
|
|
||||||
16: Copy the previous code length 3 - 6 times.
|
|
||||||
The next 2 bits indicate repeat length
|
|
||||||
(0 = 3, ... , 3 = 6)
|
|
||||||
Example: Codes 8, 16 (+2 bits 11),
|
|
||||||
16 (+2 bits 10) will expand to
|
|
||||||
12 code lengths of 8 (1 + 6 + 5)
|
|
||||||
17: Repeat a code length of 0 for 3 - 10 times.
|
|
||||||
(3 bits of length)
|
|
||||||
18: Repeat a code length of 0 for 11 - 138 times
|
|
||||||
(7 bits of length)
|
|
||||||
|
|
||||||
A code length of 0 indicates that the corresponding symbol in
|
|
||||||
the literal/length or distance alphabet will not occur in the
|
|
||||||
block, and should not participate in the Huffman code
|
|
||||||
construction algorithm given earlier. If only one distance
|
|
||||||
code is used, it is encoded using one bit, not zero bits; in
|
|
||||||
this case there is a single code length of one, with one unused
|
|
||||||
code. One distance code of zero bits means that there are no
|
|
||||||
distance codes used at all (the data is all literals).
|
|
||||||
|
|
||||||
We can now define the format of the block:
|
|
||||||
|
|
||||||
5 Bits: HLIT, # of Literal/Length codes - 257 (257 - 286)
|
|
||||||
5 Bits: HDIST, # of Distance codes - 1 (1 - 32)
|
|
||||||
4 Bits: HCLEN, # of Code Length codes - 4 (4 - 19)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 13]
|
|
||||||
|
|
||||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
(HCLEN + 4) x 3 bits: code lengths for the code length
|
|
||||||
alphabet given just above, in the order: 16, 17, 18,
|
|
||||||
0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
|
|
||||||
|
|
||||||
These code lengths are interpreted as 3-bit integers
|
|
||||||
(0-7); as above, a code length of 0 means the
|
|
||||||
corresponding symbol (literal/length or distance code
|
|
||||||
length) is not used.
|
|
||||||
|
|
||||||
HLIT + 257 code lengths for the literal/length alphabet,
|
|
||||||
encoded using the code length Huffman code
|
|
||||||
|
|
||||||
HDIST + 1 code lengths for the distance alphabet,
|
|
||||||
encoded using the code length Huffman code
|
|
||||||
|
|
||||||
The actual compressed data of the block,
|
|
||||||
encoded using the literal/length and distance Huffman
|
|
||||||
codes
|
|
||||||
|
|
||||||
The literal/length symbol 256 (end of data),
|
|
||||||
encoded using the literal/length Huffman code
|
|
||||||
|
|
||||||
The code length repeat codes can cross from HLIT + 257 to the
|
|
||||||
HDIST + 1 code lengths. In other words, all code lengths form
|
|
||||||
a single sequence of HLIT + HDIST + 258 values.
|
|
||||||
|
|
||||||
3.3. Compliance
|
|
||||||
|
|
||||||
A compressor may limit further the ranges of values specified in
|
|
||||||
the previous section and still be compliant; for example, it may
|
|
||||||
limit the range of backward pointers to some value smaller than
|
|
||||||
32K. Similarly, a compressor may limit the size of blocks so that
|
|
||||||
a compressible block fits in memory.
|
|
||||||
|
|
||||||
A compliant decompressor must accept the full range of possible
|
|
||||||
values defined in the previous section, and must accept blocks of
|
|
||||||
arbitrary size.
|
|
||||||
|
|
||||||
4. Compression algorithm details
|
|
||||||
|
|
||||||
While it is the intent of this document to define the "deflate"
|
|
||||||
compressed data format without reference to any particular
|
|
||||||
compression algorithm, the format is related to the compressed
|
|
||||||
formats produced by LZ77 (Lempel-Ziv 1977, see reference [2] below);
|
|
||||||
since many variations of LZ77 are patented, it is strongly
|
|
||||||
recommended that the implementor of a compressor follow the general
|
|
||||||
algorithm presented here, which is known not to be patented per se.
|
|
||||||
The material in this section is not part of the definition of the
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 14]
|
|
||||||
|
|
||||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
specification per se, and a compressor need not follow it in order to
|
|
||||||
be compliant.
|
|
||||||
|
|
||||||
The compressor terminates a block when it determines that starting a
|
|
||||||
new block with fresh trees would be useful, or when the block size
|
|
||||||
fills up the compressor's block buffer.
|
|
||||||
|
|
||||||
The compressor uses a chained hash table to find duplicated strings,
|
|
||||||
using a hash function that operates on 3-byte sequences. At any
|
|
||||||
given point during compression, let XYZ be the next 3 input bytes to
|
|
||||||
be examined (not necessarily all different, of course). First, the
|
|
||||||
compressor examines the hash chain for XYZ. If the chain is empty,
|
|
||||||
the compressor simply writes out X as a literal byte and advances one
|
|
||||||
byte in the input. If the hash chain is not empty, indicating that
|
|
||||||
the sequence XYZ (or, if we are unlucky, some other 3 bytes with the
|
|
||||||
same hash function value) has occurred recently, the compressor
|
|
||||||
compares all strings on the XYZ hash chain with the actual input data
|
|
||||||
sequence starting at the current point, and selects the longest
|
|
||||||
match.
|
|
||||||
|
|
||||||
The compressor searches the hash chains starting with the most recent
|
|
||||||
strings, to favor small distances and thus take advantage of the
|
|
||||||
Huffman encoding. The hash chains are singly linked. There are no
|
|
||||||
deletions from the hash chains; the algorithm simply discards matches
|
|
||||||
that are too old. To avoid a worst-case situation, very long hash
|
|
||||||
chains are arbitrarily truncated at a certain length, determined by a
|
|
||||||
run-time parameter.
|
|
||||||
|
|
||||||
To improve overall compression, the compressor optionally defers the
|
|
||||||
selection of matches ("lazy matching"): after a match of length N has
|
|
||||||
been found, the compressor searches for a longer match starting at
|
|
||||||
the next input byte. If it finds a longer match, it truncates the
|
|
||||||
previous match to a length of one (thus producing a single literal
|
|
||||||
byte) and then emits the longer match. Otherwise, it emits the
|
|
||||||
original match, and, as described above, advances N bytes before
|
|
||||||
continuing.
|
|
||||||
|
|
||||||
Run-time parameters also control this "lazy match" procedure. If
|
|
||||||
compression ratio is most important, the compressor attempts a
|
|
||||||
complete second search regardless of the length of the first match.
|
|
||||||
In the normal case, if the current match is "long enough", the
|
|
||||||
compressor reduces the search for a longer match, thus speeding up
|
|
||||||
the process. If speed is most important, the compressor inserts new
|
|
||||||
strings in the hash table only when no match was found, or when the
|
|
||||||
match is not "too long". This degrades the compression ratio but
|
|
||||||
saves time since there are both fewer insertions and fewer searches.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 15]
|
|
||||||
|
|
||||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
5. References
|
|
||||||
|
|
||||||
[1] Huffman, D. A., "A Method for the Construction of Minimum
|
|
||||||
Redundancy Codes", Proceedings of the Institute of Radio
|
|
||||||
Engineers, September 1952, Volume 40, Number 9, pp. 1098-1101.
|
|
||||||
|
|
||||||
[2] Ziv J., Lempel A., "A Universal Algorithm for Sequential Data
|
|
||||||
Compression", IEEE Transactions on Information Theory, Vol. 23,
|
|
||||||
No. 3, pp. 337-343.
|
|
||||||
|
|
||||||
[3] Gailly, J.-L., and Adler, M., ZLIB documentation and sources,
|
|
||||||
available in ftp://ftp.uu.net/pub/archiving/zip/doc/
|
|
||||||
|
|
||||||
[4] Gailly, J.-L., and Adler, M., GZIP documentation and sources,
|
|
||||||
available as gzip-*.tar in ftp://prep.ai.mit.edu/pub/gnu/
|
|
||||||
|
|
||||||
[5] Schwartz, E. S., and Kallick, B. "Generating a canonical prefix
|
|
||||||
encoding." Comm. ACM, 7,3 (Mar. 1964), pp. 166-169.
|
|
||||||
|
|
||||||
[6] Hirschberg and Lelewer, "Efficient decoding of prefix codes,"
|
|
||||||
Comm. ACM, 33,4, April 1990, pp. 449-459.
|
|
||||||
|
|
||||||
6. Security Considerations
|
|
||||||
|
|
||||||
Any data compression method involves the reduction of redundancy in
|
|
||||||
the data. Consequently, any corruption of the data is likely to have
|
|
||||||
severe effects and be difficult to correct. Uncompressed text, on
|
|
||||||
the other hand, will probably still be readable despite the presence
|
|
||||||
of some corrupted bytes.
|
|
||||||
|
|
||||||
It is recommended that systems using this data format provide some
|
|
||||||
means of validating the integrity of the compressed data. See
|
|
||||||
reference [3], for example.
|
|
||||||
|
|
||||||
7. Source code
|
|
||||||
|
|
||||||
Source code for a C language implementation of a "deflate" compliant
|
|
||||||
compressor and decompressor is available within the zlib package at
|
|
||||||
ftp://ftp.uu.net/pub/archiving/zip/zlib/.
|
|
||||||
|
|
||||||
8. Acknowledgements
|
|
||||||
|
|
||||||
Trademarks cited in this document are the property of their
|
|
||||||
respective owners.
|
|
||||||
|
|
||||||
Phil Katz designed the deflate format. Jean-Loup Gailly and Mark
|
|
||||||
Adler wrote the related software described in this specification.
|
|
||||||
Glenn Randers-Pehrson converted this document to RFC and HTML format.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 16]
|
|
||||||
|
|
||||||
RFC 1951 DEFLATE Compressed Data Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
9. Author's Address
|
|
||||||
|
|
||||||
L. Peter Deutsch
|
|
||||||
Aladdin Enterprises
|
|
||||||
203 Santa Margarita Ave.
|
|
||||||
Menlo Park, CA 94025
|
|
||||||
|
|
||||||
Phone: (415) 322-0103 (AM only)
|
|
||||||
FAX: (415) 322-1734
|
|
||||||
EMail: <ghost@aladdin.com>
|
|
||||||
|
|
||||||
Questions about the technical content of this specification can be
|
|
||||||
sent by email to:
|
|
||||||
|
|
||||||
Jean-Loup Gailly <gzip@prep.ai.mit.edu> and
|
|
||||||
Mark Adler <madler@alumni.caltech.edu>
|
|
||||||
|
|
||||||
Editorial comments on this specification can be sent by email to:
|
|
||||||
|
|
||||||
L. Peter Deutsch <ghost@aladdin.com> and
|
|
||||||
Glenn Randers-Pehrson <randeg@alumni.rpi.edu>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 17]
|
|
||||||
|
|
@ -1,675 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Network Working Group P. Deutsch
|
|
||||||
Request for Comments: 1952 Aladdin Enterprises
|
|
||||||
Category: Informational May 1996
|
|
||||||
|
|
||||||
|
|
||||||
GZIP file format specification version 4.3
|
|
||||||
|
|
||||||
Status of This Memo
|
|
||||||
|
|
||||||
This memo provides information for the Internet community. This memo
|
|
||||||
does not specify an Internet standard of any kind. Distribution of
|
|
||||||
this memo is unlimited.
|
|
||||||
|
|
||||||
IESG Note:
|
|
||||||
|
|
||||||
The IESG takes no position on the validity of any Intellectual
|
|
||||||
Property Rights statements contained in this document.
|
|
||||||
|
|
||||||
Notices
|
|
||||||
|
|
||||||
Copyright (c) 1996 L. Peter Deutsch
|
|
||||||
|
|
||||||
Permission is granted to copy and distribute this document for any
|
|
||||||
purpose and without charge, including translations into other
|
|
||||||
languages and incorporation into compilations, provided that the
|
|
||||||
copyright notice and this notice are preserved, and that any
|
|
||||||
substantive changes or deletions from the original are clearly
|
|
||||||
marked.
|
|
||||||
|
|
||||||
A pointer to the latest version of this and related documentation in
|
|
||||||
HTML format can be found at the URL
|
|
||||||
<ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html>.
|
|
||||||
|
|
||||||
Abstract
|
|
||||||
|
|
||||||
This specification defines a lossless compressed data format that is
|
|
||||||
compatible with the widely used GZIP utility. The format includes a
|
|
||||||
cyclic redundancy check value for detecting data corruption. The
|
|
||||||
format presently uses the DEFLATE method of compression but can be
|
|
||||||
easily extended to use other compression methods. The format can be
|
|
||||||
implemented readily in a manner not covered by patents.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 1]
|
|
||||||
|
|
||||||
RFC 1952 GZIP File Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
Table of Contents
|
|
||||||
|
|
||||||
1. Introduction ................................................... 2
|
|
||||||
1.1. Purpose ................................................... 2
|
|
||||||
1.2. Intended audience ......................................... 3
|
|
||||||
1.3. Scope ..................................................... 3
|
|
||||||
1.4. Compliance ................................................ 3
|
|
||||||
1.5. Definitions of terms and conventions used ................. 3
|
|
||||||
1.6. Changes from previous versions ............................ 3
|
|
||||||
2. Detailed specification ......................................... 4
|
|
||||||
2.1. Overall conventions ....................................... 4
|
|
||||||
2.2. File format ............................................... 5
|
|
||||||
2.3. Member format ............................................. 5
|
|
||||||
2.3.1. Member header and trailer ........................... 6
|
|
||||||
2.3.1.1. Extra field ................................... 8
|
|
||||||
2.3.1.2. Compliance .................................... 9
|
|
||||||
3. References .................................................. 9
|
|
||||||
4. Security Considerations .................................... 10
|
|
||||||
5. Acknowledgements ........................................... 10
|
|
||||||
6. Author's Address ........................................... 10
|
|
||||||
7. Appendix: Jean-Loup Gailly's gzip utility .................. 11
|
|
||||||
8. Appendix: Sample CRC Code .................................. 11
|
|
||||||
|
|
||||||
1. Introduction
|
|
||||||
|
|
||||||
1.1. Purpose
|
|
||||||
|
|
||||||
The purpose of this specification is to define a lossless
|
|
||||||
compressed data format that:
|
|
||||||
|
|
||||||
* Is independent of CPU type, operating system, file system,
|
|
||||||
and character set, and hence can be used for interchange;
|
|
||||||
* Can compress or decompress a data stream (as opposed to a
|
|
||||||
randomly accessible file) to produce another data stream,
|
|
||||||
using only an a priori bounded amount of intermediate
|
|
||||||
storage, and hence can be used in data communications or
|
|
||||||
similar structures such as Unix filters;
|
|
||||||
* Compresses data with efficiency comparable to the best
|
|
||||||
currently available general-purpose compression methods,
|
|
||||||
and in particular considerably better than the "compress"
|
|
||||||
program;
|
|
||||||
* Can be implemented readily in a manner not covered by
|
|
||||||
patents, and hence can be practiced freely;
|
|
||||||
* Is compatible with the file format produced by the current
|
|
||||||
widely used gzip utility, in that conforming decompressors
|
|
||||||
will be able to read data produced by the existing gzip
|
|
||||||
compressor.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 2]
|
|
||||||
|
|
||||||
RFC 1952 GZIP File Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
The data format defined by this specification does not attempt to:
|
|
||||||
|
|
||||||
* Provide random access to compressed data;
|
|
||||||
* Compress specialized data (e.g., raster graphics) as well as
|
|
||||||
the best currently available specialized algorithms.
|
|
||||||
|
|
||||||
1.2. Intended audience
|
|
||||||
|
|
||||||
This specification is intended for use by implementors of software
|
|
||||||
to compress data into gzip format and/or decompress data from gzip
|
|
||||||
format.
|
|
||||||
|
|
||||||
The text of the specification assumes a basic background in
|
|
||||||
programming at the level of bits and other primitive data
|
|
||||||
representations.
|
|
||||||
|
|
||||||
1.3. Scope
|
|
||||||
|
|
||||||
The specification specifies a compression method and a file format
|
|
||||||
(the latter assuming only that a file can store a sequence of
|
|
||||||
arbitrary bytes). It does not specify any particular interface to
|
|
||||||
a file system or anything about character sets or encodings
|
|
||||||
(except for file names and comments, which are optional).
|
|
||||||
|
|
||||||
1.4. Compliance
|
|
||||||
|
|
||||||
Unless otherwise indicated below, a compliant decompressor must be
|
|
||||||
able to accept and decompress any file that conforms to all the
|
|
||||||
specifications presented here; a compliant compressor must produce
|
|
||||||
files that conform to all the specifications presented here. The
|
|
||||||
material in the appendices is not part of the specification per se
|
|
||||||
and is not relevant to compliance.
|
|
||||||
|
|
||||||
1.5. Definitions of terms and conventions used
|
|
||||||
|
|
||||||
byte: 8 bits stored or transmitted as a unit (same as an octet).
|
|
||||||
(For this specification, a byte is exactly 8 bits, even on
|
|
||||||
machines which store a character on a number of bits different
|
|
||||||
from 8.) See below for the numbering of bits within a byte.
|
|
||||||
|
|
||||||
1.6. Changes from previous versions
|
|
||||||
|
|
||||||
There have been no technical changes to the gzip format since
|
|
||||||
version 4.1 of this specification. In version 4.2, some
|
|
||||||
terminology was changed, and the sample CRC code was rewritten for
|
|
||||||
clarity and to eliminate the requirement for the caller to do pre-
|
|
||||||
and post-conditioning. Version 4.3 is a conversion of the
|
|
||||||
specification to RFC style.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 3]
|
|
||||||
|
|
||||||
RFC 1952 GZIP File Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
2. Detailed specification
|
|
||||||
|
|
||||||
2.1. Overall conventions
|
|
||||||
|
|
||||||
In the diagrams below, a box like this:
|
|
||||||
|
|
||||||
+---+
|
|
||||||
| | <-- the vertical bars might be missing
|
|
||||||
+---+
|
|
||||||
|
|
||||||
represents one byte; a box like this:
|
|
||||||
|
|
||||||
+==============+
|
|
||||||
| |
|
|
||||||
+==============+
|
|
||||||
|
|
||||||
represents a variable number of bytes.
|
|
||||||
|
|
||||||
Bytes stored within a computer do not have a "bit order", since
|
|
||||||
they are always treated as a unit. However, a byte considered as
|
|
||||||
an integer between 0 and 255 does have a most- and least-
|
|
||||||
significant bit, and since we write numbers with the most-
|
|
||||||
significant digit on the left, we also write bytes with the most-
|
|
||||||
significant bit on the left. In the diagrams below, we number the
|
|
||||||
bits of a byte so that bit 0 is the least-significant bit, i.e.,
|
|
||||||
the bits are numbered:
|
|
||||||
|
|
||||||
+--------+
|
|
||||||
|76543210|
|
|
||||||
+--------+
|
|
||||||
|
|
||||||
This document does not address the issue of the order in which
|
|
||||||
bits of a byte are transmitted on a bit-sequential medium, since
|
|
||||||
the data format described here is byte- rather than bit-oriented.
|
|
||||||
|
|
||||||
Within a computer, a number may occupy multiple bytes. All
|
|
||||||
multi-byte numbers in the format described here are stored with
|
|
||||||
the least-significant byte first (at the lower memory address).
|
|
||||||
For example, the decimal number 520 is stored as:
|
|
||||||
|
|
||||||
0 1
|
|
||||||
+--------+--------+
|
|
||||||
|00001000|00000010|
|
|
||||||
+--------+--------+
|
|
||||||
^ ^
|
|
||||||
| |
|
|
||||||
| + more significant byte = 2 x 256
|
|
||||||
+ less significant byte = 8
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 4]
|
|
||||||
|
|
||||||
RFC 1952 GZIP File Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
2.2. File format
|
|
||||||
|
|
||||||
A gzip file consists of a series of "members" (compressed data
|
|
||||||
sets). The format of each member is specified in the following
|
|
||||||
section. The members simply appear one after another in the file,
|
|
||||||
with no additional information before, between, or after them.
|
|
||||||
|
|
||||||
2.3. Member format
|
|
||||||
|
|
||||||
Each member has the following structure:
|
|
||||||
|
|
||||||
+---+---+---+---+---+---+---+---+---+---+
|
|
||||||
|ID1|ID2|CM |FLG| MTIME |XFL|OS | (more-->)
|
|
||||||
+---+---+---+---+---+---+---+---+---+---+
|
|
||||||
|
|
||||||
(if FLG.FEXTRA set)
|
|
||||||
|
|
||||||
+---+---+=================================+
|
|
||||||
| XLEN |...XLEN bytes of "extra field"...| (more-->)
|
|
||||||
+---+---+=================================+
|
|
||||||
|
|
||||||
(if FLG.FNAME set)
|
|
||||||
|
|
||||||
+=========================================+
|
|
||||||
|...original file name, zero-terminated...| (more-->)
|
|
||||||
+=========================================+
|
|
||||||
|
|
||||||
(if FLG.FCOMMENT set)
|
|
||||||
|
|
||||||
+===================================+
|
|
||||||
|...file comment, zero-terminated...| (more-->)
|
|
||||||
+===================================+
|
|
||||||
|
|
||||||
(if FLG.FHCRC set)
|
|
||||||
|
|
||||||
+---+---+
|
|
||||||
| CRC16 |
|
|
||||||
+---+---+
|
|
||||||
|
|
||||||
+=======================+
|
|
||||||
|...compressed blocks...| (more-->)
|
|
||||||
+=======================+
|
|
||||||
|
|
||||||
0 1 2 3 4 5 6 7
|
|
||||||
+---+---+---+---+---+---+---+---+
|
|
||||||
| CRC32 | ISIZE |
|
|
||||||
+---+---+---+---+---+---+---+---+
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 5]
|
|
||||||
|
|
||||||
RFC 1952 GZIP File Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
2.3.1. Member header and trailer
|
|
||||||
|
|
||||||
ID1 (IDentification 1)
|
|
||||||
ID2 (IDentification 2)
|
|
||||||
These have the fixed values ID1 = 31 (0x1f, \037), ID2 = 139
|
|
||||||
(0x8b, \213), to identify the file as being in gzip format.
|
|
||||||
|
|
||||||
CM (Compression Method)
|
|
||||||
This identifies the compression method used in the file. CM
|
|
||||||
= 0-7 are reserved. CM = 8 denotes the "deflate"
|
|
||||||
compression method, which is the one customarily used by
|
|
||||||
gzip and which is documented elsewhere.
|
|
||||||
|
|
||||||
FLG (FLaGs)
|
|
||||||
This flag byte is divided into individual bits as follows:
|
|
||||||
|
|
||||||
bit 0 FTEXT
|
|
||||||
bit 1 FHCRC
|
|
||||||
bit 2 FEXTRA
|
|
||||||
bit 3 FNAME
|
|
||||||
bit 4 FCOMMENT
|
|
||||||
bit 5 reserved
|
|
||||||
bit 6 reserved
|
|
||||||
bit 7 reserved
|
|
||||||
|
|
||||||
If FTEXT is set, the file is probably ASCII text. This is
|
|
||||||
an optional indication, which the compressor may set by
|
|
||||||
checking a small amount of the input data to see whether any
|
|
||||||
non-ASCII characters are present. In case of doubt, FTEXT
|
|
||||||
is cleared, indicating binary data. For systems which have
|
|
||||||
different file formats for ascii text and binary data, the
|
|
||||||
decompressor can use FTEXT to choose the appropriate format.
|
|
||||||
We deliberately do not specify the algorithm used to set
|
|
||||||
this bit, since a compressor always has the option of
|
|
||||||
leaving it cleared and a decompressor always has the option
|
|
||||||
of ignoring it and letting some other program handle issues
|
|
||||||
of data conversion.
|
|
||||||
|
|
||||||
If FHCRC is set, a CRC16 for the gzip header is present,
|
|
||||||
immediately before the compressed data. The CRC16 consists
|
|
||||||
of the two least significant bytes of the CRC32 for all
|
|
||||||
bytes of the gzip header up to and not including the CRC16.
|
|
||||||
[The FHCRC bit was never set by versions of gzip up to
|
|
||||||
1.2.4, even though it was documented with a different
|
|
||||||
meaning in gzip 1.2.4.]
|
|
||||||
|
|
||||||
If FEXTRA is set, optional extra fields are present, as
|
|
||||||
described in a following section.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 6]
|
|
||||||
|
|
||||||
RFC 1952 GZIP File Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
If FNAME is set, an original file name is present,
|
|
||||||
terminated by a zero byte. The name must consist of ISO
|
|
||||||
8859-1 (LATIN-1) characters; on operating systems using
|
|
||||||
EBCDIC or any other character set for file names, the name
|
|
||||||
must be translated to the ISO LATIN-1 character set. This
|
|
||||||
is the original name of the file being compressed, with any
|
|
||||||
directory components removed, and, if the file being
|
|
||||||
compressed is on a file system with case insensitive names,
|
|
||||||
forced to lower case. There is no original file name if the
|
|
||||||
data was compressed from a source other than a named file;
|
|
||||||
for example, if the source was stdin on a Unix system, there
|
|
||||||
is no file name.
|
|
||||||
|
|
||||||
If FCOMMENT is set, a zero-terminated file comment is
|
|
||||||
present. This comment is not interpreted; it is only
|
|
||||||
intended for human consumption. The comment must consist of
|
|
||||||
ISO 8859-1 (LATIN-1) characters. Line breaks should be
|
|
||||||
denoted by a single line feed character (10 decimal).
|
|
||||||
|
|
||||||
Reserved FLG bits must be zero.
|
|
||||||
|
|
||||||
MTIME (Modification TIME)
|
|
||||||
This gives the most recent modification time of the original
|
|
||||||
file being compressed. The time is in Unix format, i.e.,
|
|
||||||
seconds since 00:00:00 GMT, Jan. 1, 1970. (Note that this
|
|
||||||
may cause problems for MS-DOS and other systems that use
|
|
||||||
local rather than Universal time.) If the compressed data
|
|
||||||
did not come from a file, MTIME is set to the time at which
|
|
||||||
compression started. MTIME = 0 means no time stamp is
|
|
||||||
available.
|
|
||||||
|
|
||||||
XFL (eXtra FLags)
|
|
||||||
These flags are available for use by specific compression
|
|
||||||
methods. The "deflate" method (CM = 8) sets these flags as
|
|
||||||
follows:
|
|
||||||
|
|
||||||
XFL = 2 - compressor used maximum compression,
|
|
||||||
slowest algorithm
|
|
||||||
XFL = 4 - compressor used fastest algorithm
|
|
||||||
|
|
||||||
OS (Operating System)
|
|
||||||
This identifies the type of file system on which compression
|
|
||||||
took place. This may be useful in determining end-of-line
|
|
||||||
convention for text files. The currently defined values are
|
|
||||||
as follows:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 7]
|
|
||||||
|
|
||||||
RFC 1952 GZIP File Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
0 - FAT filesystem (MS-DOS, OS/2, NT/Win32)
|
|
||||||
1 - Amiga
|
|
||||||
2 - VMS (or OpenVMS)
|
|
||||||
3 - Unix
|
|
||||||
4 - VM/CMS
|
|
||||||
5 - Atari TOS
|
|
||||||
6 - HPFS filesystem (OS/2, NT)
|
|
||||||
7 - Macintosh
|
|
||||||
8 - Z-System
|
|
||||||
9 - CP/M
|
|
||||||
10 - TOPS-20
|
|
||||||
11 - NTFS filesystem (NT)
|
|
||||||
12 - QDOS
|
|
||||||
13 - Acorn RISCOS
|
|
||||||
255 - unknown
|
|
||||||
|
|
||||||
XLEN (eXtra LENgth)
|
|
||||||
If FLG.FEXTRA is set, this gives the length of the optional
|
|
||||||
extra field. See below for details.
|
|
||||||
|
|
||||||
CRC32 (CRC-32)
|
|
||||||
This contains a Cyclic Redundancy Check value of the
|
|
||||||
uncompressed data computed according to CRC-32 algorithm
|
|
||||||
used in the ISO 3309 standard and in section 8.1.1.6.2 of
|
|
||||||
ITU-T recommendation V.42. (See http://www.iso.ch for
|
|
||||||
ordering ISO documents. See gopher://info.itu.ch for an
|
|
||||||
online version of ITU-T V.42.)
|
|
||||||
|
|
||||||
ISIZE (Input SIZE)
|
|
||||||
This contains the size of the original (uncompressed) input
|
|
||||||
data modulo 2^32.
|
|
||||||
|
|
||||||
2.3.1.1. Extra field
|
|
||||||
|
|
||||||
If the FLG.FEXTRA bit is set, an "extra field" is present in
|
|
||||||
the header, with total length XLEN bytes. It consists of a
|
|
||||||
series of subfields, each of the form:
|
|
||||||
|
|
||||||
+---+---+---+---+==================================+
|
|
||||||
|SI1|SI2| LEN |... LEN bytes of subfield data ...|
|
|
||||||
+---+---+---+---+==================================+
|
|
||||||
|
|
||||||
SI1 and SI2 provide a subfield ID, typically two ASCII letters
|
|
||||||
with some mnemonic value. Jean-Loup Gailly
|
|
||||||
<gzip@prep.ai.mit.edu> is maintaining a registry of subfield
|
|
||||||
IDs; please send him any subfield ID you wish to use. Subfield
|
|
||||||
IDs with SI2 = 0 are reserved for future use. The following
|
|
||||||
IDs are currently defined:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 8]
|
|
||||||
|
|
||||||
RFC 1952 GZIP File Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
SI1 SI2 Data
|
|
||||||
---------- ---------- ----
|
|
||||||
0x41 ('A') 0x70 ('P') Apollo file type information
|
|
||||||
|
|
||||||
LEN gives the length of the subfield data, excluding the 4
|
|
||||||
initial bytes.
|
|
||||||
|
|
||||||
2.3.1.2. Compliance
|
|
||||||
|
|
||||||
A compliant compressor must produce files with correct ID1,
|
|
||||||
ID2, CM, CRC32, and ISIZE, but may set all the other fields in
|
|
||||||
the fixed-length part of the header to default values (255 for
|
|
||||||
OS, 0 for all others). The compressor must set all reserved
|
|
||||||
bits to zero.
|
|
||||||
|
|
||||||
A compliant decompressor must check ID1, ID2, and CM, and
|
|
||||||
provide an error indication if any of these have incorrect
|
|
||||||
values. It must examine FEXTRA/XLEN, FNAME, FCOMMENT and FHCRC
|
|
||||||
at least so it can skip over the optional fields if they are
|
|
||||||
present. It need not examine any other part of the header or
|
|
||||||
trailer; in particular, a decompressor may ignore FTEXT and OS
|
|
||||||
and always produce binary output, and still be compliant. A
|
|
||||||
compliant decompressor must give an error indication if any
|
|
||||||
reserved bit is non-zero, since such a bit could indicate the
|
|
||||||
presence of a new field that would cause subsequent data to be
|
|
||||||
interpreted incorrectly.
|
|
||||||
|
|
||||||
3. References
|
|
||||||
|
|
||||||
[1] "Information Processing - 8-bit single-byte coded graphic
|
|
||||||
character sets - Part 1: Latin alphabet No.1" (ISO 8859-1:1987).
|
|
||||||
The ISO 8859-1 (Latin-1) character set is a superset of 7-bit
|
|
||||||
ASCII. Files defining this character set are available as
|
|
||||||
iso_8859-1.* in ftp://ftp.uu.net/graphics/png/documents/
|
|
||||||
|
|
||||||
[2] ISO 3309
|
|
||||||
|
|
||||||
[3] ITU-T recommendation V.42
|
|
||||||
|
|
||||||
[4] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification",
|
|
||||||
available in ftp://ftp.uu.net/pub/archiving/zip/doc/
|
|
||||||
|
|
||||||
[5] Gailly, J.-L., GZIP documentation, available as gzip-*.tar in
|
|
||||||
ftp://prep.ai.mit.edu/pub/gnu/
|
|
||||||
|
|
||||||
[6] Sarwate, D.V., "Computation of Cyclic Redundancy Checks via Table
|
|
||||||
Look-Up", Communications of the ACM, 31(8), pp.1008-1013.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 9]
|
|
||||||
|
|
||||||
RFC 1952 GZIP File Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
[7] Schwaderer, W.D., "CRC Calculation", April 85 PC Tech Journal,
|
|
||||||
pp.118-133.
|
|
||||||
|
|
||||||
[8] ftp://ftp.adelaide.edu.au/pub/rocksoft/papers/crc_v3.txt,
|
|
||||||
describing the CRC concept.
|
|
||||||
|
|
||||||
4. Security Considerations
|
|
||||||
|
|
||||||
Any data compression method involves the reduction of redundancy in
|
|
||||||
the data. Consequently, any corruption of the data is likely to have
|
|
||||||
severe effects and be difficult to correct. Uncompressed text, on
|
|
||||||
the other hand, will probably still be readable despite the presence
|
|
||||||
of some corrupted bytes.
|
|
||||||
|
|
||||||
It is recommended that systems using this data format provide some
|
|
||||||
means of validating the integrity of the compressed data, such as by
|
|
||||||
setting and checking the CRC-32 check value.
|
|
||||||
|
|
||||||
5. Acknowledgements
|
|
||||||
|
|
||||||
Trademarks cited in this document are the property of their
|
|
||||||
respective owners.
|
|
||||||
|
|
||||||
Jean-Loup Gailly designed the gzip format and wrote, with Mark Adler,
|
|
||||||
the related software described in this specification. Glenn
|
|
||||||
Randers-Pehrson converted this document to RFC and HTML format.
|
|
||||||
|
|
||||||
6. Author's Address
|
|
||||||
|
|
||||||
L. Peter Deutsch
|
|
||||||
Aladdin Enterprises
|
|
||||||
203 Santa Margarita Ave.
|
|
||||||
Menlo Park, CA 94025
|
|
||||||
|
|
||||||
Phone: (415) 322-0103 (AM only)
|
|
||||||
FAX: (415) 322-1734
|
|
||||||
EMail: <ghost@aladdin.com>
|
|
||||||
|
|
||||||
Questions about the technical content of this specification can be
|
|
||||||
sent by email to:
|
|
||||||
|
|
||||||
Jean-Loup Gailly <gzip@prep.ai.mit.edu> and
|
|
||||||
Mark Adler <madler@alumni.caltech.edu>
|
|
||||||
|
|
||||||
Editorial comments on this specification can be sent by email to:
|
|
||||||
|
|
||||||
L. Peter Deutsch <ghost@aladdin.com> and
|
|
||||||
Glenn Randers-Pehrson <randeg@alumni.rpi.edu>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 10]
|
|
||||||
|
|
||||||
RFC 1952 GZIP File Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
7. Appendix: Jean-Loup Gailly's gzip utility
|
|
||||||
|
|
||||||
The most widely used implementation of gzip compression, and the
|
|
||||||
original documentation on which this specification is based, were
|
|
||||||
created by Jean-Loup Gailly <gzip@prep.ai.mit.edu>. Since this
|
|
||||||
implementation is a de facto standard, we mention some more of its
|
|
||||||
features here. Again, the material in this section is not part of
|
|
||||||
the specification per se, and implementations need not follow it to
|
|
||||||
be compliant.
|
|
||||||
|
|
||||||
When compressing or decompressing a file, gzip preserves the
|
|
||||||
protection, ownership, and modification time attributes on the local
|
|
||||||
file system, since there is no provision for representing protection
|
|
||||||
attributes in the gzip file format itself. Since the file format
|
|
||||||
includes a modification time, the gzip decompressor provides a
|
|
||||||
command line switch that assigns the modification time from the file,
|
|
||||||
rather than the local modification time of the compressed input, to
|
|
||||||
the decompressed output.
|
|
||||||
|
|
||||||
8. Appendix: Sample CRC Code
|
|
||||||
|
|
||||||
The following sample code represents a practical implementation of
|
|
||||||
the CRC (Cyclic Redundancy Check). (See also ISO 3309 and ITU-T V.42
|
|
||||||
for a formal specification.)
|
|
||||||
|
|
||||||
The sample code is in the ANSI C programming language. Non C users
|
|
||||||
may find it easier to read with these hints:
|
|
||||||
|
|
||||||
& Bitwise AND operator.
|
|
||||||
^ Bitwise exclusive-OR operator.
|
|
||||||
>> Bitwise right shift operator. When applied to an
|
|
||||||
unsigned quantity, as here, right shift inserts zero
|
|
||||||
bit(s) at the left.
|
|
||||||
! Logical NOT operator.
|
|
||||||
++ "n++" increments the variable n.
|
|
||||||
0xNNN 0x introduces a hexadecimal (base 16) constant.
|
|
||||||
Suffix L indicates a long value (at least 32 bits).
|
|
||||||
|
|
||||||
/* Table of CRCs of all 8-bit messages. */
|
|
||||||
unsigned long crc_table[256];
|
|
||||||
|
|
||||||
/* Flag: has the table been computed? Initially false. */
|
|
||||||
int crc_table_computed = 0;
|
|
||||||
|
|
||||||
/* Make the table for a fast CRC. */
|
|
||||||
void make_crc_table(void)
|
|
||||||
{
|
|
||||||
unsigned long c;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 11]
|
|
||||||
|
|
||||||
RFC 1952 GZIP File Format Specification May 1996
|
|
||||||
|
|
||||||
|
|
||||||
int n, k;
|
|
||||||
for (n = 0; n < 256; n++) {
|
|
||||||
c = (unsigned long) n;
|
|
||||||
for (k = 0; k < 8; k++) {
|
|
||||||
if (c & 1) {
|
|
||||||
c = 0xedb88320L ^ (c >> 1);
|
|
||||||
} else {
|
|
||||||
c = c >> 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
crc_table[n] = c;
|
|
||||||
}
|
|
||||||
crc_table_computed = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Update a running crc with the bytes buf[0..len-1] and return
|
|
||||||
the updated crc. The crc should be initialized to zero. Pre- and
|
|
||||||
post-conditioning (one's complement) is performed within this
|
|
||||||
function so it shouldn't be done by the caller. Usage example:
|
|
||||||
|
|
||||||
unsigned long crc = 0L;
|
|
||||||
|
|
||||||
while (read_buffer(buffer, length) != EOF) {
|
|
||||||
crc = update_crc(crc, buffer, length);
|
|
||||||
}
|
|
||||||
if (crc != original_crc) error();
|
|
||||||
*/
|
|
||||||
unsigned long update_crc(unsigned long crc,
|
|
||||||
unsigned char *buf, int len)
|
|
||||||
{
|
|
||||||
unsigned long c = crc ^ 0xffffffffL;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
if (!crc_table_computed)
|
|
||||||
make_crc_table();
|
|
||||||
for (n = 0; n < len; n++) {
|
|
||||||
c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
|
|
||||||
}
|
|
||||||
return c ^ 0xffffffffL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the CRC of the bytes buf[0..len-1]. */
|
|
||||||
unsigned long crc(unsigned char *buf, int len)
|
|
||||||
{
|
|
||||||
return update_crc(0L, buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Deutsch Informational [Page 12]
|
|
||||||
|
|
@ -1,107 +0,0 @@
|
|||||||
A Fast Method for Identifying Plain Text Files
|
|
||||||
==============================================
|
|
||||||
|
|
||||||
|
|
||||||
Introduction
|
|
||||||
------------
|
|
||||||
|
|
||||||
Given a file coming from an unknown source, it is sometimes desirable
|
|
||||||
to find out whether the format of that file is plain text. Although
|
|
||||||
this may appear like a simple task, a fully accurate detection of the
|
|
||||||
file type requires heavy-duty semantic analysis on the file contents.
|
|
||||||
It is, however, possible to obtain satisfactory results by employing
|
|
||||||
various heuristics.
|
|
||||||
|
|
||||||
Previous versions of PKZip and other zip-compatible compression tools
|
|
||||||
were using a crude detection scheme: if more than 80% (4/5) of the bytes
|
|
||||||
found in a certain buffer are within the range [7..127], the file is
|
|
||||||
labeled as plain text, otherwise it is labeled as binary. A prominent
|
|
||||||
limitation of this scheme is the restriction to Latin-based alphabets.
|
|
||||||
Other alphabets, like Greek, Cyrillic or Asian, make extensive use of
|
|
||||||
the bytes within the range [128..255], and texts using these alphabets
|
|
||||||
are most often misidentified by this scheme; in other words, the rate
|
|
||||||
of false negatives is sometimes too high, which means that the recall
|
|
||||||
is low. Another weakness of this scheme is a reduced precision, due to
|
|
||||||
the false positives that may occur when binary files containing large
|
|
||||||
amounts of textual characters are misidentified as plain text.
|
|
||||||
|
|
||||||
In this article we propose a new, simple detection scheme that features
|
|
||||||
a much increased precision and a near-100% recall. This scheme is
|
|
||||||
designed to work on ASCII, Unicode and other ASCII-derived alphabets,
|
|
||||||
and it handles single-byte encodings (ISO-8859, MacRoman, KOI8, etc.)
|
|
||||||
and variable-sized encodings (ISO-2022, UTF-8, etc.). Wider encodings
|
|
||||||
(UCS-2/UTF-16 and UCS-4/UTF-32) are not handled, however.
|
|
||||||
|
|
||||||
|
|
||||||
The Algorithm
|
|
||||||
-------------
|
|
||||||
|
|
||||||
The algorithm works by dividing the set of bytecodes [0..255] into three
|
|
||||||
categories:
|
|
||||||
- The white list of textual bytecodes:
|
|
||||||
9 (TAB), 10 (LF), 13 (CR), 32 (SPACE) to 255.
|
|
||||||
- The gray list of tolerated bytecodes:
|
|
||||||
7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB), 27 (ESC).
|
|
||||||
- The black list of undesired, non-textual bytecodes:
|
|
||||||
0 (NUL) to 6, 14 to 31.
|
|
||||||
|
|
||||||
If a file contains at least one byte that belongs to the white list and
|
|
||||||
no byte that belongs to the black list, then the file is categorized as
|
|
||||||
plain text; otherwise, it is categorized as binary. (The boundary case,
|
|
||||||
when the file is empty, automatically falls into the latter category.)
|
|
||||||
|
|
||||||
|
|
||||||
Rationale
|
|
||||||
---------
|
|
||||||
|
|
||||||
The idea behind this algorithm relies on two observations.
|
|
||||||
|
|
||||||
The first observation is that, although the full range of 7-bit codes
|
|
||||||
[0..127] is properly specified by the ASCII standard, most control
|
|
||||||
characters in the range [0..31] are not used in practice. The only
|
|
||||||
widely-used, almost universally-portable control codes are 9 (TAB),
|
|
||||||
10 (LF) and 13 (CR). There are a few more control codes that are
|
|
||||||
recognized on a reduced range of platforms and text viewers/editors:
|
|
||||||
7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB) and 27 (ESC); but these
|
|
||||||
codes are rarely (if ever) used alone, without being accompanied by
|
|
||||||
some printable text. Even the newer, portable text formats such as
|
|
||||||
XML avoid using control characters outside the list mentioned here.
|
|
||||||
|
|
||||||
The second observation is that most of the binary files tend to contain
|
|
||||||
control characters, especially 0 (NUL). Even though the older text
|
|
||||||
detection schemes observe the presence of non-ASCII codes from the range
|
|
||||||
[128..255], the precision rarely has to suffer if this upper range is
|
|
||||||
labeled as textual, because the files that are genuinely binary tend to
|
|
||||||
contain both control characters and codes from the upper range. On the
|
|
||||||
other hand, the upper range needs to be labeled as textual, because it
|
|
||||||
is used by virtually all ASCII extensions. In particular, this range is
|
|
||||||
used for encoding non-Latin scripts.
|
|
||||||
|
|
||||||
Since there is no counting involved, other than simply observing the
|
|
||||||
presence or the absence of some byte values, the algorithm produces
|
|
||||||
consistent results, regardless what alphabet encoding is being used.
|
|
||||||
(If counting were involved, it could be possible to obtain different
|
|
||||||
results on a text encoded, say, using ISO-8859-16 versus UTF-8.)
|
|
||||||
|
|
||||||
There is an extra category of plain text files that are "polluted" with
|
|
||||||
one or more black-listed codes, either by mistake or by peculiar design
|
|
||||||
considerations. In such cases, a scheme that tolerates a small fraction
|
|
||||||
of black-listed codes would provide an increased recall (i.e. more true
|
|
||||||
positives). This, however, incurs a reduced precision overall, since
|
|
||||||
false positives are more likely to appear in binary files that contain
|
|
||||||
large chunks of textual data. Furthermore, "polluted" plain text should
|
|
||||||
be regarded as binary by general-purpose text detection schemes, because
|
|
||||||
general-purpose text processing algorithms might not be applicable.
|
|
||||||
Under this premise, it is safe to say that our detection method provides
|
|
||||||
a near-100% recall.
|
|
||||||
|
|
||||||
Experiments have been run on many files coming from various platforms
|
|
||||||
and applications. We tried plain text files, system logs, source code,
|
|
||||||
formatted office documents, compiled object code, etc. The results
|
|
||||||
confirm the optimistic assumptions about the capabilities of this
|
|
||||||
algorithm.
|
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
Cosmin Truta
|
|
||||||
Last updated: 2006-May-28
|
|
@ -1,23 +0,0 @@
|
|||||||
/* gzclose.c -- zlib gzclose() function
|
|
||||||
* Copyright (C) 2004, 2010 Mark Adler
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "gzguts.h"
|
|
||||||
|
|
||||||
/* gzclose() is in a separate file so that it is linked in only if it is used.
|
|
||||||
That way the other gzclose functions can be used instead to avoid linking in
|
|
||||||
unneeded compression or decompression routines. */
|
|
||||||
int ZEXPORT gzclose(gzFile file) {
|
|
||||||
#ifndef NO_GZCOMPRESS
|
|
||||||
gz_statep state;
|
|
||||||
|
|
||||||
if (file == NULL)
|
|
||||||
return Z_STREAM_ERROR;
|
|
||||||
state = (gz_statep)file;
|
|
||||||
|
|
||||||
return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file);
|
|
||||||
#else
|
|
||||||
return gzclose_r(file);
|
|
||||||
#endif
|
|
||||||
}
|
|
@ -1,158 +0,0 @@
|
|||||||
#ifndef GZGUTS_H_
|
|
||||||
#define GZGUTS_H_
|
|
||||||
/* gzguts.h -- zlib internal header definitions for gz* operations
|
|
||||||
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef _LARGEFILE64_SOURCE
|
|
||||||
# ifndef _LARGEFILE_SOURCE
|
|
||||||
# define _LARGEFILE_SOURCE 1
|
|
||||||
# endif
|
|
||||||
# ifdef _FILE_OFFSET_BITS
|
|
||||||
# undef _FILE_OFFSET_BITS
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(HAVE_INTERNAL)
|
|
||||||
# define ZLIB_INTERNAL __attribute__((visibility ("internal")))
|
|
||||||
#elif defined(HAVE_HIDDEN)
|
|
||||||
# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
|
|
||||||
#else
|
|
||||||
# define ZLIB_INTERNAL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include "zlib.h"
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
# include <stddef.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) || defined(WIN32)
|
|
||||||
# include <io.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW__)
|
|
||||||
# define WIDECHAR
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WINAPI_FAMILY
|
|
||||||
# define open _open
|
|
||||||
# define read _read
|
|
||||||
# define write _write
|
|
||||||
# define close _close
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
|
|
||||||
#if !defined(STDC99) && !defined(__CYGWIN__) && !defined(__MINGW__) && defined(WIN32)
|
|
||||||
# if !defined(vsnprintf)
|
|
||||||
# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
|
|
||||||
# define vsnprintf _vsnprintf
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* unlike snprintf (which is required in C99), _snprintf does not guarantee
|
|
||||||
null termination of the result -- however this is only used in gzlib.c
|
|
||||||
where the result is assured to fit in the space provided */
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
|
||||||
# define snprintf _snprintf
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef local
|
|
||||||
# define local static
|
|
||||||
#endif
|
|
||||||
/* compile with -Dlocal if your debugger can't find static symbols */
|
|
||||||
|
|
||||||
/* get errno and strerror definition */
|
|
||||||
#ifndef NO_STRERROR
|
|
||||||
# include <errno.h>
|
|
||||||
# define zstrerror() strerror(errno)
|
|
||||||
#else
|
|
||||||
# define zstrerror() "stdio error (consult errno)"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* provide prototypes for these when building zlib without LFS */
|
|
||||||
#if (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) && defined(WITH_GZFILEOP)
|
|
||||||
ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *);
|
|
||||||
ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int);
|
|
||||||
ZEXTERN z_off64_t ZEXPORT gztell64(gzFile);
|
|
||||||
ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* default memLevel */
|
|
||||||
#if MAX_MEM_LEVEL >= 8
|
|
||||||
# define DEF_MEM_LEVEL 8
|
|
||||||
#else
|
|
||||||
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* default i/o buffer size -- double this for output when reading (this and
|
|
||||||
twice this must be able to fit in an unsigned type) */
|
|
||||||
#define GZBUFSIZE 8192
|
|
||||||
|
|
||||||
/* gzip modes, also provide a little integrity check on the passed structure */
|
|
||||||
#define GZ_NONE 0
|
|
||||||
#define GZ_READ 7247
|
|
||||||
#define GZ_WRITE 31153
|
|
||||||
#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */
|
|
||||||
|
|
||||||
/* values for gz_state how */
|
|
||||||
#define LOOK 0 /* look for a gzip header */
|
|
||||||
#define COPY 1 /* copy input directly */
|
|
||||||
#define GZIP 2 /* decompress a gzip stream */
|
|
||||||
|
|
||||||
/* internal gzip file state data structure */
|
|
||||||
typedef struct {
|
|
||||||
/* exposed contents for gzgetc() macro */
|
|
||||||
struct gzFile_s x; /* "x" for exposed */
|
|
||||||
/* x.have: number of bytes available at x.next */
|
|
||||||
/* x.next: next output data to deliver or write */
|
|
||||||
/* x.pos: current position in uncompressed data */
|
|
||||||
/* used for both reading and writing */
|
|
||||||
int mode; /* see gzip modes above */
|
|
||||||
int fd; /* file descriptor */
|
|
||||||
char *path; /* path or fd for error messages */
|
|
||||||
unsigned size; /* buffer size, zero if not allocated yet */
|
|
||||||
unsigned want; /* requested buffer size, default is GZBUFSIZE */
|
|
||||||
unsigned char *in; /* input buffer (double-sized when writing) */
|
|
||||||
unsigned char *out; /* output buffer (double-sized when reading) */
|
|
||||||
int direct; /* 0 if processing gzip, 1 if transparent */
|
|
||||||
/* just for reading */
|
|
||||||
int how; /* 0: get header, 1: copy, 2: decompress */
|
|
||||||
z_off64_t start; /* where the gzip data started, for rewinding */
|
|
||||||
int eof; /* true if end of input file reached */
|
|
||||||
int past; /* true if read requested past end */
|
|
||||||
/* just for writing */
|
|
||||||
int level; /* compression level */
|
|
||||||
int strategy; /* compression strategy */
|
|
||||||
/* seek request */
|
|
||||||
z_off64_t skip; /* amount to skip (already rewound if backwards) */
|
|
||||||
int seek; /* true if seek request pending */
|
|
||||||
/* error information */
|
|
||||||
int err; /* error code */
|
|
||||||
char *msg; /* error message */
|
|
||||||
/* zlib inflate or deflate stream */
|
|
||||||
z_stream strm; /* stream structure in-place (not a pointer) */
|
|
||||||
} gz_state;
|
|
||||||
typedef gz_state *gz_statep;
|
|
||||||
|
|
||||||
/* shared functions */
|
|
||||||
void ZLIB_INTERNAL gz_error(gz_statep, int, const char *);
|
|
||||||
|
|
||||||
/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
|
|
||||||
value -- needed when comparing unsigned to z_off64_t, which is signed
|
|
||||||
(possible z_off64_t types off_t, off64_t, and long are all signed) */
|
|
||||||
#ifdef INT_MAX
|
|
||||||
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
|
|
||||||
#else
|
|
||||||
unsigned ZLIB_INTERNAL gz_intmax(void);
|
|
||||||
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* GZGUTS_H_ */
|
|
@ -1,518 +0,0 @@
|
|||||||
/* gzlib.c -- zlib functions common to reading and writing gzip files
|
|
||||||
* Copyright (C) 2004, 2010, 2011, 2012, 2013 Mark Adler
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "gzguts.h"
|
|
||||||
|
|
||||||
#if defined(WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__)
|
|
||||||
# define LSEEK _lseeki64
|
|
||||||
#else
|
|
||||||
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
|
|
||||||
# define LSEEK lseek64
|
|
||||||
#else
|
|
||||||
# define LSEEK lseek
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Local functions */
|
|
||||||
local void gz_reset(gz_statep);
|
|
||||||
local gzFile gz_open(const void *, int, const char *);
|
|
||||||
|
|
||||||
/* Reset gzip file state */
|
|
||||||
local void gz_reset(gz_statep state) {
|
|
||||||
state->x.have = 0; /* no output data available */
|
|
||||||
if (state->mode == GZ_READ) { /* for reading ... */
|
|
||||||
state->eof = 0; /* not at end of file */
|
|
||||||
state->past = 0; /* have not read past end yet */
|
|
||||||
state->how = LOOK; /* look for gzip header */
|
|
||||||
}
|
|
||||||
state->seek = 0; /* no seek request pending */
|
|
||||||
gz_error(state, Z_OK, NULL); /* clear error */
|
|
||||||
state->x.pos = 0; /* no uncompressed data yet */
|
|
||||||
state->strm.avail_in = 0; /* no input data yet */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open a gzip file either by name or file descriptor. */
|
|
||||||
local gzFile gz_open(const void *path, int fd, const char *mode) {
|
|
||||||
gz_statep state;
|
|
||||||
size_t len;
|
|
||||||
int oflag;
|
|
||||||
#ifdef O_CLOEXEC
|
|
||||||
int cloexec = 0;
|
|
||||||
#endif
|
|
||||||
#ifdef O_EXCL
|
|
||||||
int exclusive = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* check input */
|
|
||||||
if (path == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* allocate gzFile structure to return */
|
|
||||||
state = (gz_statep)malloc(sizeof(gz_state));
|
|
||||||
if (state == NULL)
|
|
||||||
return NULL;
|
|
||||||
state->size = 0; /* no buffers allocated yet */
|
|
||||||
state->want = GZBUFSIZE; /* requested buffer size */
|
|
||||||
state->msg = NULL; /* no error message yet */
|
|
||||||
|
|
||||||
/* interpret mode */
|
|
||||||
state->mode = GZ_NONE;
|
|
||||||
state->level = Z_DEFAULT_COMPRESSION;
|
|
||||||
state->strategy = Z_DEFAULT_STRATEGY;
|
|
||||||
state->direct = 0;
|
|
||||||
while (*mode) {
|
|
||||||
if (*mode >= '0' && *mode <= '9') {
|
|
||||||
state->level = *mode - '0';
|
|
||||||
} else {
|
|
||||||
switch (*mode) {
|
|
||||||
case 'r':
|
|
||||||
state->mode = GZ_READ;
|
|
||||||
break;
|
|
||||||
#ifndef NO_GZCOMPRESS
|
|
||||||
case 'w':
|
|
||||||
state->mode = GZ_WRITE;
|
|
||||||
break;
|
|
||||||
case 'a':
|
|
||||||
state->mode = GZ_APPEND;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case '+': /* can't read and write at the same time */
|
|
||||||
free(state);
|
|
||||||
return NULL;
|
|
||||||
case 'b': /* ignore -- will request binary anyway */
|
|
||||||
break;
|
|
||||||
#ifdef O_CLOEXEC
|
|
||||||
case 'e':
|
|
||||||
cloexec = 1;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#ifdef O_EXCL
|
|
||||||
case 'x':
|
|
||||||
exclusive = 1;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case 'f':
|
|
||||||
state->strategy = Z_FILTERED;
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
state->strategy = Z_HUFFMAN_ONLY;
|
|
||||||
break;
|
|
||||||
case 'R':
|
|
||||||
state->strategy = Z_RLE;
|
|
||||||
break;
|
|
||||||
case 'F':
|
|
||||||
state->strategy = Z_FIXED;
|
|
||||||
break;
|
|
||||||
case 'T':
|
|
||||||
state->direct = 1;
|
|
||||||
break;
|
|
||||||
default: /* could consider as an error, but just ignore */
|
|
||||||
{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mode++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* must provide an "r", "w", or "a" */
|
|
||||||
if (state->mode == GZ_NONE) {
|
|
||||||
free(state);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* can't force transparent read */
|
|
||||||
if (state->mode == GZ_READ) {
|
|
||||||
if (state->direct) {
|
|
||||||
free(state);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
state->direct = 1; /* for empty file */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* save the path name for error messages */
|
|
||||||
#ifdef WIDECHAR
|
|
||||||
if (fd == -2) {
|
|
||||||
len = wcstombs(NULL, path, 0);
|
|
||||||
if (len == (size_t)-1)
|
|
||||||
len = 0;
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
len = strlen((const char *)path);
|
|
||||||
state->path = (char *)malloc(len + 1);
|
|
||||||
if (state->path == NULL) {
|
|
||||||
free(state);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#ifdef WIDECHAR
|
|
||||||
if (fd == -2)
|
|
||||||
if (len) {
|
|
||||||
wcstombs(state->path, path, len + 1);
|
|
||||||
} else {
|
|
||||||
*(state->path) = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
snprintf(state->path, len + 1, "%s", (const char *)path);
|
|
||||||
|
|
||||||
/* compute the flags for open() */
|
|
||||||
oflag =
|
|
||||||
#ifdef O_LARGEFILE
|
|
||||||
O_LARGEFILE |
|
|
||||||
#endif
|
|
||||||
#ifdef O_BINARY
|
|
||||||
O_BINARY |
|
|
||||||
#endif
|
|
||||||
#ifdef O_CLOEXEC
|
|
||||||
(cloexec ? O_CLOEXEC : 0) |
|
|
||||||
#endif
|
|
||||||
(state->mode == GZ_READ ?
|
|
||||||
O_RDONLY :
|
|
||||||
(O_WRONLY | O_CREAT |
|
|
||||||
#ifdef O_EXCL
|
|
||||||
(exclusive ? O_EXCL : 0) |
|
|
||||||
#endif
|
|
||||||
(state->mode == GZ_WRITE ?
|
|
||||||
O_TRUNC :
|
|
||||||
O_APPEND)));
|
|
||||||
|
|
||||||
/* open the file with the appropriate flags (or just use fd) */
|
|
||||||
state->fd = fd > -1 ? fd : (
|
|
||||||
#if defined(WIN32) || defined(__MINGW__)
|
|
||||||
fd == -2 ? _wopen(path, oflag, 0666) :
|
|
||||||
#elif __CYGWIN__
|
|
||||||
fd == -2 ? open(state->path, oflag, 0666) :
|
|
||||||
#endif
|
|
||||||
open((const char *)path, oflag, 0666));
|
|
||||||
if (state->fd == -1) {
|
|
||||||
free(state->path);
|
|
||||||
free(state);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (state->mode == GZ_APPEND) {
|
|
||||||
LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */
|
|
||||||
state->mode = GZ_WRITE; /* simplify later checks */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* save the current position for rewinding (only if reading) */
|
|
||||||
if (state->mode == GZ_READ) {
|
|
||||||
state->start = LSEEK(state->fd, 0, SEEK_CUR);
|
|
||||||
if (state->start == -1) state->start = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* initialize stream */
|
|
||||||
gz_reset(state);
|
|
||||||
|
|
||||||
/* return stream */
|
|
||||||
return (gzFile)state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
gzFile ZEXPORT gzopen(const char *path, const char *mode) {
|
|
||||||
return gz_open(path, -1, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
gzFile ZEXPORT gzopen64(const char *path, const char *mode) {
|
|
||||||
return gz_open(path, -1, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
gzFile ZEXPORT gzdopen(int fd, const char *mode) {
|
|
||||||
char *path; /* identifier for error messages */
|
|
||||||
gzFile gz;
|
|
||||||
|
|
||||||
if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
|
|
||||||
return NULL;
|
|
||||||
snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */
|
|
||||||
gz = gz_open(path, fd, mode);
|
|
||||||
free(path);
|
|
||||||
return gz;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
#ifdef WIDECHAR
|
|
||||||
gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode) {
|
|
||||||
return gz_open(path, -2, mode);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
int ZEXPORT gzbuffer(gzFile file, unsigned size) {
|
|
||||||
gz_statep state;
|
|
||||||
|
|
||||||
/* get internal structure and check integrity */
|
|
||||||
if (file == NULL)
|
|
||||||
return -1;
|
|
||||||
state = (gz_statep)file;
|
|
||||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* make sure we haven't already allocated memory */
|
|
||||||
if (state->size != 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* check and set requested size */
|
|
||||||
if ((size << 1) < size)
|
|
||||||
return -1; /* need to be able to double it */
|
|
||||||
if (size < 2)
|
|
||||||
size = 2; /* need two bytes to check magic header */
|
|
||||||
state->want = size;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
int ZEXPORT gzrewind(gzFile file) {
|
|
||||||
gz_statep state;
|
|
||||||
|
|
||||||
/* get internal structure */
|
|
||||||
if (file == NULL)
|
|
||||||
return -1;
|
|
||||||
state = (gz_statep)file;
|
|
||||||
|
|
||||||
/* check that we're reading and that there's no error */
|
|
||||||
if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* back up and start over */
|
|
||||||
if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
|
|
||||||
return -1;
|
|
||||||
gz_reset(state);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) {
|
|
||||||
unsigned n;
|
|
||||||
z_off64_t ret;
|
|
||||||
gz_statep state;
|
|
||||||
|
|
||||||
/* get internal structure and check integrity */
|
|
||||||
if (file == NULL)
|
|
||||||
return -1;
|
|
||||||
state = (gz_statep)file;
|
|
||||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* check that there's no error */
|
|
||||||
if (state->err != Z_OK && state->err != Z_BUF_ERROR)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* can only seek from start or relative to current position */
|
|
||||||
if (whence != SEEK_SET && whence != SEEK_CUR)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* normalize offset to a SEEK_CUR specification */
|
|
||||||
if (whence == SEEK_SET)
|
|
||||||
offset -= state->x.pos;
|
|
||||||
else if (state->seek)
|
|
||||||
offset += state->skip;
|
|
||||||
state->seek = 0;
|
|
||||||
|
|
||||||
/* if within raw area while reading, just go there */
|
|
||||||
if (state->mode == GZ_READ && state->how == COPY && state->x.pos + offset >= 0) {
|
|
||||||
ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
|
|
||||||
if (ret == -1)
|
|
||||||
return -1;
|
|
||||||
state->x.have = 0;
|
|
||||||
state->eof = 0;
|
|
||||||
state->past = 0;
|
|
||||||
state->seek = 0;
|
|
||||||
gz_error(state, Z_OK, NULL);
|
|
||||||
state->strm.avail_in = 0;
|
|
||||||
state->x.pos += offset;
|
|
||||||
return state->x.pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* calculate skip amount, rewinding if needed for back seek when reading */
|
|
||||||
if (offset < 0) {
|
|
||||||
if (state->mode != GZ_READ) /* writing -- can't go backwards */
|
|
||||||
return -1;
|
|
||||||
offset += state->x.pos;
|
|
||||||
if (offset < 0) /* before start of file! */
|
|
||||||
return -1;
|
|
||||||
if (gzrewind(file) == -1) /* rewind, then skip to offset */
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if reading, skip what's in output buffer (one less gzgetc() check) */
|
|
||||||
if (state->mode == GZ_READ) {
|
|
||||||
n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? (unsigned)offset : state->x.have;
|
|
||||||
state->x.have -= n;
|
|
||||||
state->x.next += n;
|
|
||||||
state->x.pos += n;
|
|
||||||
offset -= n;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* request skip (if not zero) */
|
|
||||||
if (offset) {
|
|
||||||
state->seek = 1;
|
|
||||||
state->skip = offset;
|
|
||||||
}
|
|
||||||
return state->x.pos + offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) {
|
|
||||||
z_off64_t ret;
|
|
||||||
|
|
||||||
ret = gzseek64(file, (z_off64_t)offset, whence);
|
|
||||||
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
z_off64_t ZEXPORT gztell64(gzFile file) {
|
|
||||||
gz_statep state;
|
|
||||||
|
|
||||||
/* get internal structure and check integrity */
|
|
||||||
if (file == NULL)
|
|
||||||
return -1;
|
|
||||||
state = (gz_statep)file;
|
|
||||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* return position */
|
|
||||||
return state->x.pos + (state->seek ? state->skip : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
z_off_t ZEXPORT gztell(gzFile file) {
|
|
||||||
z_off64_t ret;
|
|
||||||
|
|
||||||
ret = gztell64(file);
|
|
||||||
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
z_off64_t ZEXPORT gzoffset64(gzFile file) {
|
|
||||||
z_off64_t offset;
|
|
||||||
gz_statep state;
|
|
||||||
|
|
||||||
/* get internal structure and check integrity */
|
|
||||||
if (file == NULL)
|
|
||||||
return -1;
|
|
||||||
state = (gz_statep)file;
|
|
||||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* compute and return effective offset in file */
|
|
||||||
offset = LSEEK(state->fd, 0, SEEK_CUR);
|
|
||||||
if (offset == -1)
|
|
||||||
return -1;
|
|
||||||
if (state->mode == GZ_READ) /* reading */
|
|
||||||
offset -= state->strm.avail_in; /* don't count buffered input */
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
z_off_t ZEXPORT gzoffset(gzFile file) {
|
|
||||||
z_off64_t ret;
|
|
||||||
|
|
||||||
ret = gzoffset64(file);
|
|
||||||
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
int ZEXPORT gzeof(gzFile file) {
|
|
||||||
gz_statep state;
|
|
||||||
|
|
||||||
/* get internal structure and check integrity */
|
|
||||||
if (file == NULL)
|
|
||||||
return 0;
|
|
||||||
state = (gz_statep)file;
|
|
||||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* return end-of-file state */
|
|
||||||
return state->mode == GZ_READ ? state->past : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
const char * ZEXPORT gzerror(gzFile file, int *errnum) {
|
|
||||||
gz_statep state;
|
|
||||||
|
|
||||||
/* get internal structure and check integrity */
|
|
||||||
if (file == NULL)
|
|
||||||
return NULL;
|
|
||||||
state = (gz_statep)file;
|
|
||||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* return error information */
|
|
||||||
if (errnum != NULL)
|
|
||||||
*errnum = state->err;
|
|
||||||
return state->err == Z_MEM_ERROR ? "out of memory" : (state->msg == NULL ? "" : state->msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
void ZEXPORT gzclearerr(gzFile file) {
|
|
||||||
gz_statep state;
|
|
||||||
|
|
||||||
/* get internal structure and check integrity */
|
|
||||||
if (file == NULL)
|
|
||||||
return;
|
|
||||||
state = (gz_statep)file;
|
|
||||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* clear error and end-of-file */
|
|
||||||
if (state->mode == GZ_READ) {
|
|
||||||
state->eof = 0;
|
|
||||||
state->past = 0;
|
|
||||||
}
|
|
||||||
gz_error(state, Z_OK, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create an error message in allocated memory and set state->err and
|
|
||||||
state->msg accordingly. Free any previous error message already there. Do
|
|
||||||
not try to free or allocate space if the error is Z_MEM_ERROR (out of
|
|
||||||
memory). Simply save the error message as a static string. If there is an
|
|
||||||
allocation failure constructing the error message, then convert the error to
|
|
||||||
out of memory. */
|
|
||||||
void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) {
|
|
||||||
/* free previously allocated message and clear */
|
|
||||||
if (state->msg != NULL) {
|
|
||||||
if (state->err != Z_MEM_ERROR)
|
|
||||||
free(state->msg);
|
|
||||||
state->msg = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
|
|
||||||
if (err != Z_OK && err != Z_BUF_ERROR)
|
|
||||||
state->x.have = 0;
|
|
||||||
|
|
||||||
/* set error code, and if no message, then done */
|
|
||||||
state->err = err;
|
|
||||||
if (msg == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* for an out of memory error, return literal string when requested */
|
|
||||||
if (err == Z_MEM_ERROR)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* construct error message with path */
|
|
||||||
if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) {
|
|
||||||
state->err = Z_MEM_ERROR;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, "%s%s%s", state->path, ": ", msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef INT_MAX
|
|
||||||
/* portably return maximum value for an int (when limits.h presumed not
|
|
||||||
available) -- we need to do this to cover cases where 2's complement not
|
|
||||||
used, since C standard permits 1's complement and sign-bit representations,
|
|
||||||
otherwise we could just use ((unsigned)-1) >> 1 */
|
|
||||||
unsigned ZLIB_INTERNAL gz_intmax() {
|
|
||||||
unsigned p, q;
|
|
||||||
|
|
||||||
p = 1;
|
|
||||||
do {
|
|
||||||
q = p;
|
|
||||||
p <<= 1;
|
|
||||||
p++;
|
|
||||||
} while (p > q);
|
|
||||||
return q >> 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,538 +0,0 @@
|
|||||||
/* gzread.c -- zlib functions for reading gzip files
|
|
||||||
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "gzguts.h"
|
|
||||||
|
|
||||||
/* Local functions */
|
|
||||||
local int gz_load(gz_statep, unsigned char *, unsigned, unsigned *);
|
|
||||||
local int gz_avail(gz_statep);
|
|
||||||
local int gz_look(gz_statep);
|
|
||||||
local int gz_decomp(gz_statep);
|
|
||||||
local int gz_fetch(gz_statep);
|
|
||||||
local int gz_skip(gz_statep, z_off64_t);
|
|
||||||
|
|
||||||
/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
|
|
||||||
state->fd, and update state->eof, state->err, and state->msg as appropriate.
|
|
||||||
This function needs to loop on read(), since read() is not guaranteed to
|
|
||||||
read the number of bytes requested, depending on the type of descriptor. */
|
|
||||||
local int gz_load(gz_statep state, unsigned char *buf, unsigned len, unsigned *have) {
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
*have = 0;
|
|
||||||
do {
|
|
||||||
ret = read(state->fd, buf + *have, len - *have);
|
|
||||||
if (ret <= 0)
|
|
||||||
break;
|
|
||||||
*have += ret;
|
|
||||||
} while (*have < len);
|
|
||||||
if (ret < 0) {
|
|
||||||
gz_error(state, Z_ERRNO, zstrerror());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (ret == 0)
|
|
||||||
state->eof = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load up input buffer and set eof flag if last data loaded -- return -1 on
|
|
||||||
error, 0 otherwise. Note that the eof flag is set when the end of the input
|
|
||||||
file is reached, even though there may be unused data in the buffer. Once
|
|
||||||
that data has been used, no more attempts will be made to read the file.
|
|
||||||
If strm->avail_in != 0, then the current data is moved to the beginning of
|
|
||||||
the input buffer, and then the remainder of the buffer is loaded with the
|
|
||||||
available data from the input file. */
|
|
||||||
local int gz_avail(gz_statep state) {
|
|
||||||
unsigned got;
|
|
||||||
z_stream *strm = &(state->strm);
|
|
||||||
|
|
||||||
if (state->err != Z_OK && state->err != Z_BUF_ERROR)
|
|
||||||
return -1;
|
|
||||||
if (state->eof == 0) {
|
|
||||||
if (strm->avail_in) { /* copy what's there to the start */
|
|
||||||
unsigned char *p = state->in;
|
|
||||||
unsigned const char *q = strm->next_in;
|
|
||||||
unsigned n = strm->avail_in;
|
|
||||||
do {
|
|
||||||
*p++ = *q++;
|
|
||||||
} while (--n);
|
|
||||||
}
|
|
||||||
if (gz_load(state, state->in + strm->avail_in, state->size - strm->avail_in, &got) == -1)
|
|
||||||
return -1;
|
|
||||||
strm->avail_in += got;
|
|
||||||
strm->next_in = state->in;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Look for gzip header, set up for inflate or copy. state->x.have must be 0.
|
|
||||||
If this is the first time in, allocate required memory. state->how will be
|
|
||||||
left unchanged if there is no more input data available, will be set to COPY
|
|
||||||
if there is no gzip header and direct copying will be performed, or it will
|
|
||||||
be set to GZIP for decompression. If direct copying, then leftover input
|
|
||||||
data from the input buffer will be copied to the output buffer. In that
|
|
||||||
case, all further file reads will be directly to either the output buffer or
|
|
||||||
a user buffer. If decompressing, the inflate state will be initialized.
|
|
||||||
gz_look() will return 0 on success or -1 on failure. */
|
|
||||||
local int gz_look(gz_statep state) {
|
|
||||||
z_stream *strm = &(state->strm);
|
|
||||||
|
|
||||||
/* allocate read buffers and inflate memory */
|
|
||||||
if (state->size == 0) {
|
|
||||||
/* allocate buffers */
|
|
||||||
state->in = (unsigned char *)malloc(state->want);
|
|
||||||
state->out = (unsigned char *)malloc(state->want << 1);
|
|
||||||
if (state->in == NULL || state->out == NULL) {
|
|
||||||
if (state->out != NULL)
|
|
||||||
free(state->out);
|
|
||||||
if (state->in != NULL)
|
|
||||||
free(state->in);
|
|
||||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
state->size = state->want;
|
|
||||||
|
|
||||||
/* allocate inflate memory */
|
|
||||||
state->strm.zalloc = Z_NULL;
|
|
||||||
state->strm.zfree = Z_NULL;
|
|
||||||
state->strm.opaque = Z_NULL;
|
|
||||||
state->strm.avail_in = 0;
|
|
||||||
state->strm.next_in = Z_NULL;
|
|
||||||
if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */
|
|
||||||
free(state->out);
|
|
||||||
free(state->in);
|
|
||||||
state->size = 0;
|
|
||||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get at least the magic bytes in the input buffer */
|
|
||||||
if (strm->avail_in < 2) {
|
|
||||||
if (gz_avail(state) == -1)
|
|
||||||
return -1;
|
|
||||||
if (strm->avail_in == 0)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* look for gzip magic bytes -- if there, do gzip decoding (note: there is
|
|
||||||
a logical dilemma here when considering the case of a partially written
|
|
||||||
gzip file, to wit, if a single 31 byte is written, then we cannot tell
|
|
||||||
whether this is a single-byte file, or just a partially written gzip
|
|
||||||
file -- for here we assume that if a gzip file is being written, then
|
|
||||||
the header will be written in a single operation, so that reading a
|
|
||||||
single byte is sufficient indication that it is not a gzip file) */
|
|
||||||
if (strm->avail_in > 1 &&
|
|
||||||
strm->next_in[0] == 31 && strm->next_in[1] == 139) {
|
|
||||||
inflateReset(strm);
|
|
||||||
state->how = GZIP;
|
|
||||||
state->direct = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* no gzip header -- if we were decoding gzip before, then this is trailing
|
|
||||||
garbage. Ignore the trailing garbage and finish. */
|
|
||||||
if (state->direct == 0) {
|
|
||||||
strm->avail_in = 0;
|
|
||||||
state->eof = 1;
|
|
||||||
state->x.have = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* doing raw i/o, copy any leftover input to output -- this assumes that
|
|
||||||
the output buffer is larger than the input buffer, which also assures
|
|
||||||
space for gzungetc() */
|
|
||||||
state->x.next = state->out;
|
|
||||||
if (strm->avail_in) {
|
|
||||||
memcpy(state->x.next, strm->next_in, strm->avail_in);
|
|
||||||
state->x.have = strm->avail_in;
|
|
||||||
strm->avail_in = 0;
|
|
||||||
}
|
|
||||||
state->how = COPY;
|
|
||||||
state->direct = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decompress from input to the provided next_out and avail_out in the state.
|
|
||||||
On return, state->x.have and state->x.next point to the just decompressed
|
|
||||||
data. If the gzip stream completes, state->how is reset to LOOK to look for
|
|
||||||
the next gzip stream or raw data, once state->x.have is depleted. Returns 0
|
|
||||||
on success, -1 on failure. */
|
|
||||||
local int gz_decomp(gz_statep state) {
|
|
||||||
int ret = Z_OK;
|
|
||||||
unsigned had;
|
|
||||||
z_stream *strm = &(state->strm);
|
|
||||||
|
|
||||||
/* fill output buffer up to end of deflate stream */
|
|
||||||
had = strm->avail_out;
|
|
||||||
do {
|
|
||||||
/* get more input for inflate() */
|
|
||||||
if (strm->avail_in == 0 && gz_avail(state) == -1)
|
|
||||||
return -1;
|
|
||||||
if (strm->avail_in == 0) {
|
|
||||||
gz_error(state, Z_BUF_ERROR, "unexpected end of file");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* decompress and handle errors */
|
|
||||||
ret = inflate(strm, Z_NO_FLUSH);
|
|
||||||
if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
|
|
||||||
gz_error(state, Z_STREAM_ERROR, "internal error: inflate stream corrupt");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (ret == Z_MEM_ERROR) {
|
|
||||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
|
|
||||||
gz_error(state, Z_DATA_ERROR, strm->msg == NULL ? "compressed data error" : strm->msg);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} while (strm->avail_out && ret != Z_STREAM_END);
|
|
||||||
|
|
||||||
/* update available output */
|
|
||||||
state->x.have = had - strm->avail_out;
|
|
||||||
state->x.next = strm->next_out - state->x.have;
|
|
||||||
|
|
||||||
/* if the gzip stream completed successfully, look for another */
|
|
||||||
if (ret == Z_STREAM_END)
|
|
||||||
state->how = LOOK;
|
|
||||||
|
|
||||||
/* good decompression */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fetch data and put it in the output buffer. Assumes state->x.have is 0.
|
|
||||||
Data is either copied from the input file or decompressed from the input
|
|
||||||
file depending on state->how. If state->how is LOOK, then a gzip header is
|
|
||||||
looked for to determine whether to copy or decompress. Returns -1 on error,
|
|
||||||
otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the
|
|
||||||
end of the input file has been reached and all data has been processed. */
|
|
||||||
local int gz_fetch(gz_statep state) {
|
|
||||||
z_stream *strm = &(state->strm);
|
|
||||||
|
|
||||||
do {
|
|
||||||
switch (state->how) {
|
|
||||||
case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */
|
|
||||||
if (gz_look(state) == -1)
|
|
||||||
return -1;
|
|
||||||
if (state->how == LOOK)
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
case COPY: /* -> COPY */
|
|
||||||
if (gz_load(state, state->out, state->size << 1, &(state->x.have))
|
|
||||||
== -1)
|
|
||||||
return -1;
|
|
||||||
state->x.next = state->out;
|
|
||||||
return 0;
|
|
||||||
case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */
|
|
||||||
strm->avail_out = state->size << 1;
|
|
||||||
strm->next_out = state->out;
|
|
||||||
if (gz_decomp(state) == -1)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} while (state->x.have == 0 && (!state->eof || strm->avail_in));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */
|
|
||||||
local int gz_skip(gz_statep state, z_off64_t len) {
|
|
||||||
unsigned n;
|
|
||||||
|
|
||||||
/* skip over len bytes or reach end-of-file, whichever comes first */
|
|
||||||
while (len)
|
|
||||||
/* skip over whatever is in output buffer */
|
|
||||||
if (state->x.have) {
|
|
||||||
n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?
|
|
||||||
(unsigned)len : state->x.have;
|
|
||||||
state->x.have -= n;
|
|
||||||
state->x.next += n;
|
|
||||||
state->x.pos += n;
|
|
||||||
len -= n;
|
|
||||||
} else if (state->eof && state->strm.avail_in == 0) {
|
|
||||||
/* output buffer empty -- return if we're at the end of the input */
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
/* need more data to skip -- load up output buffer */
|
|
||||||
/* get more output, looking for header if required */
|
|
||||||
if (gz_fetch(state) == -1)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
int ZEXPORT gzread(gzFile file, void *buf, unsigned len) {
|
|
||||||
unsigned got, n;
|
|
||||||
gz_statep state;
|
|
||||||
z_stream *strm;
|
|
||||||
|
|
||||||
/* get internal structure */
|
|
||||||
if (file == NULL)
|
|
||||||
return -1;
|
|
||||||
state = (gz_statep)file;
|
|
||||||
strm = &(state->strm);
|
|
||||||
|
|
||||||
/* check that we're reading and that there's no (serious) error */
|
|
||||||
if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* since an int is returned, make sure len fits in one, otherwise return
|
|
||||||
with an error (this avoids the flaw in the interface) */
|
|
||||||
if ((int)len < 0) {
|
|
||||||
gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if len is zero, avoid unnecessary operations */
|
|
||||||
if (len == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* process a skip request */
|
|
||||||
if (state->seek) {
|
|
||||||
state->seek = 0;
|
|
||||||
if (gz_skip(state, state->skip) == -1)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get len bytes to buf, or less than len if at the end */
|
|
||||||
got = 0;
|
|
||||||
do {
|
|
||||||
/* first just try copying data from the output buffer */
|
|
||||||
if (state->x.have) {
|
|
||||||
n = state->x.have > len ? len : state->x.have;
|
|
||||||
memcpy(buf, state->x.next, n);
|
|
||||||
state->x.next += n;
|
|
||||||
state->x.have -= n;
|
|
||||||
} else if (state->eof && strm->avail_in == 0) {
|
|
||||||
/* output buffer empty -- return if we're at the end of the input */
|
|
||||||
state->past = 1; /* tried to read past end */
|
|
||||||
break;
|
|
||||||
} else if (state->how == LOOK || len < (state->size << 1)) {
|
|
||||||
/* need output data -- for small len or new stream load up our output buffer */
|
|
||||||
/* get more output, looking for header if required */
|
|
||||||
if (gz_fetch(state) == -1)
|
|
||||||
return -1;
|
|
||||||
continue; /* no progress yet -- go back to copy above */
|
|
||||||
/* the copy above assures that we will leave with space in the
|
|
||||||
output buffer, allowing at least one gzungetc() to succeed */
|
|
||||||
} else if (state->how == COPY) { /* read directly */
|
|
||||||
/* large len -- read directly into user buffer */
|
|
||||||
if (gz_load(state, (unsigned char *)buf, len, &n) == -1)
|
|
||||||
return -1;
|
|
||||||
} else { /* state->how == GZIP */
|
|
||||||
/* large len -- decompress directly into user buffer */
|
|
||||||
strm->avail_out = len;
|
|
||||||
strm->next_out = (unsigned char *)buf;
|
|
||||||
if (gz_decomp(state) == -1)
|
|
||||||
return -1;
|
|
||||||
n = state->x.have;
|
|
||||||
state->x.have = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* update progress */
|
|
||||||
len -= n;
|
|
||||||
buf = (char *)buf + n;
|
|
||||||
got += n;
|
|
||||||
state->x.pos += n;
|
|
||||||
} while (len);
|
|
||||||
|
|
||||||
/* return number of bytes read into user buffer (will fit in int) */
|
|
||||||
return (int)got;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
#undef gzgetc
|
|
||||||
int ZEXPORT gzgetc(gzFile file) {
|
|
||||||
int ret;
|
|
||||||
unsigned char buf[1];
|
|
||||||
gz_statep state;
|
|
||||||
|
|
||||||
/* get internal structure */
|
|
||||||
if (file == NULL)
|
|
||||||
return -1;
|
|
||||||
state = (gz_statep)file;
|
|
||||||
|
|
||||||
/* check that we're reading and that there's no (serious) error */
|
|
||||||
if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* try output buffer (no need to check for skip request) */
|
|
||||||
if (state->x.have) {
|
|
||||||
state->x.have--;
|
|
||||||
state->x.pos++;
|
|
||||||
return *(state->x.next)++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* nothing there -- try gzread() */
|
|
||||||
ret = gzread(file, buf, 1);
|
|
||||||
return ret < 1 ? -1 : buf[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
int ZEXPORT gzgetc_(gzFile file) {
|
|
||||||
return gzgetc(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
int ZEXPORT gzungetc(int c, gzFile file) {
|
|
||||||
gz_statep state;
|
|
||||||
|
|
||||||
/* get internal structure */
|
|
||||||
if (file == NULL)
|
|
||||||
return -1;
|
|
||||||
state = (gz_statep)file;
|
|
||||||
|
|
||||||
/* check that we're reading and that there's no (serious) error */
|
|
||||||
if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* process a skip request */
|
|
||||||
if (state->seek) {
|
|
||||||
state->seek = 0;
|
|
||||||
if (gz_skip(state, state->skip) == -1)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* can't push EOF */
|
|
||||||
if (c < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* if output buffer empty, put byte at end (allows more pushing) */
|
|
||||||
if (state->x.have == 0) {
|
|
||||||
state->x.have = 1;
|
|
||||||
state->x.next = state->out + (state->size << 1) - 1;
|
|
||||||
state->x.next[0] = c;
|
|
||||||
state->x.pos--;
|
|
||||||
state->past = 0;
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if no room, give up (must have already done a gzungetc()) */
|
|
||||||
if (state->x.have == (state->size << 1)) {
|
|
||||||
gz_error(state, Z_DATA_ERROR, "out of room to push characters");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* slide output data if needed and insert byte before existing data */
|
|
||||||
if (state->x.next == state->out) {
|
|
||||||
unsigned char *src = state->out + state->x.have;
|
|
||||||
unsigned char *dest = state->out + (state->size << 1);
|
|
||||||
while (src > state->out)
|
|
||||||
*--dest = *--src;
|
|
||||||
state->x.next = dest;
|
|
||||||
}
|
|
||||||
state->x.have++;
|
|
||||||
state->x.next--;
|
|
||||||
state->x.next[0] = c;
|
|
||||||
state->x.pos--;
|
|
||||||
state->past = 0;
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
char * ZEXPORT gzgets(gzFile file, char *buf, int len) {
|
|
||||||
unsigned left, n;
|
|
||||||
char *str;
|
|
||||||
unsigned char *eol;
|
|
||||||
gz_statep state;
|
|
||||||
|
|
||||||
/* check parameters and get internal structure */
|
|
||||||
if (file == NULL || buf == NULL || len < 1)
|
|
||||||
return NULL;
|
|
||||||
state = (gz_statep)file;
|
|
||||||
|
|
||||||
/* check that we're reading and that there's no (serious) error */
|
|
||||||
if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* process a skip request */
|
|
||||||
if (state->seek) {
|
|
||||||
state->seek = 0;
|
|
||||||
if (gz_skip(state, state->skip) == -1)
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copy output bytes up to new line or len - 1, whichever comes first --
|
|
||||||
append a terminating zero to the string (we don't check for a zero in
|
|
||||||
the contents, let the user worry about that) */
|
|
||||||
str = buf;
|
|
||||||
left = (unsigned)len - 1;
|
|
||||||
if (left) do {
|
|
||||||
/* assure that something is in the output buffer */
|
|
||||||
if (state->x.have == 0 && gz_fetch(state) == -1)
|
|
||||||
return NULL; /* error */
|
|
||||||
if (state->x.have == 0) { /* end of file */
|
|
||||||
state->past = 1; /* read past end */
|
|
||||||
break; /* return what we have */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* look for end-of-line in current output buffer */
|
|
||||||
n = state->x.have > left ? left : state->x.have;
|
|
||||||
eol = (unsigned char *)memchr(state->x.next, '\n', n);
|
|
||||||
if (eol != NULL)
|
|
||||||
n = (unsigned)(eol - state->x.next) + 1;
|
|
||||||
|
|
||||||
/* copy through end-of-line, or remainder if not found */
|
|
||||||
memcpy(buf, state->x.next, n);
|
|
||||||
state->x.have -= n;
|
|
||||||
state->x.next += n;
|
|
||||||
state->x.pos += n;
|
|
||||||
left -= n;
|
|
||||||
buf += n;
|
|
||||||
} while (left && eol == NULL);
|
|
||||||
|
|
||||||
/* return terminated string, or if nothing, end of file */
|
|
||||||
if (buf == str)
|
|
||||||
return NULL;
|
|
||||||
buf[0] = 0;
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
int ZEXPORT gzdirect(gzFile file) {
|
|
||||||
gz_statep state;
|
|
||||||
|
|
||||||
/* get internal structure */
|
|
||||||
if (file == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
state = (gz_statep)file;
|
|
||||||
|
|
||||||
/* if the state is not known, but we can find out, then do so (this is
|
|
||||||
mainly for right after a gzopen() or gzdopen()) */
|
|
||||||
if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
|
|
||||||
(void)gz_look(state);
|
|
||||||
|
|
||||||
/* return 1 if transparent, 0 if processing a gzip stream */
|
|
||||||
return state->direct;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
int ZEXPORT gzclose_r(gzFile file) {
|
|
||||||
int ret, err;
|
|
||||||
gz_statep state;
|
|
||||||
|
|
||||||
/* get internal structure */
|
|
||||||
if (file == NULL)
|
|
||||||
return Z_STREAM_ERROR;
|
|
||||||
|
|
||||||
state = (gz_statep)file;
|
|
||||||
|
|
||||||
/* check that we're reading */
|
|
||||||
if (state->mode != GZ_READ)
|
|
||||||
return Z_STREAM_ERROR;
|
|
||||||
|
|
||||||
/* free memory and close file */
|
|
||||||
if (state->size) {
|
|
||||||
inflateEnd(&(state->strm));
|
|
||||||
free(state->out);
|
|
||||||
free(state->in);
|
|
||||||
}
|
|
||||||
err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
|
|
||||||
gz_error(state, Z_OK, NULL);
|
|
||||||
free(state->path);
|
|
||||||
ret = close(state->fd);
|
|
||||||
free(state);
|
|
||||||
return ret ? Z_ERRNO : err;
|
|
||||||
}
|
|
@ -1,457 +0,0 @@
|
|||||||
/* gzwrite.c -- zlib functions for writing gzip files
|
|
||||||
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include "gzguts.h"
|
|
||||||
|
|
||||||
/* Local functions */
|
|
||||||
local int gz_init(gz_statep);
|
|
||||||
local int gz_comp(gz_statep, int);
|
|
||||||
local int gz_zero(gz_statep, z_off64_t);
|
|
||||||
|
|
||||||
/* Initialize state for writing a gzip file. Mark initialization by setting
|
|
||||||
state->size to non-zero. Return -1 on failure or 0 on success. */
|
|
||||||
local int gz_init(gz_statep state) {
|
|
||||||
int ret;
|
|
||||||
z_stream *strm = &(state->strm);
|
|
||||||
|
|
||||||
/* allocate input buffer (double size for gzprintf) */
|
|
||||||
state->in = (unsigned char *)malloc(state->want << 1);
|
|
||||||
if (state->in == NULL) {
|
|
||||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* only need output buffer and deflate state if compressing */
|
|
||||||
if (!state->direct) {
|
|
||||||
/* allocate output buffer */
|
|
||||||
state->out = (unsigned char *)malloc(state->want);
|
|
||||||
if (state->out == NULL) {
|
|
||||||
free(state->in);
|
|
||||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* allocate deflate memory, set up for gzip compression */
|
|
||||||
strm->zalloc = Z_NULL;
|
|
||||||
strm->zfree = Z_NULL;
|
|
||||||
strm->opaque = Z_NULL;
|
|
||||||
ret = deflateInit2(strm, state->level, Z_DEFLATED, MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
|
|
||||||
if (ret != Z_OK) {
|
|
||||||
free(state->out);
|
|
||||||
free(state->in);
|
|
||||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
strm->next_in = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* mark state as initialized */
|
|
||||||
state->size = state->want;
|
|
||||||
|
|
||||||
/* initialize write buffer if compressing */
|
|
||||||
if (!state->direct) {
|
|
||||||
strm->avail_out = state->size;
|
|
||||||
strm->next_out = state->out;
|
|
||||||
state->x.next = strm->next_out;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Compress whatever is at avail_in and next_in and write to the output file.
|
|
||||||
Return -1 if there is an error writing to the output file, otherwise 0.
|
|
||||||
flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
|
|
||||||
then the deflate() state is reset to start a new gzip stream. If gz->direct
|
|
||||||
is true, then simply write to the output file without compressing, and
|
|
||||||
ignore flush. */
|
|
||||||
local int gz_comp(gz_statep state, int flush) {
|
|
||||||
int ret, got;
|
|
||||||
unsigned have;
|
|
||||||
z_stream *strm = &(state->strm);
|
|
||||||
|
|
||||||
/* allocate memory if this is the first time through */
|
|
||||||
if (state->size == 0 && gz_init(state) == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* write directly if requested */
|
|
||||||
if (state->direct) {
|
|
||||||
while (strm->avail_in) {
|
|
||||||
if ((got = write(state->fd, strm->next_in, strm->avail_in)) < 0) {
|
|
||||||
gz_error(state, Z_ERRNO, zstrerror());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
strm->avail_in -= got;
|
|
||||||
strm->next_in += got;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* run deflate() on provided input until it produces no more output */
|
|
||||||
ret = Z_OK;
|
|
||||||
do {
|
|
||||||
/* write out current buffer contents if full, or if flushing, but if
|
|
||||||
doing Z_FINISH then don't write until we get to Z_STREAM_END */
|
|
||||||
if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && (flush != Z_FINISH || ret == Z_STREAM_END))) {
|
|
||||||
while (strm->next_out > state->x.next) {
|
|
||||||
if ((got = write(state->fd, state->x.next, strm->next_out - state->x.next)) < 0) {
|
|
||||||
gz_error(state, Z_ERRNO, zstrerror());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
state->x.next += got;
|
|
||||||
}
|
|
||||||
if (strm->avail_out == 0) {
|
|
||||||
strm->avail_out = state->size;
|
|
||||||
strm->next_out = state->out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* compress */
|
|
||||||
have = strm->avail_out;
|
|
||||||
ret = deflate(strm, flush);
|
|
||||||
if (ret == Z_STREAM_ERROR) {
|
|
||||||
gz_error(state, Z_STREAM_ERROR, "internal error: deflate stream corrupt");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
have -= strm->avail_out;
|
|
||||||
} while (have);
|
|
||||||
|
|
||||||
/* if that completed a deflate stream, allow another to start */
|
|
||||||
if (flush == Z_FINISH)
|
|
||||||
deflateReset(strm);
|
|
||||||
|
|
||||||
/* all done, no errors */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Compress len zeros to output. Return -1 on error, 0 on success. */
|
|
||||||
local int gz_zero(gz_statep state, z_off64_t len) {
|
|
||||||
int first;
|
|
||||||
unsigned n;
|
|
||||||
z_stream *strm = &(state->strm);
|
|
||||||
|
|
||||||
/* consume whatever's left in the input buffer */
|
|
||||||
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* compress len zeros (len guaranteed > 0) */
|
|
||||||
first = 1;
|
|
||||||
while (len) {
|
|
||||||
n = GT_OFF(state->size) || (z_off64_t)state->size > len ? (unsigned)len : state->size;
|
|
||||||
if (first) {
|
|
||||||
memset(state->in, 0, n);
|
|
||||||
first = 0;
|
|
||||||
}
|
|
||||||
strm->avail_in = n;
|
|
||||||
strm->next_in = state->in;
|
|
||||||
state->x.pos += n;
|
|
||||||
if (gz_comp(state, Z_NO_FLUSH) == -1)
|
|
||||||
return -1;
|
|
||||||
len -= n;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
int ZEXPORT gzwrite(gzFile file, void const *buf, unsigned len) {
|
|
||||||
unsigned put = len;
|
|
||||||
gz_statep state;
|
|
||||||
z_stream *strm;
|
|
||||||
|
|
||||||
/* get internal structure */
|
|
||||||
if (file == NULL)
|
|
||||||
return 0;
|
|
||||||
state = (gz_statep)file;
|
|
||||||
strm = &(state->strm);
|
|
||||||
|
|
||||||
/* check that we're writing and that there's no error */
|
|
||||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* since an int is returned, make sure len fits in one, otherwise return
|
|
||||||
with an error (this avoids the flaw in the interface) */
|
|
||||||
if ((int)len < 0) {
|
|
||||||
gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if len is zero, avoid unnecessary operations */
|
|
||||||
if (len == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* allocate memory if this is the first time through */
|
|
||||||
if (state->size == 0 && gz_init(state) == -1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* check for seek request */
|
|
||||||
if (state->seek) {
|
|
||||||
state->seek = 0;
|
|
||||||
if (gz_zero(state, state->skip) == -1)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* for small len, copy to input buffer, otherwise compress directly */
|
|
||||||
if (len < state->size) {
|
|
||||||
/* copy to input buffer, compress when full */
|
|
||||||
do {
|
|
||||||
unsigned have, copy;
|
|
||||||
|
|
||||||
if (strm->avail_in == 0)
|
|
||||||
strm->next_in = state->in;
|
|
||||||
have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
|
|
||||||
copy = state->size - have;
|
|
||||||
if (copy > len)
|
|
||||||
copy = len;
|
|
||||||
memcpy(state->in + have, buf, copy);
|
|
||||||
strm->avail_in += copy;
|
|
||||||
state->x.pos += copy;
|
|
||||||
buf = (const char *)buf + copy;
|
|
||||||
len -= copy;
|
|
||||||
if (len && gz_comp(state, Z_NO_FLUSH) == -1)
|
|
||||||
return 0;
|
|
||||||
} while (len);
|
|
||||||
} else {
|
|
||||||
/* consume whatever's left in the input buffer */
|
|
||||||
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* directly compress user buffer to file */
|
|
||||||
strm->avail_in = len;
|
|
||||||
strm->next_in = (const unsigned char *)buf;
|
|
||||||
state->x.pos += len;
|
|
||||||
if (gz_comp(state, Z_NO_FLUSH) == -1)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* input was all buffered or compressed (put will fit in int) */
|
|
||||||
return (int)put;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
int ZEXPORT gzputc(gzFile file, int c) {
|
|
||||||
unsigned have;
|
|
||||||
unsigned char buf[1];
|
|
||||||
gz_statep state;
|
|
||||||
z_stream *strm;
|
|
||||||
|
|
||||||
/* get internal structure */
|
|
||||||
if (file == NULL)
|
|
||||||
return -1;
|
|
||||||
state = (gz_statep)file;
|
|
||||||
strm = &(state->strm);
|
|
||||||
|
|
||||||
/* check that we're writing and that there's no error */
|
|
||||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* check for seek request */
|
|
||||||
if (state->seek) {
|
|
||||||
state->seek = 0;
|
|
||||||
if (gz_zero(state, state->skip) == -1)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* try writing to input buffer for speed (state->size == 0 if buffer not
|
|
||||||
initialized) */
|
|
||||||
if (state->size) {
|
|
||||||
if (strm->avail_in == 0)
|
|
||||||
strm->next_in = state->in;
|
|
||||||
have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
|
|
||||||
if (have < state->size) {
|
|
||||||
state->in[have] = c;
|
|
||||||
strm->avail_in++;
|
|
||||||
state->x.pos++;
|
|
||||||
return c & 0xff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* no room in buffer or not initialized, use gz_write() */
|
|
||||||
buf[0] = c;
|
|
||||||
if (gzwrite(file, buf, 1) != 1)
|
|
||||||
return -1;
|
|
||||||
return c & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
int ZEXPORT gzputs(gzFile file, const char *str) {
|
|
||||||
int ret;
|
|
||||||
unsigned len;
|
|
||||||
|
|
||||||
/* write string */
|
|
||||||
len = (unsigned)strlen(str);
|
|
||||||
ret = gzwrite(file, str, len);
|
|
||||||
return ret == 0 && len != 0 ? -1 : ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) {
|
|
||||||
int len, left;
|
|
||||||
char *next;
|
|
||||||
gz_statep state;
|
|
||||||
z_stream *strm;
|
|
||||||
|
|
||||||
/* get internal structure */
|
|
||||||
if (file == NULL)
|
|
||||||
return -1;
|
|
||||||
state = (gz_statep)file;
|
|
||||||
strm = &(state->strm);
|
|
||||||
|
|
||||||
/* check that we're writing and that there's no error */
|
|
||||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* make sure we have some buffer space */
|
|
||||||
if (state->size == 0 && gz_init(state) == -1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* check for seek request */
|
|
||||||
if (state->seek) {
|
|
||||||
state->seek = 0;
|
|
||||||
if (gz_zero(state, state->skip) == -1)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* do the printf() into the input buffer, put length in len -- the input
|
|
||||||
buffer is double-sized just for this function, so there is guaranteed to
|
|
||||||
be state->size bytes available after the current contents */
|
|
||||||
if (strm->avail_in == 0)
|
|
||||||
strm->next_in = state->in;
|
|
||||||
next = (char *)(strm->next_in + strm->avail_in);
|
|
||||||
next[state->size - 1] = 0;
|
|
||||||
len = vsnprintf(next, state->size, format, va);
|
|
||||||
|
|
||||||
/* check that printf() results fit in buffer */
|
|
||||||
if (len == 0 || len >= state->size || next[state->size - 1] != 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* update buffer and position, compress first half if past that */
|
|
||||||
strm->avail_in += len;
|
|
||||||
state->x.pos += len;
|
|
||||||
if (strm->avail_in >= state->size) {
|
|
||||||
left = strm->avail_in - state->size;
|
|
||||||
strm->avail_in = state->size;
|
|
||||||
if (gz_comp(state, Z_NO_FLUSH) == -1)
|
|
||||||
return 0;
|
|
||||||
memcpy(state->in, state->in + state->size, left);
|
|
||||||
strm->next_in = state->in;
|
|
||||||
strm->avail_in = left;
|
|
||||||
}
|
|
||||||
return (int)len;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) {
|
|
||||||
va_list va;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
va_start(va, format);
|
|
||||||
ret = gzvprintf(file, format, va);
|
|
||||||
va_end(va);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
int ZEXPORT gzflush(gzFile file, int flush) {
|
|
||||||
gz_statep state;
|
|
||||||
|
|
||||||
/* get internal structure */
|
|
||||||
if (file == NULL)
|
|
||||||
return -1;
|
|
||||||
state = (gz_statep)file;
|
|
||||||
|
|
||||||
/* check that we're writing and that there's no error */
|
|
||||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
|
||||||
return Z_STREAM_ERROR;
|
|
||||||
|
|
||||||
/* check flush parameter */
|
|
||||||
if (flush < 0 || flush > Z_FINISH)
|
|
||||||
return Z_STREAM_ERROR;
|
|
||||||
|
|
||||||
/* check for seek request */
|
|
||||||
if (state->seek) {
|
|
||||||
state->seek = 0;
|
|
||||||
if (gz_zero(state, state->skip) == -1)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* compress remaining data with requested flush */
|
|
||||||
gz_comp(state, flush);
|
|
||||||
return state->err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
int ZEXPORT gzsetparams(gzFile file, int level, int strategy) {
|
|
||||||
gz_statep state;
|
|
||||||
z_stream *strm;
|
|
||||||
|
|
||||||
/* get internal structure */
|
|
||||||
if (file == NULL)
|
|
||||||
return Z_STREAM_ERROR;
|
|
||||||
state = (gz_statep)file;
|
|
||||||
strm = &(state->strm);
|
|
||||||
|
|
||||||
/* check that we're writing and that there's no error */
|
|
||||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
|
||||||
return Z_STREAM_ERROR;
|
|
||||||
|
|
||||||
/* if no change is requested, then do nothing */
|
|
||||||
if (level == state->level && strategy == state->strategy)
|
|
||||||
return Z_OK;
|
|
||||||
|
|
||||||
/* check for seek request */
|
|
||||||
if (state->seek) {
|
|
||||||
state->seek = 0;
|
|
||||||
if (gz_zero(state, state->skip) == -1)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* change compression parameters for subsequent input */
|
|
||||||
if (state->size) {
|
|
||||||
/* flush previous input with previous parameters before changing */
|
|
||||||
if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
|
|
||||||
return state->err;
|
|
||||||
deflateParams(strm, level, strategy);
|
|
||||||
}
|
|
||||||
state->level = level;
|
|
||||||
state->strategy = strategy;
|
|
||||||
return Z_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- see zlib.h -- */
|
|
||||||
int ZEXPORT gzclose_w(gzFile file) {
|
|
||||||
int ret = Z_OK;
|
|
||||||
gz_statep state;
|
|
||||||
|
|
||||||
/* get internal structure */
|
|
||||||
if (file == NULL)
|
|
||||||
return Z_STREAM_ERROR;
|
|
||||||
state = (gz_statep)file;
|
|
||||||
|
|
||||||
/* check that we're writing */
|
|
||||||
if (state->mode != GZ_WRITE)
|
|
||||||
return Z_STREAM_ERROR;
|
|
||||||
|
|
||||||
/* check for seek request */
|
|
||||||
if (state->seek) {
|
|
||||||
state->seek = 0;
|
|
||||||
if (gz_zero(state, state->skip) == -1)
|
|
||||||
ret = state->err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* flush, free memory, and close file */
|
|
||||||
if (gz_comp(state, Z_FINISH) == -1)
|
|
||||||
ret = state->err;
|
|
||||||
if (state->size) {
|
|
||||||
if (!state->direct) {
|
|
||||||
(void)deflateEnd(&(state->strm));
|
|
||||||
free(state->out);
|
|
||||||
}
|
|
||||||
free(state->in);
|
|
||||||
}
|
|
||||||
gz_error(state, Z_OK, NULL);
|
|
||||||
free(state->path);
|
|
||||||
if (close(state->fd) == -1)
|
|
||||||
ret = Z_ERRNO;
|
|
||||||
free(state);
|
|
||||||
return ret;
|
|
||||||
}
|
|
@ -1,612 +0,0 @@
|
|||||||
/* infback.c -- inflate using a call-back interface
|
|
||||||
* Copyright (C) 1995-2011 Mark Adler
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
This code is largely copied from inflate.c. Normally either infback.o or
|
|
||||||
inflate.o would be linked into an application--not both. The interface
|
|
||||||
with inffast.c is retained so that optimized assembler-coded versions of
|
|
||||||
inflate_fast() can be used with either inflate.c or infback.c.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "zutil.h"
|
|
||||||
#include "inftrees.h"
|
|
||||||
#include "inflate.h"
|
|
||||||
#include "inffast.h"
|
|
||||||
|
|
||||||
/* function prototypes */
|
|
||||||
local void fixedtables(struct inflate_state *state);
|
|
||||||
|
|
||||||
/*
|
|
||||||
strm provides memory allocation functions in zalloc and zfree, or
|
|
||||||
Z_NULL to use the library memory allocation functions.
|
|
||||||
|
|
||||||
windowBits is in the range 8..15, and window is a user-supplied
|
|
||||||
window and output buffer that is 2**windowBits bytes.
|
|
||||||
*/
|
|
||||||
int ZEXPORT inflateBackInit_(z_stream *strm, int windowBits, unsigned char *window,
|
|
||||||
const char *version, int stream_size) {
|
|
||||||
struct inflate_state *state;
|
|
||||||
|
|
||||||
if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || stream_size != (int)(sizeof(z_stream)))
|
|
||||||
return Z_VERSION_ERROR;
|
|
||||||
if (strm == Z_NULL || window == Z_NULL || windowBits < 8 || windowBits > 15)
|
|
||||||
return Z_STREAM_ERROR;
|
|
||||||
strm->msg = Z_NULL; /* in case we return an error */
|
|
||||||
if (strm->zalloc == (alloc_func)0) {
|
|
||||||
strm->zalloc = zcalloc;
|
|
||||||
strm->opaque = NULL;
|
|
||||||
}
|
|
||||||
if (strm->zfree == (free_func)0)
|
|
||||||
strm->zfree = zcfree;
|
|
||||||
state = (struct inflate_state *)ZALLOC(strm, 1, sizeof(struct inflate_state));
|
|
||||||
if (state == Z_NULL)
|
|
||||||
return Z_MEM_ERROR;
|
|
||||||
Tracev((stderr, "inflate: allocated\n"));
|
|
||||||
strm->state = (struct internal_state *)state;
|
|
||||||
state->dmax = 32768U;
|
|
||||||
state->wbits = windowBits;
|
|
||||||
state->wsize = 1U << windowBits;
|
|
||||||
state->window = window;
|
|
||||||
state->wnext = 0;
|
|
||||||
state->whave = 0;
|
|
||||||
return Z_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Return state with length and distance decoding tables and index sizes set to
|
|
||||||
fixed code decoding. Normally this returns fixed tables from inffixed.h.
|
|
||||||
If BUILDFIXED is defined, then instead this routine builds the tables the
|
|
||||||
first time it's called, and returns those tables the first time and
|
|
||||||
thereafter. This reduces the size of the code by about 2K bytes, in
|
|
||||||
exchange for a little execution time. However, BUILDFIXED should not be
|
|
||||||
used for threaded applications, since the rewriting of the tables and virgin
|
|
||||||
may not be thread-safe.
|
|
||||||
*/
|
|
||||||
local void fixedtables(struct inflate_state *state) {
|
|
||||||
#ifdef BUILDFIXED
|
|
||||||
static int virgin = 1;
|
|
||||||
static code *lenfix, *distfix;
|
|
||||||
static code fixed[544];
|
|
||||||
|
|
||||||
/* build fixed huffman tables if first call (may not be thread safe) */
|
|
||||||
if (virgin) {
|
|
||||||
unsigned sym, bits;
|
|
||||||
static code *next;
|
|
||||||
|
|
||||||
/* literal/length table */
|
|
||||||
sym = 0;
|
|
||||||
while (sym < 144) state->lens[sym++] = 8;
|
|
||||||
while (sym < 256) state->lens[sym++] = 9;
|
|
||||||
while (sym < 280) state->lens[sym++] = 7;
|
|
||||||
while (sym < 288) state->lens[sym++] = 8;
|
|
||||||
next = fixed;
|
|
||||||
lenfix = next;
|
|
||||||
bits = 9;
|
|
||||||
inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
|
|
||||||
|
|
||||||
/* distance table */
|
|
||||||
sym = 0;
|
|
||||||
while (sym < 32) state->lens[sym++] = 5;
|
|
||||||
distfix = next;
|
|
||||||
bits = 5;
|
|
||||||
inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
|
|
||||||
|
|
||||||
/* do this just once */
|
|
||||||
virgin = 0;
|
|
||||||
}
|
|
||||||
#else /* !BUILDFIXED */
|
|
||||||
# include "inffixed.h"
|
|
||||||
#endif /* BUILDFIXED */
|
|
||||||
state->lencode = lenfix;
|
|
||||||
state->lenbits = 9;
|
|
||||||
state->distcode = distfix;
|
|
||||||
state->distbits = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Macros for inflateBack(): */
|
|
||||||
|
|
||||||
/* Load returned state from inflate_fast() */
|
|
||||||
#define LOAD() \
|
|
||||||
do { \
|
|
||||||
put = strm->next_out; \
|
|
||||||
left = strm->avail_out; \
|
|
||||||
next = strm->next_in; \
|
|
||||||
have = strm->avail_in; \
|
|
||||||
hold = state->hold; \
|
|
||||||
bits = state->bits; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/* Set state from registers for inflate_fast() */
|
|
||||||
#define RESTORE() \
|
|
||||||
do { \
|
|
||||||
strm->next_out = put; \
|
|
||||||
strm->avail_out = left; \
|
|
||||||
strm->next_in = next; \
|
|
||||||
strm->avail_in = have; \
|
|
||||||
state->hold = hold; \
|
|
||||||
state->bits = bits; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/* Clear the input bit accumulator */
|
|
||||||
#define INITBITS() \
|
|
||||||
do { \
|
|
||||||
hold = 0; \
|
|
||||||
bits = 0; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/* Assure that some input is available. If input is requested, but denied,
|
|
||||||
then return a Z_BUF_ERROR from inflateBack(). */
|
|
||||||
#define PULL() \
|
|
||||||
do { \
|
|
||||||
if (have == 0) { \
|
|
||||||
have = in(in_desc, &next); \
|
|
||||||
if (have == 0) { \
|
|
||||||
next = Z_NULL; \
|
|
||||||
ret = Z_BUF_ERROR; \
|
|
||||||
goto inf_leave; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/* Get a byte of input into the bit accumulator, or return from inflateBack()
|
|
||||||
with an error if there is no input available. */
|
|
||||||
#define PULLBYTE() \
|
|
||||||
do { \
|
|
||||||
PULL(); \
|
|
||||||
have--; \
|
|
||||||
hold += (*next++ << bits); \
|
|
||||||
bits += 8; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/* Assure that there are at least n bits in the bit accumulator. If there is
|
|
||||||
not enough available input to do that, then return from inflateBack() with
|
|
||||||
an error. */
|
|
||||||
#define NEEDBITS(n) \
|
|
||||||
do { \
|
|
||||||
while (bits < (unsigned)(n)) \
|
|
||||||
PULLBYTE(); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/* Return the low n bits of the bit accumulator (n < 16) */
|
|
||||||
#define BITS(n) \
|
|
||||||
(hold & ((1U << (n)) - 1))
|
|
||||||
|
|
||||||
/* Remove n bits from the bit accumulator */
|
|
||||||
#define DROPBITS(n) \
|
|
||||||
do { \
|
|
||||||
hold >>= (n); \
|
|
||||||
bits -= (unsigned)(n); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/* Remove zero to seven bits as needed to go to a byte boundary */
|
|
||||||
#define BYTEBITS() \
|
|
||||||
do { \
|
|
||||||
hold >>= bits & 7; \
|
|
||||||
bits -= bits & 7; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/* Assure that some output space is available, by writing out the window
|
|
||||||
if it's full. If the write fails, return from inflateBack() with a
|
|
||||||
Z_BUF_ERROR. */
|
|
||||||
#define ROOM() \
|
|
||||||
do { \
|
|
||||||
if (left == 0) { \
|
|
||||||
put = state->window; \
|
|
||||||
left = state->wsize; \
|
|
||||||
state->whave = left; \
|
|
||||||
if (out(out_desc, put, left)) { \
|
|
||||||
ret = Z_BUF_ERROR; \
|
|
||||||
goto inf_leave; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/*
|
|
||||||
strm provides the memory allocation functions and window buffer on input,
|
|
||||||
and provides information on the unused input on return. For Z_DATA_ERROR
|
|
||||||
returns, strm will also provide an error message.
|
|
||||||
|
|
||||||
in() and out() are the call-back input and output functions. When
|
|
||||||
inflateBack() needs more input, it calls in(). When inflateBack() has
|
|
||||||
filled the window with output, or when it completes with data in the
|
|
||||||
window, it calls out() to write out the data. The application must not
|
|
||||||
change the provided input until in() is called again or inflateBack()
|
|
||||||
returns. The application must not change the window/output buffer until
|
|
||||||
inflateBack() returns.
|
|
||||||
|
|
||||||
in() and out() are called with a descriptor parameter provided in the
|
|
||||||
inflateBack() call. This parameter can be a structure that provides the
|
|
||||||
information required to do the read or write, as well as accumulated
|
|
||||||
information on the input and output such as totals and check values.
|
|
||||||
|
|
||||||
in() should return zero on failure. out() should return non-zero on
|
|
||||||
failure. If either in() or out() fails, than inflateBack() returns a
|
|
||||||
Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
|
|
||||||
was in() or out() that caused in the error. Otherwise, inflateBack()
|
|
||||||
returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
|
|
||||||
error, or Z_MEM_ERROR if it could not allocate memory for the state.
|
|
||||||
inflateBack() can also return Z_STREAM_ERROR if the input parameters
|
|
||||||
are not correct, i.e. strm is Z_NULL or the state was not initialized.
|
|
||||||
*/
|
|
||||||
int ZEXPORT inflateBack(z_stream *strm, in_func in, void *in_desc, out_func out, void *out_desc) {
|
|
||||||
struct inflate_state *state;
|
|
||||||
const unsigned char *next; /* next input */
|
|
||||||
unsigned char *put; /* next output */
|
|
||||||
unsigned have, left; /* available input and output */
|
|
||||||
uint32_t hold; /* bit buffer */
|
|
||||||
unsigned bits; /* bits in bit buffer */
|
|
||||||
unsigned copy; /* number of stored or match bytes to copy */
|
|
||||||
unsigned char *from; /* where to copy match bytes from */
|
|
||||||
code here; /* current decoding table entry */
|
|
||||||
code last; /* parent table entry */
|
|
||||||
unsigned len; /* length to copy for repeats, bits to drop */
|
|
||||||
int ret; /* return code */
|
|
||||||
static const uint16_t order[19] = /* permutation of code lengths */
|
|
||||||
{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
|
|
||||||
|
|
||||||
/* Check that the strm exists and that the state was initialized */
|
|
||||||
if (strm == Z_NULL || strm->state == Z_NULL)
|
|
||||||
return Z_STREAM_ERROR;
|
|
||||||
state = (struct inflate_state *)strm->state;
|
|
||||||
|
|
||||||
/* Reset the state */
|
|
||||||
strm->msg = Z_NULL;
|
|
||||||
state->mode = TYPE;
|
|
||||||
state->last = 0;
|
|
||||||
state->whave = 0;
|
|
||||||
next = strm->next_in;
|
|
||||||
have = next != Z_NULL ? strm->avail_in : 0;
|
|
||||||
hold = 0;
|
|
||||||
bits = 0;
|
|
||||||
put = state->window;
|
|
||||||
left = state->wsize;
|
|
||||||
|
|
||||||
/* Inflate until end of block marked as last */
|
|
||||||
for (;;)
|
|
||||||
switch (state->mode) {
|
|
||||||
case TYPE:
|
|
||||||
/* determine and dispatch block type */
|
|
||||||
if (state->last) {
|
|
||||||
BYTEBITS();
|
|
||||||
state->mode = DONE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
NEEDBITS(3);
|
|
||||||
state->last = BITS(1);
|
|
||||||
DROPBITS(1);
|
|
||||||
switch (BITS(2)) {
|
|
||||||
case 0: /* stored block */
|
|
||||||
Tracev((stderr, "inflate: stored block%s\n", state->last ? " (last)" : ""));
|
|
||||||
state->mode = STORED;
|
|
||||||
break;
|
|
||||||
case 1: /* fixed block */
|
|
||||||
fixedtables(state);
|
|
||||||
Tracev((stderr, "inflate: fixed codes block%s\n", state->last ? " (last)" : ""));
|
|
||||||
state->mode = LEN; /* decode codes */
|
|
||||||
break;
|
|
||||||
case 2: /* dynamic block */
|
|
||||||
Tracev((stderr, "inflate: dynamic codes block%s\n", state->last ? " (last)" : ""));
|
|
||||||
state->mode = TABLE;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
strm->msg = (char *)"invalid block type";
|
|
||||||
state->mode = BAD;
|
|
||||||
}
|
|
||||||
DROPBITS(2);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case STORED:
|
|
||||||
/* get and verify stored block length */
|
|
||||||
BYTEBITS(); /* go to byte boundary */
|
|
||||||
NEEDBITS(32);
|
|
||||||
if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
|
|
||||||
strm->msg = (char *)"invalid stored block lengths";
|
|
||||||
state->mode = BAD;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
state->length = (uint16_t)hold;
|
|
||||||
Tracev((stderr, "inflate: stored length %u\n", state->length));
|
|
||||||
INITBITS();
|
|
||||||
|
|
||||||
/* copy stored block from input to output */
|
|
||||||
while (state->length != 0) {
|
|
||||||
copy = state->length;
|
|
||||||
PULL();
|
|
||||||
ROOM();
|
|
||||||
if (copy > have)
|
|
||||||
copy = have;
|
|
||||||
if (copy > left)
|
|
||||||
copy = left;
|
|
||||||
memcpy(put, next, copy);
|
|
||||||
have -= copy;
|
|
||||||
next += copy;
|
|
||||||
left -= copy;
|
|
||||||
put += copy;
|
|
||||||
state->length -= copy;
|
|
||||||
}
|
|
||||||
Tracev((stderr, "inflate: stored end\n"));
|
|
||||||
state->mode = TYPE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TABLE:
|
|
||||||
/* get dynamic table entries descriptor */
|
|
||||||
NEEDBITS(14);
|
|
||||||
state->nlen = BITS(5) + 257;
|
|
||||||
DROPBITS(5);
|
|
||||||
state->ndist = BITS(5) + 1;
|
|
||||||
DROPBITS(5);
|
|
||||||
state->ncode = BITS(4) + 4;
|
|
||||||
DROPBITS(4);
|
|
||||||
#ifndef PKZIP_BUG_WORKAROUND
|
|
||||||
if (state->nlen > 286 || state->ndist > 30) {
|
|
||||||
strm->msg = (char *)"too many length or distance symbols";
|
|
||||||
state->mode = BAD;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
Tracev((stderr, "inflate: table sizes ok\n"));
|
|
||||||
|
|
||||||
/* get code length code lengths (not a typo) */
|
|
||||||
state->have = 0;
|
|
||||||
while (state->have < state->ncode) {
|
|
||||||
NEEDBITS(3);
|
|
||||||
state->lens[order[state->have++]] = (uint16_t)BITS(3);
|
|
||||||
DROPBITS(3);
|
|
||||||
}
|
|
||||||
while (state->have < 19)
|
|
||||||
state->lens[order[state->have++]] = 0;
|
|
||||||
state->next = state->codes;
|
|
||||||
state->lencode = (code const *)(state->next);
|
|
||||||
state->lenbits = 7;
|
|
||||||
ret = inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work);
|
|
||||||
if (ret) {
|
|
||||||
strm->msg = (char *)"invalid code lengths set";
|
|
||||||
state->mode = BAD;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Tracev((stderr, "inflate: code lengths ok\n"));
|
|
||||||
|
|
||||||
/* get length and distance code code lengths */
|
|
||||||
state->have = 0;
|
|
||||||
while (state->have < state->nlen + state->ndist) {
|
|
||||||
for (;;) {
|
|
||||||
here = state->lencode[BITS(state->lenbits)];
|
|
||||||
if (here.bits <= bits)
|
|
||||||
break;
|
|
||||||
PULLBYTE();
|
|
||||||
}
|
|
||||||
if (here.val < 16) {
|
|
||||||
DROPBITS(here.bits);
|
|
||||||
state->lens[state->have++] = here.val;
|
|
||||||
} else {
|
|
||||||
if (here.val == 16) {
|
|
||||||
NEEDBITS(here.bits + 2);
|
|
||||||
DROPBITS(here.bits);
|
|
||||||
if (state->have == 0) {
|
|
||||||
strm->msg = (char *)"invalid bit length repeat";
|
|
||||||
state->mode = BAD;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
len = (unsigned)(state->lens[state->have - 1]);
|
|
||||||
copy = 3 + BITS(2);
|
|
||||||
DROPBITS(2);
|
|
||||||
} else if (here.val == 17) {
|
|
||||||
NEEDBITS(here.bits + 3);
|
|
||||||
DROPBITS(here.bits);
|
|
||||||
len = 0;
|
|
||||||
copy = 3 + BITS(3);
|
|
||||||
DROPBITS(3);
|
|
||||||
} else {
|
|
||||||
NEEDBITS(here.bits + 7);
|
|
||||||
DROPBITS(here.bits);
|
|
||||||
len = 0;
|
|
||||||
copy = 11 + BITS(7);
|
|
||||||
DROPBITS(7);
|
|
||||||
}
|
|
||||||
if (state->have + copy > state->nlen + state->ndist) {
|
|
||||||
strm->msg = (char *)"invalid bit length repeat";
|
|
||||||
state->mode = BAD;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
while (copy--)
|
|
||||||
state->lens[state->have++] = (uint16_t)len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* handle error breaks in while */
|
|
||||||
if (state->mode == BAD)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* check for end-of-block code (better have one) */
|
|
||||||
if (state->lens[256] == 0) {
|
|
||||||
strm->msg = (char *)"invalid code -- missing end-of-block";
|
|
||||||
state->mode = BAD;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* build code tables -- note: do not change the lenbits or distbits
|
|
||||||
values here (9 and 6) without reading the comments in inftrees.h
|
|
||||||
concerning the ENOUGH constants, which depend on those values */
|
|
||||||
state->next = state->codes;
|
|
||||||
state->lencode = (code const *)(state->next);
|
|
||||||
state->lenbits = 9;
|
|
||||||
ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work);
|
|
||||||
if (ret) {
|
|
||||||
strm->msg = (char *)"invalid literal/lengths set";
|
|
||||||
state->mode = BAD;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
state->distcode = (code const *)(state->next);
|
|
||||||
state->distbits = 6;
|
|
||||||
ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
|
|
||||||
&(state->next), &(state->distbits), state->work);
|
|
||||||
if (ret) {
|
|
||||||
strm->msg = (char *)"invalid distances set";
|
|
||||||
state->mode = BAD;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Tracev((stderr, "inflate: codes ok\n"));
|
|
||||||
state->mode = LEN;
|
|
||||||
|
|
||||||
case LEN:
|
|
||||||
/* use inflate_fast() if we have enough input and output */
|
|
||||||
if (have >= 6 && left >= 258) {
|
|
||||||
RESTORE();
|
|
||||||
if (state->whave < state->wsize)
|
|
||||||
state->whave = state->wsize - left;
|
|
||||||
inflate_fast(strm, state->wsize);
|
|
||||||
LOAD();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get a literal, length, or end-of-block code */
|
|
||||||
for (;;) {
|
|
||||||
here = state->lencode[BITS(state->lenbits)];
|
|
||||||
if (here.bits <= bits)
|
|
||||||
break;
|
|
||||||
PULLBYTE();
|
|
||||||
}
|
|
||||||
if (here.op && (here.op & 0xf0) == 0) {
|
|
||||||
last = here;
|
|
||||||
for (;;) {
|
|
||||||
here = state->lencode[last.val +
|
|
||||||
(BITS(last.bits + last.op) >> last.bits)];
|
|
||||||
if ((unsigned)last.bits + (unsigned)here.bits <= bits)
|
|
||||||
break;
|
|
||||||
PULLBYTE();
|
|
||||||
}
|
|
||||||
DROPBITS(last.bits);
|
|
||||||
}
|
|
||||||
DROPBITS(here.bits);
|
|
||||||
state->length = here.val;
|
|
||||||
|
|
||||||
/* process literal */
|
|
||||||
if (here.op == 0) {
|
|
||||||
Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
|
|
||||||
"inflate: literal '%c'\n" :
|
|
||||||
"inflate: literal 0x%02x\n", here.val));
|
|
||||||
ROOM();
|
|
||||||
*put++ = (unsigned char)(state->length);
|
|
||||||
left--;
|
|
||||||
state->mode = LEN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* process end of block */
|
|
||||||
if (here.op & 32) {
|
|
||||||
Tracevv((stderr, "inflate: end of block\n"));
|
|
||||||
state->mode = TYPE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* invalid code */
|
|
||||||
if (here.op & 64) {
|
|
||||||
strm->msg = (char *)"invalid literal/length code";
|
|
||||||
state->mode = BAD;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* length code -- get extra bits, if any */
|
|
||||||
state->extra = (here.op & 15);
|
|
||||||
if (state->extra != 0) {
|
|
||||||
NEEDBITS(state->extra);
|
|
||||||
state->length += BITS(state->extra);
|
|
||||||
DROPBITS(state->extra);
|
|
||||||
}
|
|
||||||
Tracevv((stderr, "inflate: length %u\n", state->length));
|
|
||||||
|
|
||||||
/* get distance code */
|
|
||||||
for (;;) {
|
|
||||||
here = state->distcode[BITS(state->distbits)];
|
|
||||||
if (here.bits <= bits)
|
|
||||||
break;
|
|
||||||
PULLBYTE();
|
|
||||||
}
|
|
||||||
if ((here.op & 0xf0) == 0) {
|
|
||||||
last = here;
|
|
||||||
for (;;) {
|
|
||||||
here = state->distcode[last.val + (BITS(last.bits + last.op) >> last.bits)];
|
|
||||||
if ((unsigned)last.bits + (unsigned)here.bits <= bits)
|
|
||||||
break;
|
|
||||||
PULLBYTE();
|
|
||||||
}
|
|
||||||
DROPBITS(last.bits);
|
|
||||||
}
|
|
||||||
DROPBITS(here.bits);
|
|
||||||
if (here.op & 64) {
|
|
||||||
strm->msg = (char *)"invalid distance code";
|
|
||||||
state->mode = BAD;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
state->offset = here.val;
|
|
||||||
|
|
||||||
/* get distance extra bits, if any */
|
|
||||||
state->extra = (here.op & 15);
|
|
||||||
if (state->extra != 0) {
|
|
||||||
NEEDBITS(state->extra);
|
|
||||||
state->offset += BITS(state->extra);
|
|
||||||
DROPBITS(state->extra);
|
|
||||||
}
|
|
||||||
if (state->offset > state->wsize - (state->whave < state->wsize ? left : 0)) {
|
|
||||||
strm->msg = (char *)"invalid distance too far back";
|
|
||||||
state->mode = BAD;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Tracevv((stderr, "inflate: distance %u\n", state->offset));
|
|
||||||
|
|
||||||
/* copy match from window to output */
|
|
||||||
do {
|
|
||||||
ROOM();
|
|
||||||
copy = state->wsize - state->offset;
|
|
||||||
if (copy < left) {
|
|
||||||
from = put + copy;
|
|
||||||
copy = left - copy;
|
|
||||||
} else {
|
|
||||||
from = put - state->offset;
|
|
||||||
copy = left;
|
|
||||||
}
|
|
||||||
if (copy > state->length)
|
|
||||||
copy = state->length;
|
|
||||||
state->length -= copy;
|
|
||||||
left -= copy;
|
|
||||||
do {
|
|
||||||
*put++ = *from++;
|
|
||||||
} while (--copy);
|
|
||||||
} while (state->length != 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DONE:
|
|
||||||
/* inflate stream terminated properly -- write leftover output */
|
|
||||||
ret = Z_STREAM_END;
|
|
||||||
if (left < state->wsize) {
|
|
||||||
if (out(out_desc, state->window, state->wsize - left))
|
|
||||||
ret = Z_BUF_ERROR;
|
|
||||||
}
|
|
||||||
goto inf_leave;
|
|
||||||
|
|
||||||
case BAD:
|
|
||||||
ret = Z_DATA_ERROR;
|
|
||||||
goto inf_leave;
|
|
||||||
|
|
||||||
default: /* can't happen, but makes compilers happy */
|
|
||||||
ret = Z_STREAM_ERROR;
|
|
||||||
goto inf_leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return unused input */
|
|
||||||
inf_leave:
|
|
||||||
strm->next_in = next;
|
|
||||||
strm->avail_in = have;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ZEXPORT inflateBackEnd(z_stream *strm) {
|
|
||||||
if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
|
|
||||||
return Z_STREAM_ERROR;
|
|
||||||
ZFREE(strm, strm->state);
|
|
||||||
strm->state = Z_NULL;
|
|
||||||
Tracev((stderr, "inflate: end\n"));
|
|
||||||
return Z_OK;
|
|
||||||
}
|
|
@ -1,328 +0,0 @@
|
|||||||
/* inffast.c -- fast decoding
|
|
||||||
* Copyright (C) 1995-2008, 2010, 2013 Mark Adler
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "zutil.h"
|
|
||||||
#include "inftrees.h"
|
|
||||||
#include "inflate.h"
|
|
||||||
#include "inffast.h"
|
|
||||||
|
|
||||||
/* Allow machine dependent optimization for post-increment or pre-increment.
|
|
||||||
Based on testing to date,
|
|
||||||
Pre-increment preferred for:
|
|
||||||
- PowerPC G3 (Adler)
|
|
||||||
- MIPS R5000 (Randers-Pehrson)
|
|
||||||
Post-increment preferred for:
|
|
||||||
- none
|
|
||||||
No measurable difference:
|
|
||||||
- Pentium III (Anderson)
|
|
||||||
- M68060 (Nikl)
|
|
||||||
*/
|
|
||||||
#ifdef POSTINC
|
|
||||||
# define OFF 0
|
|
||||||
# define PUP(a) *(a)++
|
|
||||||
#else
|
|
||||||
# define OFF 1
|
|
||||||
# define PUP(a) *++(a)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Return the low n bits of the bit accumulator (n < 16) */
|
|
||||||
#define BITS(n) \
|
|
||||||
(hold & ((1U << (n)) - 1))
|
|
||||||
|
|
||||||
/* Remove n bits from the bit accumulator */
|
|
||||||
#define DROPBITS(n) \
|
|
||||||
do { \
|
|
||||||
hold >>= (n); \
|
|
||||||
bits -= (unsigned)(n); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/*
|
|
||||||
Decode literal, length, and distance codes and write out the resulting
|
|
||||||
literal and match bytes until either not enough input or output is
|
|
||||||
available, an end-of-block is encountered, or a data error is encountered.
|
|
||||||
When large enough input and output buffers are supplied to inflate(), for
|
|
||||||
example, a 16K input buffer and a 64K output buffer, more than 95% of the
|
|
||||||
inflate execution time is spent in this routine.
|
|
||||||
|
|
||||||
Entry assumptions:
|
|
||||||
|
|
||||||
state->mode == LEN
|
|
||||||
strm->avail_in >= 6
|
|
||||||
strm->avail_out >= 258
|
|
||||||
start >= strm->avail_out
|
|
||||||
state->bits < 8
|
|
||||||
|
|
||||||
On return, state->mode is one of:
|
|
||||||
|
|
||||||
LEN -- ran out of enough output space or enough available input
|
|
||||||
TYPE -- reached end of block code, inflate() to interpret next block
|
|
||||||
BAD -- error in block data
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
|
|
||||||
- The maximum input bits used by a length/distance pair is 15 bits for the
|
|
||||||
length code, 5 bits for the length extra, 15 bits for the distance code,
|
|
||||||
and 13 bits for the distance extra. This totals 48 bits, or six bytes.
|
|
||||||
Therefore if strm->avail_in >= 6, then there is enough input to avoid
|
|
||||||
checking for available input while decoding.
|
|
||||||
|
|
||||||
- The maximum bytes that a single length/distance pair can output is 258
|
|
||||||
bytes, which is the maximum length that can be coded. inflate_fast()
|
|
||||||
requires strm->avail_out >= 258 for each loop to avoid checking for
|
|
||||||
output space.
|
|
||||||
*/
|
|
||||||
void ZLIB_INTERNAL inflate_fast(z_stream *strm, unsigned long start) {
|
|
||||||
/* start: inflate()'s starting value for strm->avail_out */
|
|
||||||
struct inflate_state *state;
|
|
||||||
const unsigned char *in; /* local strm->next_in */
|
|
||||||
const unsigned char *last; /* have enough input while in < last */
|
|
||||||
unsigned char *out; /* local strm->next_out */
|
|
||||||
unsigned char *beg; /* inflate()'s initial strm->next_out */
|
|
||||||
unsigned char *end; /* while out < end, enough space available */
|
|
||||||
#ifdef INFLATE_STRICT
|
|
||||||
unsigned dmax; /* maximum distance from zlib header */
|
|
||||||
#endif
|
|
||||||
unsigned wsize; /* window size or zero if not using window */
|
|
||||||
unsigned whave; /* valid bytes in the window */
|
|
||||||
unsigned wnext; /* window write index */
|
|
||||||
unsigned char *window; /* allocated sliding window, if wsize != 0 */
|
|
||||||
uint32_t hold; /* local strm->hold */
|
|
||||||
unsigned bits; /* local strm->bits */
|
|
||||||
code const *lcode; /* local strm->lencode */
|
|
||||||
code const *dcode; /* local strm->distcode */
|
|
||||||
unsigned lmask; /* mask for first level of length codes */
|
|
||||||
unsigned dmask; /* mask for first level of distance codes */
|
|
||||||
code here; /* retrieved table entry */
|
|
||||||
unsigned op; /* code bits, operation, extra bits, or */
|
|
||||||
/* window position, window bytes to copy */
|
|
||||||
unsigned len; /* match length, unused bytes */
|
|
||||||
unsigned dist; /* match distance */
|
|
||||||
unsigned char *from; /* where to copy match from */
|
|
||||||
|
|
||||||
/* copy state to local variables */
|
|
||||||
state = (struct inflate_state *)strm->state;
|
|
||||||
in = strm->next_in - OFF;
|
|
||||||
last = in + (strm->avail_in - 5);
|
|
||||||
out = strm->next_out - OFF;
|
|
||||||
beg = out - (start - strm->avail_out);
|
|
||||||
end = out + (strm->avail_out - 257);
|
|
||||||
#ifdef INFLATE_STRICT
|
|
||||||
dmax = state->dmax;
|
|
||||||
#endif
|
|
||||||
wsize = state->wsize;
|
|
||||||
whave = state->whave;
|
|
||||||
wnext = state->wnext;
|
|
||||||
window = state->window;
|
|
||||||
hold = state->hold;
|
|
||||||
bits = state->bits;
|
|
||||||
lcode = state->lencode;
|
|
||||||
dcode = state->distcode;
|
|
||||||
lmask = (1U << state->lenbits) - 1;
|
|
||||||
dmask = (1U << state->distbits) - 1;
|
|
||||||
|
|
||||||
/* decode literals and length/distances until end-of-block or not enough
|
|
||||||
input data or output space */
|
|
||||||
do {
|
|
||||||
if (bits < 15) {
|
|
||||||
hold += (PUP(in) << bits);
|
|
||||||
bits += 8;
|
|
||||||
hold += (PUP(in) << bits);
|
|
||||||
bits += 8;
|
|
||||||
}
|
|
||||||
here = lcode[hold & lmask];
|
|
||||||
dolen:
|
|
||||||
DROPBITS(here.bits);
|
|
||||||
op = here.op;
|
|
||||||
if (op == 0) { /* literal */
|
|
||||||
Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
|
|
||||||
"inflate: literal '%c'\n" :
|
|
||||||
"inflate: literal 0x%02x\n", here.val));
|
|
||||||
PUP(out) = (unsigned char)(here.val);
|
|
||||||
} else if (op & 16) { /* length base */
|
|
||||||
len = here.val;
|
|
||||||
op &= 15; /* number of extra bits */
|
|
||||||
if (op) {
|
|
||||||
if (bits < op) {
|
|
||||||
hold += (PUP(in) << bits);
|
|
||||||
bits += 8;
|
|
||||||
}
|
|
||||||
len += BITS(op);
|
|
||||||
DROPBITS(op);
|
|
||||||
}
|
|
||||||
Tracevv((stderr, "inflate: length %u\n", len));
|
|
||||||
if (bits < 15) {
|
|
||||||
hold += (PUP(in) << bits);
|
|
||||||
bits += 8;
|
|
||||||
hold += (PUP(in) << bits);
|
|
||||||
bits += 8;
|
|
||||||
}
|
|
||||||
here = dcode[hold & dmask];
|
|
||||||
dodist:
|
|
||||||
DROPBITS(here.bits);
|
|
||||||
op = here.op;
|
|
||||||
if (op & 16) { /* distance base */
|
|
||||||
dist = here.val;
|
|
||||||
op &= 15; /* number of extra bits */
|
|
||||||
if (bits < op) {
|
|
||||||
hold += (PUP(in) << bits);
|
|
||||||
bits += 8;
|
|
||||||
if (bits < op) {
|
|
||||||
hold += (PUP(in) << bits);
|
|
||||||
bits += 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dist += BITS(op);
|
|
||||||
#ifdef INFLATE_STRICT
|
|
||||||
if (dist > dmax) {
|
|
||||||
strm->msg = (char *)"invalid distance too far back";
|
|
||||||
state->mode = BAD;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
DROPBITS(op);
|
|
||||||
Tracevv((stderr, "inflate: distance %u\n", dist));
|
|
||||||
op = (unsigned)(out - beg); /* max distance in output */
|
|
||||||
if (dist > op) { /* see if copy from window */
|
|
||||||
op = dist - op; /* distance back in window */
|
|
||||||
if (op > whave) {
|
|
||||||
if (state->sane) {
|
|
||||||
strm->msg = (char *)"invalid distance too far back";
|
|
||||||
state->mode = BAD;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
|
|
||||||
if (len <= op - whave) {
|
|
||||||
do {
|
|
||||||
PUP(out) = 0;
|
|
||||||
} while (--len);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
len -= op - whave;
|
|
||||||
do {
|
|
||||||
PUP(out) = 0;
|
|
||||||
} while (--op > whave);
|
|
||||||
if (op == 0) {
|
|
||||||
from = out - dist;
|
|
||||||
do {
|
|
||||||
PUP(out) = PUP(from);
|
|
||||||
} while (--len);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
from = window - OFF;
|
|
||||||
if (wnext == 0) { /* very common case */
|
|
||||||
from += wsize - op;
|
|
||||||
if (op < len) { /* some from window */
|
|
||||||
len -= op;
|
|
||||||
do {
|
|
||||||
PUP(out) = PUP(from);
|
|
||||||
} while (--op);
|
|
||||||
from = out - dist; /* rest from output */
|
|
||||||
}
|
|
||||||
} else if (wnext < op) { /* wrap around window */
|
|
||||||
from += wsize + wnext - op;
|
|
||||||
op -= wnext;
|
|
||||||
if (op < len) { /* some from end of window */
|
|
||||||
len -= op;
|
|
||||||
do {
|
|
||||||
PUP(out) = PUP(from);
|
|
||||||
} while (--op);
|
|
||||||
from = window - OFF;
|
|
||||||
if (wnext < len) { /* some from start of window */
|
|
||||||
op = wnext;
|
|
||||||
len -= op;
|
|
||||||
do {
|
|
||||||
PUP(out) = PUP(from);
|
|
||||||
} while (--op);
|
|
||||||
from = out - dist; /* rest from output */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { /* contiguous in window */
|
|
||||||
from += wnext - op;
|
|
||||||
if (op < len) { /* some from window */
|
|
||||||
len -= op;
|
|
||||||
do {
|
|
||||||
PUP(out) = PUP(from);
|
|
||||||
} while (--op);
|
|
||||||
from = out - dist; /* rest from output */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (len > 2) {
|
|
||||||
PUP(out) = PUP(from);
|
|
||||||
PUP(out) = PUP(from);
|
|
||||||
PUP(out) = PUP(from);
|
|
||||||
len -= 3;
|
|
||||||
}
|
|
||||||
if (len) {
|
|
||||||
PUP(out) = PUP(from);
|
|
||||||
if (len > 1)
|
|
||||||
PUP(out) = PUP(from);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
from = out - dist; /* copy direct from output */
|
|
||||||
do { /* minimum length is three */
|
|
||||||
PUP(out) = PUP(from);
|
|
||||||
PUP(out) = PUP(from);
|
|
||||||
PUP(out) = PUP(from);
|
|
||||||
len -= 3;
|
|
||||||
} while (len > 2);
|
|
||||||
if (len) {
|
|
||||||
PUP(out) = PUP(from);
|
|
||||||
if (len > 1)
|
|
||||||
PUP(out) = PUP(from);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ((op & 64) == 0) { /* 2nd level distance code */
|
|
||||||
here = dcode[here.val + BITS(op)];
|
|
||||||
goto dodist;
|
|
||||||
} else {
|
|
||||||
strm->msg = (char *)"invalid distance code";
|
|
||||||
state->mode = BAD;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if ((op & 64) == 0) { /* 2nd level length code */
|
|
||||||
here = lcode[here.val + BITS(op)];
|
|
||||||
goto dolen;
|
|
||||||
} else if (op & 32) { /* end-of-block */
|
|
||||||
Tracevv((stderr, "inflate: end of block\n"));
|
|
||||||
state->mode = TYPE;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
strm->msg = (char *)"invalid literal/length code";
|
|
||||||
state->mode = BAD;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while (in < last && out < end);
|
|
||||||
|
|
||||||
/* return unused bytes (on entry, bits < 8, so in won't go too far back) */
|
|
||||||
len = bits >> 3;
|
|
||||||
in -= len;
|
|
||||||
bits -= len << 3;
|
|
||||||
hold &= (1U << bits) - 1;
|
|
||||||
|
|
||||||
/* update state and return */
|
|
||||||
strm->next_in = in + OFF;
|
|
||||||
strm->next_out = out + OFF;
|
|
||||||
strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
|
|
||||||
strm->avail_out = (unsigned)(out < end ? 257 + (end - out) : 257 - (out - end));
|
|
||||||
state->hold = hold;
|
|
||||||
state->bits = bits;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
|
|
||||||
- Using bit fields for code structure
|
|
||||||
- Different op definition to avoid & for extra bits (do & for table bits)
|
|
||||||
- Three separate decoding do-loops for direct, window, and wnext == 0
|
|
||||||
- Special case for distance > 1 copies to do overlapped load and store copy
|
|
||||||
- Explicit branch predictions (based on measured branch probabilities)
|
|
||||||
- Deferring match copy and interspersed it with decoding subsequent codes
|
|
||||||
- Swapping literal/length else
|
|
||||||
- Swapping window/direct else
|
|
||||||
- Larger unrolled copy loops (three is about right)
|
|
||||||
- Moving len -= 3 statement into middle of loop
|
|
||||||
*/
|
|
@ -1,15 +0,0 @@
|
|||||||
#ifndef INFFAST_H_
|
|
||||||
#define INFFAST_H_
|
|
||||||
/* inffast.h -- header to use inffast.c
|
|
||||||
* Copyright (C) 1995-2003, 2010 Mark Adler
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* WARNING: this file should *not* be used by applications. It is
|
|
||||||
part of the implementation of the compression library and is
|
|
||||||
subject to change. Applications should only use zlib.h.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void ZLIB_INTERNAL inflate_fast(z_stream *strm, unsigned long start);
|
|
||||||
|
|
||||||
#endif /* INFFAST_H_ */
|
|
@ -1,94 +0,0 @@
|
|||||||
/* inffixed.h -- table for decoding fixed codes
|
|
||||||
* Generated automatically by makefixed().
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* WARNING: this file should *not* be used by applications.
|
|
||||||
It is part of the implementation of this library and is
|
|
||||||
subject to change. Applications should only use zlib.h.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static const code lenfix[512] = {
|
|
||||||
{96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
|
|
||||||
{0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
|
|
||||||
{0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
|
|
||||||
{0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
|
|
||||||
{0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
|
|
||||||
{21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
|
|
||||||
{0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
|
|
||||||
{0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
|
|
||||||
{18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
|
|
||||||
{0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
|
|
||||||
{0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
|
|
||||||
{0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
|
|
||||||
{20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
|
|
||||||
{0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
|
|
||||||
{0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
|
|
||||||
{0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
|
|
||||||
{16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
|
|
||||||
{0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
|
|
||||||
{0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
|
|
||||||
{0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
|
|
||||||
{0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
|
|
||||||
{0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
|
|
||||||
{0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
|
|
||||||
{0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
|
|
||||||
{17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
|
|
||||||
{0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
|
|
||||||
{0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
|
|
||||||
{0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
|
|
||||||
{19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
|
|
||||||
{0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
|
|
||||||
{0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
|
|
||||||
{0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
|
|
||||||
{16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
|
|
||||||
{0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
|
|
||||||
{0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
|
|
||||||
{0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
|
|
||||||
{0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
|
|
||||||
{20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
|
|
||||||
{0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
|
|
||||||
{0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
|
|
||||||
{17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
|
|
||||||
{0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
|
|
||||||
{0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
|
|
||||||
{0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
|
|
||||||
{20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
|
|
||||||
{0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
|
|
||||||
{0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
|
|
||||||
{0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
|
|
||||||
{16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
|
|
||||||
{0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
|
|
||||||
{0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
|
|
||||||
{0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
|
|
||||||
{0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
|
|
||||||
{0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
|
|
||||||
{0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
|
|
||||||
{0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
|
|
||||||
{16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
|
|
||||||
{0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
|
|
||||||
{0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
|
|
||||||
{0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
|
|
||||||
{19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
|
|
||||||
{0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
|
|
||||||
{0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
|
|
||||||
{0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
|
|
||||||
{16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
|
|
||||||
{0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
|
|
||||||
{0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
|
|
||||||
{0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
|
|
||||||
{0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
|
|
||||||
{64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
|
|
||||||
{0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
|
|
||||||
{0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
|
|
||||||
{18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
|
|
||||||
{0,9,255}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const code distfix[32] = {
|
|
||||||
{16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
|
|
||||||
{21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
|
|
||||||
{18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
|
|
||||||
{19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
|
|
||||||
{16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
|
|
||||||
{22,5,193},{64,5,0}
|
|
||||||
};
|
|
File diff suppressed because it is too large
Load Diff
@ -1,127 +0,0 @@
|
|||||||
/* inflate.h -- internal inflate state definition
|
|
||||||
* Copyright (C) 1995-2009 Mark Adler
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* WARNING: this file should *not* be used by applications. It is
|
|
||||||
part of the implementation of the compression library and is
|
|
||||||
subject to change. Applications should only use zlib.h.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef INFLATE_H_
|
|
||||||
#define INFLATE_H_
|
|
||||||
|
|
||||||
/* define NO_GZIP when compiling if you want to disable gzip header and
|
|
||||||
trailer decoding by inflate(). NO_GZIP would be used to avoid linking in
|
|
||||||
the crc code when it is not needed. For shared libraries, gzip decoding
|
|
||||||
should be left enabled. */
|
|
||||||
#ifndef NO_GZIP
|
|
||||||
# define GUNZIP
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Possible inflate modes between inflate() calls */
|
|
||||||
typedef enum {
|
|
||||||
HEAD, /* i: waiting for magic header */
|
|
||||||
FLAGS, /* i: waiting for method and flags (gzip) */
|
|
||||||
TIME, /* i: waiting for modification time (gzip) */
|
|
||||||
OS, /* i: waiting for extra flags and operating system (gzip) */
|
|
||||||
EXLEN, /* i: waiting for extra length (gzip) */
|
|
||||||
EXTRA, /* i: waiting for extra bytes (gzip) */
|
|
||||||
NAME, /* i: waiting for end of file name (gzip) */
|
|
||||||
COMMENT, /* i: waiting for end of comment (gzip) */
|
|
||||||
HCRC, /* i: waiting for header crc (gzip) */
|
|
||||||
DICTID, /* i: waiting for dictionary check value */
|
|
||||||
DICT, /* waiting for inflateSetDictionary() call */
|
|
||||||
TYPE, /* i: waiting for type bits, including last-flag bit */
|
|
||||||
TYPEDO, /* i: same, but skip check to exit inflate on new block */
|
|
||||||
STORED, /* i: waiting for stored size (length and complement) */
|
|
||||||
COPY_, /* i/o: same as COPY below, but only first time in */
|
|
||||||
COPY, /* i/o: waiting for input or output to copy stored block */
|
|
||||||
TABLE, /* i: waiting for dynamic block table lengths */
|
|
||||||
LENLENS, /* i: waiting for code length code lengths */
|
|
||||||
CODELENS, /* i: waiting for length/lit and distance code lengths */
|
|
||||||
LEN_, /* i: same as LEN below, but only first time in */
|
|
||||||
LEN, /* i: waiting for length/lit/eob code */
|
|
||||||
LENEXT, /* i: waiting for length extra bits */
|
|
||||||
DIST, /* i: waiting for distance code */
|
|
||||||
DISTEXT, /* i: waiting for distance extra bits */
|
|
||||||
MATCH, /* o: waiting for output space to copy string */
|
|
||||||
LIT, /* o: waiting for output space to write literal */
|
|
||||||
CHECK, /* i: waiting for 32-bit check value */
|
|
||||||
LENGTH, /* i: waiting for 32-bit length (gzip) */
|
|
||||||
DONE, /* finished check, done -- remain here until reset */
|
|
||||||
BAD, /* got a data error -- remain here until reset */
|
|
||||||
MEM, /* got an inflate() memory error -- remain here until reset */
|
|
||||||
SYNC /* looking for synchronization bytes to restart inflate() */
|
|
||||||
} inflate_mode;
|
|
||||||
|
|
||||||
/*
|
|
||||||
State transitions between above modes -
|
|
||||||
|
|
||||||
(most modes can go to BAD or MEM on error -- not shown for clarity)
|
|
||||||
|
|
||||||
Process header:
|
|
||||||
HEAD -> (gzip) or (zlib) or (raw)
|
|
||||||
(gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->
|
|
||||||
HCRC -> TYPE
|
|
||||||
(zlib) -> DICTID or TYPE
|
|
||||||
DICTID -> DICT -> TYPE
|
|
||||||
(raw) -> TYPEDO
|
|
||||||
Read deflate blocks:
|
|
||||||
TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK
|
|
||||||
STORED -> COPY_ -> COPY -> TYPE
|
|
||||||
TABLE -> LENLENS -> CODELENS -> LEN_
|
|
||||||
LEN_ -> LEN
|
|
||||||
Read deflate codes in fixed or dynamic block:
|
|
||||||
LEN -> LENEXT or LIT or TYPE
|
|
||||||
LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
|
|
||||||
LIT -> LEN
|
|
||||||
Process trailer:
|
|
||||||
CHECK -> LENGTH -> DONE
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* state maintained between inflate() calls. Approximately 10K bytes. */
|
|
||||||
struct inflate_state {
|
|
||||||
inflate_mode mode; /* current inflate mode */
|
|
||||||
int last; /* true if processing last block */
|
|
||||||
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
|
|
||||||
int havedict; /* true if dictionary provided */
|
|
||||||
int flags; /* gzip header method and flags (0 if zlib) */
|
|
||||||
unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
|
|
||||||
unsigned long check; /* protected copy of check value */
|
|
||||||
unsigned long total; /* protected copy of output count */
|
|
||||||
gz_headerp head; /* where to save gzip header information */
|
|
||||||
/* sliding window */
|
|
||||||
unsigned wbits; /* log base 2 of requested window size */
|
|
||||||
uint32_t wsize; /* window size or zero if not using window */
|
|
||||||
uint32_t whave; /* valid bytes in the window */
|
|
||||||
uint32_t wnext; /* window write index */
|
|
||||||
unsigned char *window; /* allocated sliding window, if needed */
|
|
||||||
/* bit accumulator */
|
|
||||||
uint32_t hold; /* input bit accumulator */
|
|
||||||
unsigned bits; /* number of bits in "in" */
|
|
||||||
/* for string and stored block copying */
|
|
||||||
uint32_t length; /* literal or length of data to copy */
|
|
||||||
unsigned offset; /* distance back to copy string from */
|
|
||||||
/* for table and code decoding */
|
|
||||||
unsigned extra; /* extra bits needed */
|
|
||||||
/* fixed and dynamic code tables */
|
|
||||||
code const *lencode; /* starting table for length/literal codes */
|
|
||||||
code const *distcode; /* starting table for distance codes */
|
|
||||||
unsigned lenbits; /* index bits for lencode */
|
|
||||||
unsigned distbits; /* index bits for distcode */
|
|
||||||
/* dynamic table building */
|
|
||||||
unsigned ncode; /* number of code length code lengths */
|
|
||||||
unsigned nlen; /* number of length code lengths */
|
|
||||||
unsigned ndist; /* number of distance code lengths */
|
|
||||||
uint32_t have; /* number of code lengths in lens[] */
|
|
||||||
code *next; /* next available space in codes[] */
|
|
||||||
uint16_t lens[320]; /* temporary storage for code lengths */
|
|
||||||
uint16_t work[288]; /* work area for code table building */
|
|
||||||
code codes[ENOUGH]; /* space for code tables */
|
|
||||||
int sane; /* if false, allow invalid distance too far */
|
|
||||||
int back; /* bits back of last unprocessed length/lit */
|
|
||||||
unsigned was; /* initial length of match */
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* INFLATE_H_ */
|
|
@ -1,298 +0,0 @@
|
|||||||
/* inftrees.c -- generate Huffman trees for efficient decoding
|
|
||||||
* Copyright (C) 1995-2013 Mark Adler
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "zutil.h"
|
|
||||||
#include "inftrees.h"
|
|
||||||
|
|
||||||
#define MAXBITS 15
|
|
||||||
|
|
||||||
const char inflate_copyright[] = " inflate 1.2.8.f Copyright 1995-2013 Mark Adler ";
|
|
||||||
/*
|
|
||||||
If you use the zlib library in a product, an acknowledgment is welcome
|
|
||||||
in the documentation of your product. If for some reason you cannot
|
|
||||||
include such an acknowledgment, I would appreciate that you keep this
|
|
||||||
copyright string in the executable of your product.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Build a set of tables to decode the provided canonical Huffman code.
|
|
||||||
The code lengths are lens[0..codes-1]. The result starts at *table,
|
|
||||||
whose indices are 0..2^bits-1. work is a writable array of at least
|
|
||||||
lens shorts, which is used as a work area. type is the type of code
|
|
||||||
to be generated, CODES, LENS, or DISTS. On return, zero is success,
|
|
||||||
-1 is an invalid code, and +1 means that ENOUGH isn't enough. table
|
|
||||||
on return points to the next available entry's address. bits is the
|
|
||||||
requested root table index bits, and on return it is the actual root
|
|
||||||
table index bits. It will differ if the request is greater than the
|
|
||||||
longest code or if it is less than the shortest code.
|
|
||||||
*/
|
|
||||||
int ZLIB_INTERNAL inflate_table(codetype type, uint16_t *lens, unsigned codes,
|
|
||||||
code * *table, unsigned *bits, uint16_t *work) {
|
|
||||||
unsigned len; /* a code's length in bits */
|
|
||||||
unsigned sym; /* index of code symbols */
|
|
||||||
unsigned min, max; /* minimum and maximum code lengths */
|
|
||||||
unsigned root; /* number of index bits for root table */
|
|
||||||
unsigned curr; /* number of index bits for current table */
|
|
||||||
unsigned drop; /* code bits to drop for sub-table */
|
|
||||||
int left; /* number of prefix codes available */
|
|
||||||
unsigned used; /* code entries in table used */
|
|
||||||
unsigned huff; /* Huffman code */
|
|
||||||
unsigned incr; /* for incrementing code, index */
|
|
||||||
unsigned fill; /* index for replicating entries */
|
|
||||||
unsigned low; /* low bits for current root entry */
|
|
||||||
unsigned mask; /* mask for low root bits */
|
|
||||||
code here; /* table entry for duplication */
|
|
||||||
code *next; /* next available space in table */
|
|
||||||
const uint16_t *base; /* base value table to use */
|
|
||||||
const uint16_t *extra; /* extra bits table to use */
|
|
||||||
int end; /* use base and extra for symbol > end */
|
|
||||||
uint16_t count[MAXBITS+1]; /* number of codes of each length */
|
|
||||||
uint16_t offs[MAXBITS+1]; /* offsets in table for each length */
|
|
||||||
static const uint16_t lbase[31] = { /* Length codes 257..285 base */
|
|
||||||
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
|
|
||||||
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
|
|
||||||
static const uint16_t lext[31] = { /* Length codes 257..285 extra */
|
|
||||||
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
|
|
||||||
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78};
|
|
||||||
static const uint16_t dbase[32] = { /* Distance codes 0..29 base */
|
|
||||||
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
|
|
||||||
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
|
|
||||||
8193, 12289, 16385, 24577, 0, 0};
|
|
||||||
static const uint16_t dext[32] = { /* Distance codes 0..29 extra */
|
|
||||||
16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
|
|
||||||
23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
|
|
||||||
28, 28, 29, 29, 64, 64};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Process a set of code lengths to create a canonical Huffman code. The
|
|
||||||
code lengths are lens[0..codes-1]. Each length corresponds to the
|
|
||||||
symbols 0..codes-1. The Huffman code is generated by first sorting the
|
|
||||||
symbols by length from short to long, and retaining the symbol order
|
|
||||||
for codes with equal lengths. Then the code starts with all zero bits
|
|
||||||
for the first code of the shortest length, and the codes are integer
|
|
||||||
increments for the same length, and zeros are appended as the length
|
|
||||||
increases. For the deflate format, these bits are stored backwards
|
|
||||||
from their more natural integer increment ordering, and so when the
|
|
||||||
decoding tables are built in the large loop below, the integer codes
|
|
||||||
are incremented backwards.
|
|
||||||
|
|
||||||
This routine assumes, but does not check, that all of the entries in
|
|
||||||
lens[] are in the range 0..MAXBITS. The caller must assure this.
|
|
||||||
1..MAXBITS is interpreted as that code length. zero means that that
|
|
||||||
symbol does not occur in this code.
|
|
||||||
|
|
||||||
The codes are sorted by computing a count of codes for each length,
|
|
||||||
creating from that a table of starting indices for each length in the
|
|
||||||
sorted table, and then entering the symbols in order in the sorted
|
|
||||||
table. The sorted table is work[], with that space being provided by
|
|
||||||
the caller.
|
|
||||||
|
|
||||||
The length counts are used for other purposes as well, i.e. finding
|
|
||||||
the minimum and maximum length codes, determining if there are any
|
|
||||||
codes at all, checking for a valid set of lengths, and looking ahead
|
|
||||||
at length counts to determine sub-table sizes when building the
|
|
||||||
decoding tables.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
|
|
||||||
for (len = 0; len <= MAXBITS; len++)
|
|
||||||
count[len] = 0;
|
|
||||||
for (sym = 0; sym < codes; sym++)
|
|
||||||
count[lens[sym]]++;
|
|
||||||
|
|
||||||
/* bound code lengths, force root to be within code lengths */
|
|
||||||
root = *bits;
|
|
||||||
for (max = MAXBITS; max >= 1; max--)
|
|
||||||
if (count[max] != 0) break;
|
|
||||||
if (root > max) root = max;
|
|
||||||
if (max == 0) { /* no symbols to code at all */
|
|
||||||
here.op = (unsigned char)64; /* invalid code marker */
|
|
||||||
here.bits = (unsigned char)1;
|
|
||||||
here.val = (uint16_t)0;
|
|
||||||
*(*table)++ = here; /* make a table to force an error */
|
|
||||||
*(*table)++ = here;
|
|
||||||
*bits = 1;
|
|
||||||
return 0; /* no symbols, but wait for decoding to report error */
|
|
||||||
}
|
|
||||||
for (min = 1; min < max; min++)
|
|
||||||
if (count[min] != 0) break;
|
|
||||||
if (root < min) root = min;
|
|
||||||
|
|
||||||
/* check for an over-subscribed or incomplete set of lengths */
|
|
||||||
left = 1;
|
|
||||||
for (len = 1; len <= MAXBITS; len++) {
|
|
||||||
left <<= 1;
|
|
||||||
left -= count[len];
|
|
||||||
if (left < 0) return -1; /* over-subscribed */
|
|
||||||
}
|
|
||||||
if (left > 0 && (type == CODES || max != 1))
|
|
||||||
return -1; /* incomplete set */
|
|
||||||
|
|
||||||
/* generate offsets into symbol table for each length for sorting */
|
|
||||||
offs[1] = 0;
|
|
||||||
for (len = 1; len < MAXBITS; len++)
|
|
||||||
offs[len + 1] = offs[len] + count[len];
|
|
||||||
|
|
||||||
/* sort symbols by length, by symbol order within each length */
|
|
||||||
for (sym = 0; sym < codes; sym++)
|
|
||||||
if (lens[sym] != 0) work[offs[lens[sym]]++] = (uint16_t)sym;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Create and fill in decoding tables. In this loop, the table being
|
|
||||||
filled is at next and has curr index bits. The code being used is huff
|
|
||||||
with length len. That code is converted to an index by dropping drop
|
|
||||||
bits off of the bottom. For codes where len is less than drop + curr,
|
|
||||||
those top drop + curr - len bits are incremented through all values to
|
|
||||||
fill the table with replicated entries.
|
|
||||||
|
|
||||||
root is the number of index bits for the root table. When len exceeds
|
|
||||||
root, sub-tables are created pointed to by the root entry with an index
|
|
||||||
of the low root bits of huff. This is saved in low to check for when a
|
|
||||||
new sub-table should be started. drop is zero when the root table is
|
|
||||||
being filled, and drop is root when sub-tables are being filled.
|
|
||||||
|
|
||||||
When a new sub-table is needed, it is necessary to look ahead in the
|
|
||||||
code lengths to determine what size sub-table is needed. The length
|
|
||||||
counts are used for this, and so count[] is decremented as codes are
|
|
||||||
entered in the tables.
|
|
||||||
|
|
||||||
used keeps track of how many table entries have been allocated from the
|
|
||||||
provided *table space. It is checked for LENS and DIST tables against
|
|
||||||
the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
|
|
||||||
the initial root table size constants. See the comments in inftrees.h
|
|
||||||
for more information.
|
|
||||||
|
|
||||||
sym increments through all symbols, and the loop terminates when
|
|
||||||
all codes of length max, i.e. all codes, have been processed. This
|
|
||||||
routine permits incomplete codes, so another loop after this one fills
|
|
||||||
in the rest of the decoding tables with invalid code markers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* set up for code type */
|
|
||||||
switch (type) {
|
|
||||||
case CODES:
|
|
||||||
base = extra = work; /* dummy value--not used */
|
|
||||||
end = 19;
|
|
||||||
break;
|
|
||||||
case LENS:
|
|
||||||
base = lbase;
|
|
||||||
base -= 257;
|
|
||||||
extra = lext;
|
|
||||||
extra -= 257;
|
|
||||||
end = 256;
|
|
||||||
break;
|
|
||||||
default: /* DISTS */
|
|
||||||
base = dbase;
|
|
||||||
extra = dext;
|
|
||||||
end = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* initialize state for loop */
|
|
||||||
huff = 0; /* starting code */
|
|
||||||
sym = 0; /* starting code symbol */
|
|
||||||
len = min; /* starting code length */
|
|
||||||
next = *table; /* current table to fill in */
|
|
||||||
curr = root; /* current table index bits */
|
|
||||||
drop = 0; /* current bits to drop from code for index */
|
|
||||||
low = (unsigned)(-1); /* trigger new sub-table when len > root */
|
|
||||||
used = 1U << root; /* use root table entries */
|
|
||||||
mask = used - 1; /* mask for comparing low */
|
|
||||||
|
|
||||||
/* check available table space */
|
|
||||||
if ((type == LENS && used > ENOUGH_LENS) ||
|
|
||||||
(type == DISTS && used > ENOUGH_DISTS))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* process all codes and make table entries */
|
|
||||||
for (;;) {
|
|
||||||
/* create table entry */
|
|
||||||
here.bits = (unsigned char)(len - drop);
|
|
||||||
if ((int)(work[sym]) < end) {
|
|
||||||
here.op = (unsigned char)0;
|
|
||||||
here.val = work[sym];
|
|
||||||
} else if ((int)(work[sym]) > end) {
|
|
||||||
here.op = (unsigned char)(extra[work[sym]]);
|
|
||||||
here.val = base[work[sym]];
|
|
||||||
} else {
|
|
||||||
here.op = (unsigned char)(32 + 64); /* end of block */
|
|
||||||
here.val = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* replicate for those indices with low len bits equal to huff */
|
|
||||||
incr = 1U << (len - drop);
|
|
||||||
fill = 1U << curr;
|
|
||||||
min = fill; /* save offset to next table */
|
|
||||||
do {
|
|
||||||
fill -= incr;
|
|
||||||
next[(huff >> drop) + fill] = here;
|
|
||||||
} while (fill != 0);
|
|
||||||
|
|
||||||
/* backwards increment the len-bit code huff */
|
|
||||||
incr = 1U << (len - 1);
|
|
||||||
while (huff & incr)
|
|
||||||
incr >>= 1;
|
|
||||||
if (incr != 0) {
|
|
||||||
huff &= incr - 1;
|
|
||||||
huff += incr;
|
|
||||||
} else {
|
|
||||||
huff = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* go to next symbol, update count, len */
|
|
||||||
sym++;
|
|
||||||
if (--(count[len]) == 0) {
|
|
||||||
if (len == max)
|
|
||||||
break;
|
|
||||||
len = lens[work[sym]];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create new sub-table if needed */
|
|
||||||
if (len > root && (huff & mask) != low) {
|
|
||||||
/* if first time, transition to sub-tables */
|
|
||||||
if (drop == 0)
|
|
||||||
drop = root;
|
|
||||||
|
|
||||||
/* increment past last table */
|
|
||||||
next += min; /* here min is 1 << curr */
|
|
||||||
|
|
||||||
/* determine length of next table */
|
|
||||||
curr = len - drop;
|
|
||||||
left = (int)(1 << curr);
|
|
||||||
while (curr + drop < max) {
|
|
||||||
left -= count[curr + drop];
|
|
||||||
if (left <= 0)
|
|
||||||
break;
|
|
||||||
curr++;
|
|
||||||
left <<= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check for enough space */
|
|
||||||
used += 1U << curr;
|
|
||||||
if ((type == LENS && used > ENOUGH_LENS) || (type == DISTS && used > ENOUGH_DISTS))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* point entry in root table to sub-table */
|
|
||||||
low = huff & mask;
|
|
||||||
(*table)[low].op = (unsigned char)curr;
|
|
||||||
(*table)[low].bits = (unsigned char)root;
|
|
||||||
(*table)[low].val = (uint16_t)(next - *table);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* fill in remaining table entry if code is incomplete (guaranteed to have
|
|
||||||
at most one remaining entry, since if the code is incomplete, the
|
|
||||||
maximum code length that was allowed to get this far is one bit) */
|
|
||||||
if (huff != 0) {
|
|
||||||
here.op = (unsigned char)64; /* invalid code marker */
|
|
||||||
here.bits = (unsigned char)(len - drop);
|
|
||||||
here.val = (uint16_t)0;
|
|
||||||
next[huff] = here;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set return parameters */
|
|
||||||
*table += used;
|
|
||||||
*bits = root;
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,66 +0,0 @@
|
|||||||
#ifndef INFTREES_H_
|
|
||||||
#define INFTREES_H_
|
|
||||||
|
|
||||||
/* inftrees.h -- header to use inftrees.c
|
|
||||||
* Copyright (C) 1995-2005, 2010 Mark Adler
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* WARNING: this file should *not* be used by applications. It is
|
|
||||||
part of the implementation of the compression library and is
|
|
||||||
subject to change. Applications should only use zlib.h.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Structure for decoding tables. Each entry provides either the
|
|
||||||
information needed to do the operation requested by the code that
|
|
||||||
indexed that table entry, or it provides a pointer to another
|
|
||||||
table that indexes more bits of the code. op indicates whether
|
|
||||||
the entry is a pointer to another table, a literal, a length or
|
|
||||||
distance, an end-of-block, or an invalid code. For a table
|
|
||||||
pointer, the low four bits of op is the number of index bits of
|
|
||||||
that table. For a length or distance, the low four bits of op
|
|
||||||
is the number of extra bits to get after the code. bits is
|
|
||||||
the number of bits in this code or part of the code to drop off
|
|
||||||
of the bit buffer. val is the actual byte to output in the case
|
|
||||||
of a literal, the base length or distance, or the offset from
|
|
||||||
the current table to the next table. Each entry is four bytes. */
|
|
||||||
typedef struct {
|
|
||||||
unsigned char op; /* operation, extra bits, table bits */
|
|
||||||
unsigned char bits; /* bits in this part of the code */
|
|
||||||
uint16_t val; /* offset in table or code value */
|
|
||||||
} code;
|
|
||||||
|
|
||||||
/* op values as set by inflate_table():
|
|
||||||
00000000 - literal
|
|
||||||
0000tttt - table link, tttt != 0 is the number of table index bits
|
|
||||||
0001eeee - length or distance, eeee is the number of extra bits
|
|
||||||
01100000 - end of block
|
|
||||||
01000000 - invalid code
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Maximum size of the dynamic table. The maximum number of code structures is
|
|
||||||
1444, which is the sum of 852 for literal/length codes and 592 for distance
|
|
||||||
codes. These values were found by exhaustive searches using the program
|
|
||||||
examples/enough.c found in the zlib distribtution. The arguments to that
|
|
||||||
program are the number of symbols, the initial root table size, and the
|
|
||||||
maximum bit length of a code. "enough 286 9 15" for literal/length codes
|
|
||||||
returns returns 852, and "enough 30 6 15" for distance codes returns 592.
|
|
||||||
The initial root table size (9 or 6) is found in the fifth argument of the
|
|
||||||
inflate_table() calls in inflate.c and infback.c. If the root table size is
|
|
||||||
changed, then these maximum sizes would be need to be recalculated and
|
|
||||||
updated. */
|
|
||||||
#define ENOUGH_LENS 852
|
|
||||||
#define ENOUGH_DISTS 592
|
|
||||||
#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)
|
|
||||||
|
|
||||||
/* Type of code to build for inflate_table() */
|
|
||||||
typedef enum {
|
|
||||||
CODES,
|
|
||||||
LENS,
|
|
||||||
DISTS
|
|
||||||
} codetype;
|
|
||||||
|
|
||||||
int ZLIB_INTERNAL inflate_table (codetype type, uint16_t *lens, unsigned codes,
|
|
||||||
code * *table, unsigned *bits, uint16_t *work);
|
|
||||||
|
|
||||||
#endif /* INFTREES_H_ */
|
|
@ -1,471 +0,0 @@
|
|||||||
/*
|
|
||||||
* Set match_start to the longest match starting at the given string and
|
|
||||||
* return its length. Matches shorter or equal to prev_length are discarded,
|
|
||||||
* in which case the result is equal to prev_length and match_start is garbage.
|
|
||||||
*
|
|
||||||
* IN assertions: cur_match is the head of the hash chain for the current
|
|
||||||
* string (strstart) and its distance is <= MAX_DIST, and prev_length >=1
|
|
||||||
* OUT assertion: the match length is not greater than s->lookahead
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "deflate.h"
|
|
||||||
|
|
||||||
#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
|
|
||||||
|
|
||||||
/* Only use std3_longest_match for little_endian systems, also avoid using it with
|
|
||||||
non-gcc compilers since the __builtin_ctzl() function might not be optimized. */
|
|
||||||
# if defined(__GNUC__) && defined(HAVE_BUILTIN_CTZL) && ((__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) \
|
|
||||||
|| defined(__LITTLE_ENDIAN__))
|
|
||||||
# define std3_longest_match
|
|
||||||
# elif(defined(_MSC_VER) && defined(_WIN32))
|
|
||||||
# define std3_longest_match
|
|
||||||
# else
|
|
||||||
# define std2_longest_match
|
|
||||||
# endif
|
|
||||||
|
|
||||||
#else
|
|
||||||
# define std1_longest_match
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && !defined(__clang__)
|
|
||||||
#include <intrin.h>
|
|
||||||
/* This is not a general purpose replacement for __builtin_ctzl. The function expects that value is != 0
|
|
||||||
* Because of that assumption trailing_zero is not initialized and the return value of _BitScanForward is not checked
|
|
||||||
*/
|
|
||||||
static __forceinline unsigned long __builtin_ctzl(unsigned long value)
|
|
||||||
{
|
|
||||||
unsigned long trailing_zero;
|
|
||||||
_BitScanForward(&trailing_zero, value);
|
|
||||||
return trailing_zero;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef std1_longest_match
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Standard longest_match
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
ZLIB_INTERNAL unsigned longest_match(deflate_state *const s, IPos cur_match) {
|
|
||||||
const unsigned wmask = s->w_mask;
|
|
||||||
const Pos *prev = s->prev;
|
|
||||||
|
|
||||||
unsigned chain_length;
|
|
||||||
IPos limit;
|
|
||||||
unsigned int len, best_len, nice_match;
|
|
||||||
unsigned char *scan, *match, *strend, scan_end, scan_end1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple
|
|
||||||
* of 16. It is easy to get rid of this optimization if necessary.
|
|
||||||
*/
|
|
||||||
Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Do not waste too much time if we already have a good match
|
|
||||||
*/
|
|
||||||
best_len = s->prev_length;
|
|
||||||
chain_length = s->max_chain_length;
|
|
||||||
if (best_len >= s->good_match)
|
|
||||||
chain_length >>= 2;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Do not looks for matches beyond the end of the input. This is
|
|
||||||
* necessary to make deflate deterministic
|
|
||||||
*/
|
|
||||||
nice_match = (unsigned int)s->nice_match > s->lookahead ? s->lookahead : s->nice_match;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Stop when cur_match becomes <= limit. To simplify the code,
|
|
||||||
* we prevent matches with the string of window index 0
|
|
||||||
*/
|
|
||||||
limit = s->strstart > MAX_DIST(s) ? s->strstart - MAX_DIST(s) : 0;
|
|
||||||
|
|
||||||
scan = s->window + s->strstart;
|
|
||||||
strend = s->window + s->strstart + MAX_MATCH;
|
|
||||||
scan_end1 = scan[best_len-1];
|
|
||||||
scan_end = scan[best_len];
|
|
||||||
|
|
||||||
Assert((unsigned long)s->strstart <= s->window_size - MIN_LOOKAHEAD, "need lookahead");
|
|
||||||
do {
|
|
||||||
Assert(cur_match < s->strstart, "no future");
|
|
||||||
match = s->window + cur_match;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Skip to next match if the match length cannot increase
|
|
||||||
* or if the match length is less than 2. Note that the checks
|
|
||||||
* below for insufficient lookahead only occur occasionally
|
|
||||||
* for performance reasons. Therefore uninitialized memory
|
|
||||||
* will be accessed and conditional jumps will be made that
|
|
||||||
* depend on those values. However the length of the match
|
|
||||||
* is limited to the lookahead, so the output of deflate is not
|
|
||||||
* affected by the uninitialized values.
|
|
||||||
*/
|
|
||||||
if (match[best_len] != scan_end ||
|
|
||||||
match[best_len-1] != scan_end1 ||
|
|
||||||
*match != *scan ||
|
|
||||||
*++match != scan[1])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The check at best_len-1 can be removed because it will
|
|
||||||
* be made again later. (This heuristic is not always a win.)
|
|
||||||
* It is not necessary to compare scan[2] and match[2] since
|
|
||||||
* they are always equal when the other bytes match, given
|
|
||||||
* that the hash keys are equal and that HASH_BITS >= 8.
|
|
||||||
*/
|
|
||||||
scan += 2;
|
|
||||||
match++;
|
|
||||||
Assert(*scan == *match, "match[2]?");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We check for insufficient lookahead only every 8th
|
|
||||||
* comparision; the 256th check will be made at strstart + 258.
|
|
||||||
*/
|
|
||||||
do {
|
|
||||||
} while (*++scan == *++match && *++scan == *++match &&
|
|
||||||
*++scan == *++match && *++scan == *++match &&
|
|
||||||
*++scan == *++match && *++scan == *++match &&
|
|
||||||
*++scan == *++match && *++scan == *++match &&
|
|
||||||
scan < strend);
|
|
||||||
|
|
||||||
Assert(scan <= s->window+(unsigned int)(s->window_size-1), "wild scan");
|
|
||||||
|
|
||||||
len = MAX_MATCH - (int)(strend - scan);
|
|
||||||
scan = strend - MAX_MATCH;
|
|
||||||
|
|
||||||
if (len > best_len) {
|
|
||||||
s->match_start = cur_match;
|
|
||||||
best_len = len;
|
|
||||||
if (len >= nice_match)
|
|
||||||
break;
|
|
||||||
scan_end1 = scan[best_len-1];
|
|
||||||
scan_end = scan[best_len];
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* The probability of finding a match later if we here
|
|
||||||
* is pretty low, so for performance it's best to
|
|
||||||
* outright stop here for the lower compression levels
|
|
||||||
*/
|
|
||||||
if (s->level < 6)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length);
|
|
||||||
|
|
||||||
if ((unsigned int)best_len <= s->lookahead)
|
|
||||||
return best_len;
|
|
||||||
return s->lookahead;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef std2_longest_match
|
|
||||||
/*
|
|
||||||
* UNALIGNED_OK longest_match
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
ZLIB_INTERNAL unsigned longest_match(deflate_state *const s, IPos cur_match) {
|
|
||||||
const unsigned wmask = s->w_mask;
|
|
||||||
const Pos *prev = s->prev;
|
|
||||||
|
|
||||||
uint16_t scan_start, scan_end;
|
|
||||||
unsigned chain_length;
|
|
||||||
IPos limit;
|
|
||||||
unsigned int len, best_len, nice_match;
|
|
||||||
unsigned char *scan, *strend;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple
|
|
||||||
* of 16. It is easy to get rid of this optimization if necessary.
|
|
||||||
*/
|
|
||||||
Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Do not waste too much time if we already have a good match
|
|
||||||
*/
|
|
||||||
best_len = s->prev_length;
|
|
||||||
chain_length = s->max_chain_length;
|
|
||||||
if (best_len >= s->good_match)
|
|
||||||
chain_length >>= 2;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Do not looks for matches beyond the end of the input. This is
|
|
||||||
* necessary to make deflate deterministic
|
|
||||||
*/
|
|
||||||
nice_match = (unsigned int)s->nice_match > s->lookahead ? s->lookahead : s->nice_match;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Stop when cur_match becomes <= limit. To simplify the code,
|
|
||||||
* we prevent matches with the string of window index 0
|
|
||||||
*/
|
|
||||||
limit = s->strstart > MAX_DIST(s) ? s->strstart - MAX_DIST(s) : 0;
|
|
||||||
|
|
||||||
scan = s->window + s->strstart;
|
|
||||||
strend = s->window + s->strstart + MAX_MATCH - 1;
|
|
||||||
scan_start = *(uint16_t *)scan;
|
|
||||||
scan_end = *(uint16_t *)(scan + best_len-1);
|
|
||||||
|
|
||||||
Assert((unsigned long)s->strstart <= s->window_size - MIN_LOOKAHEAD, "need lookahead");
|
|
||||||
do {
|
|
||||||
unsigned char *match;
|
|
||||||
Assert(cur_match < s->strstart, "no future");
|
|
||||||
match = s->window + cur_match;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Skip to next match if the match length cannot increase
|
|
||||||
* or if the match length is less than 2. Note that the checks
|
|
||||||
* below for insufficient lookahead only occur occasionally
|
|
||||||
* for performance reasons. Therefore uninitialized memory
|
|
||||||
* will be accessed and conditional jumps will be made that
|
|
||||||
* depend on those values. However the length of the match
|
|
||||||
* is limited to the lookahead, so the output of deflate is not
|
|
||||||
* affected by the uninitialized values.
|
|
||||||
*/
|
|
||||||
if (likely((*(uint16_t *)(match + best_len - 1) != scan_end)))
|
|
||||||
continue;
|
|
||||||
if (*(uint16_t *)match != scan_start)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* It is not necessary to compare scan[2] and match[2] since
|
|
||||||
* they are always equal when the other bytes match, given that
|
|
||||||
* the hash keys are equal and that HASH_BITS >= 8. Compare 2
|
|
||||||
* bytes at a time at strstart+3, +5, ... up to strstart+257.
|
|
||||||
* We check for insufficient lookahead only every 4th
|
|
||||||
* comparison; the 128th check will be made at strstart+257.
|
|
||||||
* If MAX_MATCH-2 is not a multiple of 8, it is necessary to
|
|
||||||
* put more guard bytes at the end of the window, or to check
|
|
||||||
* more often for insufficient lookahead.
|
|
||||||
*/
|
|
||||||
Assert(scan[2] == match[2], "scan[2]?");
|
|
||||||
scan++;
|
|
||||||
match++;
|
|
||||||
|
|
||||||
do {
|
|
||||||
} while (*(uint16_t *)(scan += 2)== *(uint16_t *)(match += 2) &&
|
|
||||||
*(uint16_t *)(scan += 2)== *(uint16_t *)(match += 2) &&
|
|
||||||
*(uint16_t *)(scan += 2)== *(uint16_t *)(match += 2) &&
|
|
||||||
*(uint16_t *)(scan += 2)== *(uint16_t *)(match += 2) &&
|
|
||||||
scan < strend);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Here, scan <= window + strstart + 257
|
|
||||||
*/
|
|
||||||
Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
|
|
||||||
if (*scan == *match)
|
|
||||||
scan++;
|
|
||||||
|
|
||||||
len = (MAX_MATCH -1) - (int)(strend-scan);
|
|
||||||
scan = strend - (MAX_MATCH-1);
|
|
||||||
|
|
||||||
if (len > best_len) {
|
|
||||||
s->match_start = cur_match;
|
|
||||||
best_len = len;
|
|
||||||
if (len >= nice_match)
|
|
||||||
break;
|
|
||||||
scan_end = *(uint16_t *)(scan + best_len - 1);
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* The probability of finding a match later if we here
|
|
||||||
* is pretty low, so for performance it's best to
|
|
||||||
* outright stop here for the lower compression levels
|
|
||||||
*/
|
|
||||||
if (s->level < 6)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while (--chain_length && (cur_match = prev[cur_match & wmask]) > limit);
|
|
||||||
|
|
||||||
if ((unsigned)best_len <= s->lookahead)
|
|
||||||
return best_len;
|
|
||||||
return s->lookahead;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef std3_longest_match
|
|
||||||
/* longest_match() with minor change to improve performance (in terms of
|
|
||||||
* execution time).
|
|
||||||
*
|
|
||||||
* The pristine longest_match() function is sketched bellow (strip the
|
|
||||||
* then-clause of the "#ifdef UNALIGNED_OK"-directive)
|
|
||||||
*
|
|
||||||
* ------------------------------------------------------------
|
|
||||||
* unsigned int longest_match(...) {
|
|
||||||
* ...
|
|
||||||
* do {
|
|
||||||
* match = s->window + cur_match; //s0
|
|
||||||
* if (*(ushf*)(match+best_len-1) != scan_end || //s1
|
|
||||||
* *(ushf*)match != scan_start) continue; //s2
|
|
||||||
* ...
|
|
||||||
*
|
|
||||||
* do {
|
|
||||||
* } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
|
|
||||||
* *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
|
|
||||||
* *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
|
|
||||||
* *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
|
|
||||||
* scan < strend); //s3
|
|
||||||
*
|
|
||||||
* ...
|
|
||||||
* } while(cond); //s4
|
|
||||||
*
|
|
||||||
* -------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* The change include:
|
|
||||||
*
|
|
||||||
* 1) The hottest statements of the function is: s0, s1 and s4. Pull them
|
|
||||||
* together to form a new loop. The benefit is two-fold:
|
|
||||||
*
|
|
||||||
* o. Ease the compiler to yield good code layout: the conditional-branch
|
|
||||||
* corresponding to s1 and its biased target s4 become very close (likely,
|
|
||||||
* fit in the same cache-line), hence improving instruction-fetching
|
|
||||||
* efficiency.
|
|
||||||
*
|
|
||||||
* o. Ease the compiler to promote "s->window" into register. "s->window"
|
|
||||||
* is loop-invariant; it is supposed to be promoted into register and keep
|
|
||||||
* the value throughout the entire loop. However, there are many such
|
|
||||||
* loop-invariant, and x86-family has small register file; "s->window" is
|
|
||||||
* likely to be chosen as register-allocation victim such that its value
|
|
||||||
* is reloaded from memory in every single iteration. By forming a new loop,
|
|
||||||
* "s->window" is loop-invariant of that newly created tight loop. It is
|
|
||||||
* lot easier for compiler to promote this quantity to register and keep
|
|
||||||
* its value throughout the entire small loop.
|
|
||||||
*
|
|
||||||
* 2) Transfrom s3 such that it examines sizeof(long)-byte-match at a time.
|
|
||||||
* This is done by:
|
|
||||||
* ------------------------------------------------
|
|
||||||
* v1 = load from "scan" by sizeof(long) bytes
|
|
||||||
* v2 = load from "match" by sizeof(lnog) bytes
|
|
||||||
* v3 = v1 xor v2
|
|
||||||
* match-bit = little-endian-machine(yes-for-x86) ?
|
|
||||||
* count-trailing-zero(v3) :
|
|
||||||
* count-leading-zero(v3);
|
|
||||||
*
|
|
||||||
* match-byte = match-bit/8
|
|
||||||
*
|
|
||||||
* "scan" and "match" advance if necessary
|
|
||||||
* -------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
ZLIB_INTERNAL unsigned longest_match(deflate_state *const s, IPos cur_match) {
|
|
||||||
unsigned chain_length = s->max_chain_length;/* max hash chain length */
|
|
||||||
register unsigned char *scan = s->window + s->strstart; /* current string */
|
|
||||||
register unsigned char *match; /* matched string */
|
|
||||||
register unsigned int len; /* length of current match */
|
|
||||||
unsigned int best_len = s->prev_length; /* best match length so far */
|
|
||||||
unsigned int nice_match = s->nice_match; /* stop if match long enough */
|
|
||||||
IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
|
|
||||||
s->strstart - (IPos)MAX_DIST(s) : NIL;
|
|
||||||
/* Stop when cur_match becomes <= limit. To simplify the code,
|
|
||||||
* we prevent matches with the string of window index 0.
|
|
||||||
*/
|
|
||||||
Pos *prev = s->prev;
|
|
||||||
unsigned int wmask = s->w_mask;
|
|
||||||
|
|
||||||
register unsigned char *strend = s->window + s->strstart + MAX_MATCH;
|
|
||||||
register uint16_t scan_start = *(uint16_t*)scan;
|
|
||||||
register uint16_t scan_end = *(uint16_t*)(scan+best_len-1);
|
|
||||||
|
|
||||||
/* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
|
|
||||||
* It is easy to get rid of this optimization if necessary.
|
|
||||||
*/
|
|
||||||
Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
|
|
||||||
|
|
||||||
/* Do not waste too much time if we already have a good match: */
|
|
||||||
if (s->prev_length >= s->good_match) {
|
|
||||||
chain_length >>= 2;
|
|
||||||
}
|
|
||||||
/* Do not look for matches beyond the end of the input. This is necessary
|
|
||||||
* to make deflate deterministic.
|
|
||||||
*/
|
|
||||||
if ((unsigned int)nice_match > s->lookahead) nice_match = s->lookahead;
|
|
||||||
|
|
||||||
Assert((unsigned long)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
|
|
||||||
|
|
||||||
do {
|
|
||||||
Assert(cur_match < s->strstart, "no future");
|
|
||||||
|
|
||||||
/* Skip to next match if the match length cannot increase
|
|
||||||
* or if the match length is less than 2. Note that the checks below
|
|
||||||
* for insufficient lookahead only occur occasionally for performance
|
|
||||||
* reasons. Therefore uninitialized memory will be accessed, and
|
|
||||||
* conditional jumps will be made that depend on those values.
|
|
||||||
* However the length of the match is limited to the lookahead, so
|
|
||||||
* the output of deflate is not affected by the uninitialized values.
|
|
||||||
*/
|
|
||||||
unsigned char *win = s->window;
|
|
||||||
int cont = 1;
|
|
||||||
do {
|
|
||||||
match = win + cur_match;
|
|
||||||
if (likely(*(uint16_t*)(match+best_len-1) != scan_end)) {
|
|
||||||
if ((cur_match = prev[cur_match & wmask]) > limit
|
|
||||||
&& --chain_length != 0) {
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
cont = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
} while (1);
|
|
||||||
|
|
||||||
if (!cont)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (*(uint16_t*)match != scan_start)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* It is not necessary to compare scan[2] and match[2] since they are
|
|
||||||
* always equal when the other bytes match, given that the hash keys
|
|
||||||
* are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
|
|
||||||
* strstart+3, +5, ... up to strstart+257. We check for insufficient
|
|
||||||
* lookahead only every 4th comparison; the 128th check will be made
|
|
||||||
* at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
|
|
||||||
* necessary to put more guard bytes at the end of the window, or
|
|
||||||
* to check more often for insufficient lookahead.
|
|
||||||
*/
|
|
||||||
scan += 2, match+=2;
|
|
||||||
Assert(*scan == *match, "match[2]?");
|
|
||||||
do {
|
|
||||||
unsigned long sv = *(unsigned long*)(void*)scan;
|
|
||||||
unsigned long mv = *(unsigned long*)(void*)match;
|
|
||||||
unsigned long xor = sv ^ mv;
|
|
||||||
if (xor) {
|
|
||||||
int match_byte = __builtin_ctzl(xor) / 8;
|
|
||||||
scan += match_byte;
|
|
||||||
match += match_byte;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
scan += sizeof(unsigned long);
|
|
||||||
match += sizeof(unsigned long);
|
|
||||||
}
|
|
||||||
} while (scan < strend);
|
|
||||||
|
|
||||||
if (scan > strend)
|
|
||||||
scan = strend;
|
|
||||||
|
|
||||||
Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
|
|
||||||
|
|
||||||
len = MAX_MATCH - (int)(strend - scan);
|
|
||||||
scan = strend - MAX_MATCH;
|
|
||||||
|
|
||||||
if (len > best_len) {
|
|
||||||
s->match_start = cur_match;
|
|
||||||
best_len = len;
|
|
||||||
if (len >= nice_match)
|
|
||||||
break;
|
|
||||||
scan_end = *(uint16_t*)(scan+best_len-1);
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* The probability of finding a match later if we here
|
|
||||||
* is pretty low, so for performance it's best to
|
|
||||||
* outright stop here for the lower compression levels
|
|
||||||
*/
|
|
||||||
if (s->level < 6)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length != 0);
|
|
||||||
|
|
||||||
if ((unsigned int)best_len <= s->lookahead)
|
|
||||||
return (unsigned int)best_len;
|
|
||||||
return s->lookahead;
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,6 +0,0 @@
|
|||||||
#ifndef MATCH_H_
|
|
||||||
#define MATCH_H_
|
|
||||||
|
|
||||||
unsigned int longest_match (deflate_state *s, IPos cur_match);
|
|
||||||
|
|
||||||
#endif /* MATCH_H_ */
|
|
2
contrib/libzlib-ng/test/.gitignore
vendored
2
contrib/libzlib-ng/test/.gitignore
vendored
@ -1,2 +0,0 @@
|
|||||||
# ignore Makefiles; they're all automatically generated
|
|
||||||
Makefile
|
|
Binary file not shown.
@ -1,20 +0,0 @@
|
|||||||
// http://www.securityfocus.com/archive/1/312869 --- originally by Richard Kettlewell
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <zlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
gzFile f;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if(!(f = gzopen("/dev/null", "w"))) {
|
|
||||||
perror("/dev/null");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
ret = gzprintf(f, "%10240s", "");
|
|
||||||
printf("gzprintf -> %d\n", ret);
|
|
||||||
ret = gzclose(f);
|
|
||||||
printf("gzclose -> %d [%d]\n", ret, errno);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,10 +0,0 @@
|
|||||||
Makefile.in: template for Unix Makefile
|
|
||||||
|
|
||||||
CVE-2003-0107.c:
|
|
||||||
CVE-2002-0059 :
|
|
||||||
CVE-2004-0797 :
|
|
||||||
CVE-2005-1849 :
|
|
||||||
CVE-2005-2096 : test cases for the relevant CVEs
|
|
||||||
|
|
||||||
testCVEinputs.sh: script to run tests for CVEs where input data is supplied
|
|
||||||
|
|
@ -1,77 +0,0 @@
|
|||||||
# Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
|
|
||||||
# Copyright 2015, Daniel Axtens, IBM Corporation
|
|
||||||
# zlib license, see zlib.h
|
|
||||||
|
|
||||||
CC=
|
|
||||||
CFLAGS=
|
|
||||||
EXE=
|
|
||||||
SRCDIR=
|
|
||||||
SRCTOP=
|
|
||||||
INCLUDES=
|
|
||||||
TEST_LDFLAGS=-L.. ../libz.a
|
|
||||||
|
|
||||||
COMPATTESTS =
|
|
||||||
|
|
||||||
all: oldtests cvetests $(COMPATTESTS)
|
|
||||||
|
|
||||||
oldtests: #set by ../configure
|
|
||||||
|
|
||||||
teststatic:
|
|
||||||
@TMPST=tmpst_$$; \
|
|
||||||
if echo hello world | ../minigzip | ../minigzip -d && ../example $$TMPST ; then \
|
|
||||||
echo ' *** zlib test OK ***'; \
|
|
||||||
else \
|
|
||||||
echo ' *** zlib test FAILED ***'; exit 1; \
|
|
||||||
fi; \
|
|
||||||
rm -f $$TMPST
|
|
||||||
|
|
||||||
testshared:
|
|
||||||
@LD_LIBRARY_PATH=`pwd`/..:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
|
|
||||||
LD_LIBRARYN32_PATH=`pwd`/..:$(LD_LIBRARYN32_PATH) ; export LD_LIBRARYN32_PATH; \
|
|
||||||
DYLD_LIBRARY_PATH=`pwd`/..:$(DYLD_LIBRARY_PATH) ; export DYLD_LIBRARY_PATH; \
|
|
||||||
SHLIB_PATH=`pwd`/..:$(SHLIB_PATH) ; export SHLIB_PATH; \
|
|
||||||
TMPSH=tmpsh_$$; \
|
|
||||||
if echo hello world | ../minigzipsh | ../minigzipsh -d && ../examplesh $$TMPSH; then \
|
|
||||||
echo ' *** zlib shared test OK ***'; \
|
|
||||||
else \
|
|
||||||
echo ' *** zlib shared test FAILED ***'; exit 1; \
|
|
||||||
fi; \
|
|
||||||
rm -f $$TMPSH
|
|
||||||
|
|
||||||
test64:
|
|
||||||
@TMP64=tmp64_$$; \
|
|
||||||
if echo hello world | ../minigzip64 | ../minigzip64 -d && ../example64 $$TMP64; then \
|
|
||||||
echo ' *** zlib 64-bit test OK ***'; \
|
|
||||||
else \
|
|
||||||
echo ' *** zlib 64-bit test FAILED ***'; exit 1; \
|
|
||||||
fi; \
|
|
||||||
rm -f $$TMP64
|
|
||||||
|
|
||||||
cvetests: testCVEinputs
|
|
||||||
|
|
||||||
# Tests requiring zlib-ng to be built with --zlib-compat
|
|
||||||
compattests: testCVE-2003-0107
|
|
||||||
|
|
||||||
testCVEinputs:
|
|
||||||
@$(SRCDIR)/testCVEinputs.sh
|
|
||||||
|
|
||||||
testCVE-2003-0107: CVE-2003-0107$(EXE)
|
|
||||||
@if ./CVE-2003-0107$(EXE); then \
|
|
||||||
echo ' *** zlib not vulnerable to CVE-2003-0107 ***'; \
|
|
||||||
else \
|
|
||||||
echo ' *** zlib VULNERABLE to CVE-2003-0107 ***'; exit 1; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
CVE-2003-0107.o: $(SRCDIR)/CVE-2003-0107.c
|
|
||||||
$(CC) $(CFLAGS) -I.. -I$(SRCTOP) -c -o $@ $(SRCDIR)/CVE-2003-0107.c
|
|
||||||
|
|
||||||
CVE-2003-0107$(EXE): CVE-2003-0107.o
|
|
||||||
$(CC) $(CFLAGS) -o $@ CVE-2003-0107.o $(TEST_LDFLAGS)
|
|
||||||
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f *.o *.gcda *.gcno *.gcov
|
|
||||||
rm -f CVE-2003-0107$(EXE)
|
|
||||||
|
|
||||||
distclean:
|
|
||||||
rm -f Makefile
|
|
@ -1,544 +0,0 @@
|
|||||||
/* example.c -- usage example of the zlib compression library
|
|
||||||
* Copyright (C) 1995-2006, 2011 Jean-loup Gailly.
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* @(#) $Id$ */
|
|
||||||
|
|
||||||
#include "zlib.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#define TESTFILE "foo.gz"
|
|
||||||
|
|
||||||
#define CHECK_ERR(err, msg) { \
|
|
||||||
if (err != Z_OK) { \
|
|
||||||
fprintf(stderr, "%s error: %d\n", msg, err); \
|
|
||||||
exit(1); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
const char hello[] = "hello, hello!";
|
|
||||||
/* "hello world" would be more standard, but the repeated "hello"
|
|
||||||
* stresses the compression code better, sorry...
|
|
||||||
*/
|
|
||||||
|
|
||||||
const char dictionary[] = "hello";
|
|
||||||
unsigned long dictId; /* Adler32 value of the dictionary */
|
|
||||||
|
|
||||||
void test_deflate (unsigned char *compr, size_t comprLen);
|
|
||||||
void test_inflate (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen);
|
|
||||||
void test_large_deflate (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen);
|
|
||||||
void test_large_inflate (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen);
|
|
||||||
void test_flush (unsigned char *compr, size_t *comprLen);
|
|
||||||
void test_sync (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen);
|
|
||||||
void test_dict_deflate (unsigned char *compr, size_t comprLen);
|
|
||||||
void test_dict_inflate (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen);
|
|
||||||
int main (int argc, char *argv[]);
|
|
||||||
|
|
||||||
|
|
||||||
static alloc_func zalloc = (alloc_func)0;
|
|
||||||
static free_func zfree = (free_func)0;
|
|
||||||
|
|
||||||
void test_compress (unsigned char *compr, size_t comprLen,
|
|
||||||
unsigned char *uncompr, size_t uncomprLen);
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Test compress() and uncompress()
|
|
||||||
*/
|
|
||||||
void test_compress(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
size_t len = strlen(hello)+1;
|
|
||||||
|
|
||||||
err = compress(compr, &comprLen, (const unsigned char*)hello, len);
|
|
||||||
CHECK_ERR(err, "compress");
|
|
||||||
|
|
||||||
strcpy((char*)uncompr, "garbage");
|
|
||||||
|
|
||||||
err = uncompress(uncompr, &uncomprLen, compr, comprLen);
|
|
||||||
CHECK_ERR(err, "uncompress");
|
|
||||||
|
|
||||||
if (strcmp((char*)uncompr, hello)) {
|
|
||||||
fprintf(stderr, "bad uncompress\n");
|
|
||||||
exit(1);
|
|
||||||
} else {
|
|
||||||
printf("uncompress(): %s\n", (char *)uncompr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WITH_GZFILEOP
|
|
||||||
void test_gzio (const char *fname,
|
|
||||||
unsigned char *uncompr, unsigned long uncomprLen);
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Test read/write of .gz files
|
|
||||||
*/
|
|
||||||
void test_gzio(const char *fname, unsigned char *uncompr, unsigned long uncomprLen)
|
|
||||||
{
|
|
||||||
#ifdef NO_GZCOMPRESS
|
|
||||||
fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");
|
|
||||||
#else
|
|
||||||
int err;
|
|
||||||
int len = (int)strlen(hello)+1;
|
|
||||||
gzFile file;
|
|
||||||
z_off_t pos;
|
|
||||||
|
|
||||||
file = gzopen(fname, "wb");
|
|
||||||
if (file == NULL) {
|
|
||||||
fprintf(stderr, "gzopen error\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
gzputc(file, 'h');
|
|
||||||
if (gzputs(file, "ello") != 4) {
|
|
||||||
fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (gzprintf(file, ", %s!", "hello") != 8) {
|
|
||||||
fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
gzseek(file, 1L, SEEK_CUR); /* add one zero byte */
|
|
||||||
gzclose(file);
|
|
||||||
|
|
||||||
file = gzopen(fname, "rb");
|
|
||||||
if (file == NULL) {
|
|
||||||
fprintf(stderr, "gzopen error\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
strcpy((char*)uncompr, "garbage");
|
|
||||||
|
|
||||||
if (gzread(file, uncompr, (unsigned)uncomprLen) != len) {
|
|
||||||
fprintf(stderr, "gzread err: %s\n", gzerror(file, &err));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (strcmp((char*)uncompr, hello)) {
|
|
||||||
fprintf(stderr, "bad gzread: %s\n", (char*)uncompr);
|
|
||||||
exit(1);
|
|
||||||
} else {
|
|
||||||
printf("gzread(): %s\n", (char*)uncompr);
|
|
||||||
}
|
|
||||||
|
|
||||||
pos = gzseek(file, -8L, SEEK_CUR);
|
|
||||||
if (pos != 6 || gztell(file) != pos) {
|
|
||||||
fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",
|
|
||||||
(long)pos, (long)gztell(file));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gzgetc(file) != ' ') {
|
|
||||||
fprintf(stderr, "gzgetc error\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gzungetc(' ', file) != ' ') {
|
|
||||||
fprintf(stderr, "gzungetc error\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
gzgets(file, (char*)uncompr, (int)uncomprLen);
|
|
||||||
if (strlen((char*)uncompr) != 7) { /* " hello!" */
|
|
||||||
fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (strcmp((char*)uncompr, hello + 6)) {
|
|
||||||
fprintf(stderr, "bad gzgets after gzseek\n");
|
|
||||||
exit(1);
|
|
||||||
} else {
|
|
||||||
printf("gzgets() after gzseek: %s\n", (char*)uncompr);
|
|
||||||
}
|
|
||||||
|
|
||||||
gzclose(file);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* WITH_GZFILEOP */
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Test deflate() with small buffers
|
|
||||||
*/
|
|
||||||
void test_deflate(unsigned char *compr, size_t comprLen)
|
|
||||||
{
|
|
||||||
z_stream c_stream; /* compression stream */
|
|
||||||
int err;
|
|
||||||
unsigned long len = (unsigned long)strlen(hello)+1;
|
|
||||||
|
|
||||||
c_stream.zalloc = zalloc;
|
|
||||||
c_stream.zfree = zfree;
|
|
||||||
c_stream.opaque = (void *)0;
|
|
||||||
|
|
||||||
err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
|
|
||||||
CHECK_ERR(err, "deflateInit");
|
|
||||||
|
|
||||||
c_stream.next_in = (const unsigned char *)hello;
|
|
||||||
c_stream.next_out = compr;
|
|
||||||
|
|
||||||
while (c_stream.total_in != len && c_stream.total_out < comprLen) {
|
|
||||||
c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
|
|
||||||
err = deflate(&c_stream, Z_NO_FLUSH);
|
|
||||||
CHECK_ERR(err, "deflate");
|
|
||||||
}
|
|
||||||
/* Finish the stream, still forcing small buffers: */
|
|
||||||
for (;;) {
|
|
||||||
c_stream.avail_out = 1;
|
|
||||||
err = deflate(&c_stream, Z_FINISH);
|
|
||||||
if (err == Z_STREAM_END) break;
|
|
||||||
CHECK_ERR(err, "deflate");
|
|
||||||
}
|
|
||||||
|
|
||||||
err = deflateEnd(&c_stream);
|
|
||||||
CHECK_ERR(err, "deflateEnd");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Test inflate() with small buffers
|
|
||||||
*/
|
|
||||||
void test_inflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
z_stream d_stream; /* decompression stream */
|
|
||||||
|
|
||||||
strcpy((char*)uncompr, "garbage");
|
|
||||||
|
|
||||||
d_stream.zalloc = zalloc;
|
|
||||||
d_stream.zfree = zfree;
|
|
||||||
d_stream.opaque = (void *)0;
|
|
||||||
|
|
||||||
d_stream.next_in = compr;
|
|
||||||
d_stream.avail_in = 0;
|
|
||||||
d_stream.next_out = uncompr;
|
|
||||||
|
|
||||||
err = inflateInit(&d_stream);
|
|
||||||
CHECK_ERR(err, "inflateInit");
|
|
||||||
|
|
||||||
while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
|
|
||||||
d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
|
|
||||||
err = inflate(&d_stream, Z_NO_FLUSH);
|
|
||||||
if (err == Z_STREAM_END) break;
|
|
||||||
CHECK_ERR(err, "inflate");
|
|
||||||
}
|
|
||||||
|
|
||||||
err = inflateEnd(&d_stream);
|
|
||||||
CHECK_ERR(err, "inflateEnd");
|
|
||||||
|
|
||||||
if (strcmp((char*)uncompr, hello)) {
|
|
||||||
fprintf(stderr, "bad inflate\n");
|
|
||||||
exit(1);
|
|
||||||
} else {
|
|
||||||
printf("inflate(): %s\n", (char *)uncompr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Test deflate() with large buffers and dynamic change of compression level
|
|
||||||
*/
|
|
||||||
void test_large_deflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen)
|
|
||||||
{
|
|
||||||
z_stream c_stream; /* compression stream */
|
|
||||||
int err;
|
|
||||||
|
|
||||||
c_stream.zalloc = zalloc;
|
|
||||||
c_stream.zfree = zfree;
|
|
||||||
c_stream.opaque = (void *)0;
|
|
||||||
|
|
||||||
err = deflateInit(&c_stream, Z_BEST_SPEED);
|
|
||||||
CHECK_ERR(err, "deflateInit");
|
|
||||||
|
|
||||||
c_stream.next_out = compr;
|
|
||||||
c_stream.avail_out = (unsigned int)comprLen;
|
|
||||||
|
|
||||||
/* At this point, uncompr is still mostly zeroes, so it should compress
|
|
||||||
* very well:
|
|
||||||
*/
|
|
||||||
c_stream.next_in = uncompr;
|
|
||||||
c_stream.avail_in = (unsigned int)uncomprLen;
|
|
||||||
err = deflate(&c_stream, Z_NO_FLUSH);
|
|
||||||
CHECK_ERR(err, "deflate");
|
|
||||||
if (c_stream.avail_in != 0) {
|
|
||||||
fprintf(stderr, "deflate not greedy\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Feed in already compressed data and switch to no compression: */
|
|
||||||
deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
|
|
||||||
c_stream.next_in = compr;
|
|
||||||
c_stream.avail_in = (unsigned int)comprLen/2;
|
|
||||||
err = deflate(&c_stream, Z_NO_FLUSH);
|
|
||||||
CHECK_ERR(err, "deflate");
|
|
||||||
|
|
||||||
/* Switch back to compressing mode: */
|
|
||||||
deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
|
|
||||||
c_stream.next_in = uncompr;
|
|
||||||
c_stream.avail_in = (unsigned int)uncomprLen;
|
|
||||||
err = deflate(&c_stream, Z_NO_FLUSH);
|
|
||||||
CHECK_ERR(err, "deflate");
|
|
||||||
|
|
||||||
err = deflate(&c_stream, Z_FINISH);
|
|
||||||
if (err != Z_STREAM_END) {
|
|
||||||
fprintf(stderr, "deflate should report Z_STREAM_END\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
err = deflateEnd(&c_stream);
|
|
||||||
CHECK_ERR(err, "deflateEnd");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Test inflate() with large buffers
|
|
||||||
*/
|
|
||||||
void test_large_inflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
z_stream d_stream; /* decompression stream */
|
|
||||||
|
|
||||||
strcpy((char*)uncompr, "garbage");
|
|
||||||
|
|
||||||
d_stream.zalloc = zalloc;
|
|
||||||
d_stream.zfree = zfree;
|
|
||||||
d_stream.opaque = (void *)0;
|
|
||||||
|
|
||||||
d_stream.next_in = compr;
|
|
||||||
d_stream.avail_in = (unsigned int)comprLen;
|
|
||||||
|
|
||||||
err = inflateInit(&d_stream);
|
|
||||||
CHECK_ERR(err, "inflateInit");
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
d_stream.next_out = uncompr; /* discard the output */
|
|
||||||
d_stream.avail_out = (unsigned int)uncomprLen;
|
|
||||||
err = inflate(&d_stream, Z_NO_FLUSH);
|
|
||||||
if (err == Z_STREAM_END) break;
|
|
||||||
CHECK_ERR(err, "large inflate");
|
|
||||||
}
|
|
||||||
|
|
||||||
err = inflateEnd(&d_stream);
|
|
||||||
CHECK_ERR(err, "inflateEnd");
|
|
||||||
|
|
||||||
if (d_stream.total_out != 2*uncomprLen + comprLen/2) {
|
|
||||||
fprintf(stderr, "bad large inflate: %zu\n", d_stream.total_out);
|
|
||||||
exit(1);
|
|
||||||
} else {
|
|
||||||
printf("large_inflate(): OK\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Test deflate() with full flush
|
|
||||||
*/
|
|
||||||
void test_flush(unsigned char *compr, size_t *comprLen)
|
|
||||||
{
|
|
||||||
z_stream c_stream; /* compression stream */
|
|
||||||
int err;
|
|
||||||
unsigned int len = (unsigned int)strlen(hello)+1;
|
|
||||||
|
|
||||||
c_stream.zalloc = zalloc;
|
|
||||||
c_stream.zfree = zfree;
|
|
||||||
c_stream.opaque = (void *)0;
|
|
||||||
|
|
||||||
err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
|
|
||||||
CHECK_ERR(err, "deflateInit");
|
|
||||||
|
|
||||||
c_stream.next_in = (const unsigned char *)hello;
|
|
||||||
c_stream.next_out = compr;
|
|
||||||
c_stream.avail_in = 3;
|
|
||||||
c_stream.avail_out = (unsigned int)*comprLen;
|
|
||||||
err = deflate(&c_stream, Z_FULL_FLUSH);
|
|
||||||
CHECK_ERR(err, "deflate");
|
|
||||||
|
|
||||||
compr[3]++; /* force an error in first compressed block */
|
|
||||||
c_stream.avail_in = len - 3;
|
|
||||||
|
|
||||||
err = deflate(&c_stream, Z_FINISH);
|
|
||||||
if (err != Z_STREAM_END) {
|
|
||||||
CHECK_ERR(err, "deflate");
|
|
||||||
}
|
|
||||||
err = deflateEnd(&c_stream);
|
|
||||||
CHECK_ERR(err, "deflateEnd");
|
|
||||||
|
|
||||||
*comprLen = c_stream.total_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Test inflateSync()
|
|
||||||
*/
|
|
||||||
void test_sync(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
z_stream d_stream; /* decompression stream */
|
|
||||||
|
|
||||||
strcpy((char*)uncompr, "garbage");
|
|
||||||
|
|
||||||
d_stream.zalloc = zalloc;
|
|
||||||
d_stream.zfree = zfree;
|
|
||||||
d_stream.opaque = (void *)0;
|
|
||||||
|
|
||||||
d_stream.next_in = compr;
|
|
||||||
d_stream.avail_in = 2; /* just read the zlib header */
|
|
||||||
|
|
||||||
err = inflateInit(&d_stream);
|
|
||||||
CHECK_ERR(err, "inflateInit");
|
|
||||||
|
|
||||||
d_stream.next_out = uncompr;
|
|
||||||
d_stream.avail_out = (unsigned int)uncomprLen;
|
|
||||||
|
|
||||||
err = inflate(&d_stream, Z_NO_FLUSH);
|
|
||||||
CHECK_ERR(err, "inflate");
|
|
||||||
|
|
||||||
d_stream.avail_in = (unsigned int)comprLen-2; /* read all compressed data */
|
|
||||||
err = inflateSync(&d_stream); /* but skip the damaged part */
|
|
||||||
CHECK_ERR(err, "inflateSync");
|
|
||||||
|
|
||||||
err = inflate(&d_stream, Z_FINISH);
|
|
||||||
if (err != Z_DATA_ERROR) {
|
|
||||||
fprintf(stderr, "inflate should report DATA_ERROR\n");
|
|
||||||
/* Because of incorrect adler32 */
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
err = inflateEnd(&d_stream);
|
|
||||||
CHECK_ERR(err, "inflateEnd");
|
|
||||||
|
|
||||||
printf("after inflateSync(): hel%s\n", (char *)uncompr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Test deflate() with preset dictionary
|
|
||||||
*/
|
|
||||||
void test_dict_deflate(unsigned char *compr, size_t comprLen)
|
|
||||||
{
|
|
||||||
z_stream c_stream; /* compression stream */
|
|
||||||
int err;
|
|
||||||
|
|
||||||
c_stream.zalloc = zalloc;
|
|
||||||
c_stream.zfree = zfree;
|
|
||||||
c_stream.opaque = (void *)0;
|
|
||||||
|
|
||||||
err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
|
|
||||||
CHECK_ERR(err, "deflateInit");
|
|
||||||
|
|
||||||
err = deflateSetDictionary(&c_stream,
|
|
||||||
(const unsigned char*)dictionary, (int)sizeof(dictionary));
|
|
||||||
CHECK_ERR(err, "deflateSetDictionary");
|
|
||||||
|
|
||||||
dictId = c_stream.adler;
|
|
||||||
c_stream.next_out = compr;
|
|
||||||
c_stream.avail_out = (unsigned int)comprLen;
|
|
||||||
|
|
||||||
c_stream.next_in = (const unsigned char *)hello;
|
|
||||||
c_stream.avail_in = (unsigned int)strlen(hello)+1;
|
|
||||||
|
|
||||||
err = deflate(&c_stream, Z_FINISH);
|
|
||||||
if (err != Z_STREAM_END) {
|
|
||||||
fprintf(stderr, "deflate should report Z_STREAM_END\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
err = deflateEnd(&c_stream);
|
|
||||||
CHECK_ERR(err, "deflateEnd");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Test inflate() with a preset dictionary
|
|
||||||
*/
|
|
||||||
void test_dict_inflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
z_stream d_stream; /* decompression stream */
|
|
||||||
|
|
||||||
strcpy((char*)uncompr, "garbage");
|
|
||||||
|
|
||||||
d_stream.zalloc = zalloc;
|
|
||||||
d_stream.zfree = zfree;
|
|
||||||
d_stream.opaque = (void *)0;
|
|
||||||
|
|
||||||
d_stream.next_in = compr;
|
|
||||||
d_stream.avail_in = (unsigned int)comprLen;
|
|
||||||
|
|
||||||
err = inflateInit(&d_stream);
|
|
||||||
CHECK_ERR(err, "inflateInit");
|
|
||||||
|
|
||||||
d_stream.next_out = uncompr;
|
|
||||||
d_stream.avail_out = (unsigned int)uncomprLen;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
err = inflate(&d_stream, Z_NO_FLUSH);
|
|
||||||
if (err == Z_STREAM_END) break;
|
|
||||||
if (err == Z_NEED_DICT) {
|
|
||||||
if (d_stream.adler != dictId) {
|
|
||||||
fprintf(stderr, "unexpected dictionary");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
err = inflateSetDictionary(&d_stream, (const unsigned char*)dictionary,
|
|
||||||
(int)sizeof(dictionary));
|
|
||||||
}
|
|
||||||
CHECK_ERR(err, "inflate with dict");
|
|
||||||
}
|
|
||||||
|
|
||||||
err = inflateEnd(&d_stream);
|
|
||||||
CHECK_ERR(err, "inflateEnd");
|
|
||||||
|
|
||||||
if (strcmp((char*)uncompr, hello)) {
|
|
||||||
fprintf(stderr, "bad inflate with dict\n");
|
|
||||||
exit(1);
|
|
||||||
} else {
|
|
||||||
printf("inflate with dictionary: %s\n", (char *)uncompr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Usage: example [output.gz [input.gz]]
|
|
||||||
*/
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
unsigned char *compr, *uncompr;
|
|
||||||
size_t comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
|
|
||||||
size_t uncomprLen = comprLen;
|
|
||||||
static const char* myVersion = ZLIB_VERSION;
|
|
||||||
|
|
||||||
if (zlibVersion()[0] != myVersion[0]) {
|
|
||||||
fprintf(stderr, "incompatible zlib version\n");
|
|
||||||
exit(1);
|
|
||||||
|
|
||||||
} else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {
|
|
||||||
fprintf(stderr, "warning: different zlib version\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n",
|
|
||||||
ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags());
|
|
||||||
|
|
||||||
compr = (unsigned char*)calloc((unsigned int)comprLen, 1);
|
|
||||||
uncompr = (unsigned char*)calloc((unsigned int)uncomprLen, 1);
|
|
||||||
/* compr and uncompr are cleared to avoid reading uninitialized
|
|
||||||
* data and to ensure that uncompr compresses well.
|
|
||||||
*/
|
|
||||||
if (compr == Z_NULL || uncompr == Z_NULL) {
|
|
||||||
printf("out of memory\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
test_compress(compr, comprLen, uncompr, uncomprLen);
|
|
||||||
|
|
||||||
#ifdef WITH_GZFILEOP
|
|
||||||
test_gzio((argc > 1 ? argv[1] : TESTFILE),
|
|
||||||
uncompr, uncomprLen);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
test_deflate(compr, comprLen);
|
|
||||||
test_inflate(compr, comprLen, uncompr, uncomprLen);
|
|
||||||
|
|
||||||
test_large_deflate(compr, comprLen, uncompr, uncomprLen);
|
|
||||||
test_large_inflate(compr, comprLen, uncompr, uncomprLen);
|
|
||||||
|
|
||||||
test_flush(compr, &comprLen);
|
|
||||||
test_sync(compr, comprLen, uncompr, uncomprLen);
|
|
||||||
comprLen = uncomprLen;
|
|
||||||
|
|
||||||
test_dict_deflate(compr, comprLen);
|
|
||||||
test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
|
|
||||||
|
|
||||||
free(compr);
|
|
||||||
free(uncompr);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,668 +0,0 @@
|
|||||||
/* infcover.c -- test zlib's inflate routines with full code coverage
|
|
||||||
* Copyright (C) 2011 Mark Adler
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* to use, do: ./configure --cover && make cover */
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include "zlib.h"
|
|
||||||
|
|
||||||
/* get definition of internal structure so we can mess with it (see pull()),
|
|
||||||
and so we can call inflate_trees() (see cover5()) */
|
|
||||||
#define ZLIB_INTERNAL
|
|
||||||
#include "inftrees.h"
|
|
||||||
#include "inflate.h"
|
|
||||||
|
|
||||||
/* -- memory tracking routines -- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
These memory tracking routines are provided to zlib and track all of zlib's
|
|
||||||
allocations and deallocations, check for LIFO operations, keep a current
|
|
||||||
and high water mark of total bytes requested, optionally set a limit on the
|
|
||||||
total memory that can be allocated, and when done check for memory leaks.
|
|
||||||
|
|
||||||
They are used as follows:
|
|
||||||
|
|
||||||
z_stream strm;
|
|
||||||
mem_setup(&strm) initializes the memory tracking and sets the
|
|
||||||
zalloc, zfree, and opaque members of strm to use
|
|
||||||
memory tracking for all zlib operations on strm
|
|
||||||
mem_limit(&strm, limit) sets a limit on the total bytes requested -- a
|
|
||||||
request that exceeds this limit will result in an
|
|
||||||
allocation failure (returns NULL) -- setting the
|
|
||||||
limit to zero means no limit, which is the default
|
|
||||||
after mem_setup()
|
|
||||||
mem_used(&strm, "msg") prints to stderr "msg" and the total bytes used
|
|
||||||
mem_high(&strm, "msg") prints to stderr "msg" and the high water mark
|
|
||||||
mem_done(&strm, "msg") ends memory tracking, releases all allocations
|
|
||||||
for the tracking as well as leaked zlib blocks, if
|
|
||||||
any. If there was anything unusual, such as leaked
|
|
||||||
blocks, non-FIFO frees, or frees of addresses not
|
|
||||||
allocated, then "msg" and information about the
|
|
||||||
problem is printed to stderr. If everything is
|
|
||||||
normal, nothing is printed. mem_done resets the
|
|
||||||
strm members to Z_NULL to use the default memory
|
|
||||||
allocation routines on the next zlib initialization
|
|
||||||
using strm.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* these items are strung together in a linked list, one for each allocation */
|
|
||||||
struct mem_item {
|
|
||||||
void *ptr; /* pointer to allocated memory */
|
|
||||||
size_t size; /* requested size of allocation */
|
|
||||||
struct mem_item *next; /* pointer to next item in list, or NULL */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* this structure is at the root of the linked list, and tracks statistics */
|
|
||||||
struct mem_zone {
|
|
||||||
struct mem_item *first; /* pointer to first item in list, or NULL */
|
|
||||||
size_t total, highwater; /* total allocations, and largest total */
|
|
||||||
size_t limit; /* memory allocation limit, or 0 if no limit */
|
|
||||||
int notlifo, rogue; /* counts of non-LIFO frees and rogue frees */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* memory allocation routine to pass to zlib */
|
|
||||||
static void *mem_alloc(void *mem, unsigned count, unsigned size)
|
|
||||||
{
|
|
||||||
void *ptr;
|
|
||||||
struct mem_item *item;
|
|
||||||
struct mem_zone *zone = mem;
|
|
||||||
size_t len = count * (size_t)size;
|
|
||||||
|
|
||||||
/* induced allocation failure */
|
|
||||||
if (zone == NULL || (zone->limit && zone->total + len > zone->limit))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* perform allocation using the standard library, fill memory with a
|
|
||||||
non-zero value to make sure that the code isn't depending on zeros */
|
|
||||||
ptr = malloc(len);
|
|
||||||
if (ptr == NULL)
|
|
||||||
return NULL;
|
|
||||||
memset(ptr, 0xa5, len);
|
|
||||||
|
|
||||||
/* create a new item for the list */
|
|
||||||
item = malloc(sizeof(struct mem_item));
|
|
||||||
if (item == NULL) {
|
|
||||||
free(ptr);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
item->ptr = ptr;
|
|
||||||
item->size = len;
|
|
||||||
|
|
||||||
/* insert item at the beginning of the list */
|
|
||||||
item->next = zone->first;
|
|
||||||
zone->first = item;
|
|
||||||
|
|
||||||
/* update the statistics */
|
|
||||||
zone->total += item->size;
|
|
||||||
if (zone->total > zone->highwater)
|
|
||||||
zone->highwater = zone->total;
|
|
||||||
|
|
||||||
/* return the allocated memory */
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* memory free routine to pass to zlib */
|
|
||||||
static void mem_free(void *mem, void *ptr)
|
|
||||||
{
|
|
||||||
struct mem_item *item, *next;
|
|
||||||
struct mem_zone *zone = mem;
|
|
||||||
|
|
||||||
/* if no zone, just do a free */
|
|
||||||
if (zone == NULL) {
|
|
||||||
free(ptr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* point next to the item that matches ptr, or NULL if not found -- remove
|
|
||||||
the item from the linked list if found */
|
|
||||||
next = zone->first;
|
|
||||||
if (next) {
|
|
||||||
if (next->ptr == ptr)
|
|
||||||
zone->first = next->next; /* first one is it, remove from list */
|
|
||||||
else {
|
|
||||||
do { /* search the linked list */
|
|
||||||
item = next;
|
|
||||||
next = item->next;
|
|
||||||
} while (next != NULL && next->ptr != ptr);
|
|
||||||
if (next) { /* if found, remove from linked list */
|
|
||||||
item->next = next->next;
|
|
||||||
zone->notlifo++; /* not a LIFO free */
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if found, update the statistics and free the item */
|
|
||||||
if (next) {
|
|
||||||
zone->total -= next->size;
|
|
||||||
free(next);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if not found, update the rogue count */
|
|
||||||
else
|
|
||||||
zone->rogue++;
|
|
||||||
|
|
||||||
/* in any case, do the requested free with the standard library function */
|
|
||||||
free(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set up a controlled memory allocation space for monitoring, set the stream
|
|
||||||
parameters to the controlled routines, with opaque pointing to the space */
|
|
||||||
static void mem_setup(z_stream *strm)
|
|
||||||
{
|
|
||||||
struct mem_zone *zone;
|
|
||||||
|
|
||||||
zone = malloc(sizeof(struct mem_zone));
|
|
||||||
assert(zone != NULL);
|
|
||||||
zone->first = NULL;
|
|
||||||
zone->total = 0;
|
|
||||||
zone->highwater = 0;
|
|
||||||
zone->limit = 0;
|
|
||||||
zone->notlifo = 0;
|
|
||||||
zone->rogue = 0;
|
|
||||||
strm->opaque = zone;
|
|
||||||
strm->zalloc = mem_alloc;
|
|
||||||
strm->zfree = mem_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set a limit on the total memory allocation, or 0 to remove the limit */
|
|
||||||
static void mem_limit(z_stream *strm, size_t limit)
|
|
||||||
{
|
|
||||||
struct mem_zone *zone = strm->opaque;
|
|
||||||
|
|
||||||
zone->limit = limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* show the current total requested allocations in bytes */
|
|
||||||
static void mem_used(z_stream *strm, char *prefix)
|
|
||||||
{
|
|
||||||
struct mem_zone *zone = strm->opaque;
|
|
||||||
|
|
||||||
fprintf(stderr, "%s: %zu allocated\n", prefix, zone->total);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* show the high water allocation in bytes */
|
|
||||||
static void mem_high(z_stream *strm, char *prefix)
|
|
||||||
{
|
|
||||||
struct mem_zone *zone = strm->opaque;
|
|
||||||
|
|
||||||
fprintf(stderr, "%s: %zu high water mark\n", prefix, zone->highwater);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* release the memory allocation zone -- if there are any surprises, notify */
|
|
||||||
static void mem_done(z_stream *strm, char *prefix)
|
|
||||||
{
|
|
||||||
int count = 0;
|
|
||||||
struct mem_item *item, *next;
|
|
||||||
struct mem_zone *zone = strm->opaque;
|
|
||||||
|
|
||||||
/* show high water mark */
|
|
||||||
mem_high(strm, prefix);
|
|
||||||
|
|
||||||
/* free leftover allocations and item structures, if any */
|
|
||||||
item = zone->first;
|
|
||||||
while (item != NULL) {
|
|
||||||
free(item->ptr);
|
|
||||||
next = item->next;
|
|
||||||
free(item);
|
|
||||||
item = next;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* issue alerts about anything unexpected */
|
|
||||||
if (count || zone->total)
|
|
||||||
fprintf(stderr, "** %s: %zu bytes in %d blocks not freed\n",
|
|
||||||
prefix, zone->total, count);
|
|
||||||
if (zone->notlifo)
|
|
||||||
fprintf(stderr, "** %s: %d frees not LIFO\n", prefix, zone->notlifo);
|
|
||||||
if (zone->rogue)
|
|
||||||
fprintf(stderr, "** %s: %d frees not recognized\n",
|
|
||||||
prefix, zone->rogue);
|
|
||||||
|
|
||||||
/* free the zone and delete from the stream */
|
|
||||||
free(zone);
|
|
||||||
strm->opaque = Z_NULL;
|
|
||||||
strm->zalloc = Z_NULL;
|
|
||||||
strm->zfree = Z_NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- inflate test routines -- */
|
|
||||||
|
|
||||||
/* Decode a hexadecimal string, set *len to length, in[] to the bytes. This
|
|
||||||
decodes liberally, in that hex digits can be adjacent, in which case two in
|
|
||||||
a row writes a byte. Or they can be delimited by any non-hex character,
|
|
||||||
where the delimiters are ignored except when a single hex digit is followed
|
|
||||||
by a delimiter, where that single digit writes a byte. The returned data is
|
|
||||||
allocated and must eventually be freed. NULL is returned if out of memory.
|
|
||||||
If the length is not needed, then len can be NULL. */
|
|
||||||
static unsigned char *h2b(const char *hex, unsigned *len)
|
|
||||||
{
|
|
||||||
unsigned char *in, *re;
|
|
||||||
unsigned next, val;
|
|
||||||
|
|
||||||
in = malloc((strlen(hex) + 1) >> 1);
|
|
||||||
if (in == NULL)
|
|
||||||
return NULL;
|
|
||||||
next = 0;
|
|
||||||
val = 1;
|
|
||||||
do {
|
|
||||||
if (*hex >= '0' && *hex <= '9')
|
|
||||||
val = (val << 4) + *hex - '0';
|
|
||||||
else if (*hex >= 'A' && *hex <= 'F')
|
|
||||||
val = (val << 4) + *hex - 'A' + 10;
|
|
||||||
else if (*hex >= 'a' && *hex <= 'f')
|
|
||||||
val = (val << 4) + *hex - 'a' + 10;
|
|
||||||
else if (val != 1 && val < 32) /* one digit followed by delimiter */
|
|
||||||
val += 240; /* make it look like two digits */
|
|
||||||
if (val > 255) { /* have two digits */
|
|
||||||
in[next++] = val & 0xff; /* save the decoded byte */
|
|
||||||
val = 1; /* start over */
|
|
||||||
}
|
|
||||||
} while (*hex++); /* go through the loop with the terminating null */
|
|
||||||
if (len != NULL)
|
|
||||||
*len = next;
|
|
||||||
re = realloc(in, next);
|
|
||||||
return re == NULL ? in : re;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* generic inflate() run, where hex is the hexadecimal input data, what is the
|
|
||||||
text to include in an error message, step is how much input data to feed
|
|
||||||
inflate() on each call, or zero to feed it all, win is the window bits
|
|
||||||
parameter to inflateInit2(), len is the size of the output buffer, and err
|
|
||||||
is the error code expected from the first inflate() call (the second
|
|
||||||
inflate() call is expected to return Z_STREAM_END). If win is 47, then
|
|
||||||
header information is collected with inflateGetHeader(). If a zlib stream
|
|
||||||
is looking for a dictionary, then an empty dictionary is provided.
|
|
||||||
inflate() is run until all of the input data is consumed. */
|
|
||||||
static void inf(char *hex, char *what, unsigned step, int win, unsigned len, int err)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
unsigned have;
|
|
||||||
unsigned char *in, *out;
|
|
||||||
z_stream strm, copy;
|
|
||||||
gz_header head;
|
|
||||||
|
|
||||||
mem_setup(&strm);
|
|
||||||
strm.avail_in = 0;
|
|
||||||
strm.next_in = Z_NULL;
|
|
||||||
ret = inflateInit2(&strm, win);
|
|
||||||
if (ret != Z_OK) {
|
|
||||||
mem_done(&strm, what);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
out = malloc(len); assert(out != NULL);
|
|
||||||
if (win == 47) {
|
|
||||||
head.extra = out;
|
|
||||||
head.extra_max = len;
|
|
||||||
head.name = out;
|
|
||||||
head.name_max = len;
|
|
||||||
head.comment = out;
|
|
||||||
head.comm_max = len;
|
|
||||||
ret = inflateGetHeader(&strm, &head); assert(ret == Z_OK);
|
|
||||||
}
|
|
||||||
in = h2b(hex, &have); assert(in != NULL);
|
|
||||||
if (step == 0 || step > have)
|
|
||||||
step = have;
|
|
||||||
strm.avail_in = step;
|
|
||||||
have -= step;
|
|
||||||
strm.next_in = in;
|
|
||||||
do {
|
|
||||||
strm.avail_out = len;
|
|
||||||
strm.next_out = out;
|
|
||||||
ret = inflate(&strm, Z_NO_FLUSH); assert(err == 9 || ret == err);
|
|
||||||
if (ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_NEED_DICT)
|
|
||||||
break;
|
|
||||||
if (ret == Z_NEED_DICT) {
|
|
||||||
ret = inflateSetDictionary(&strm, in, 1);
|
|
||||||
assert(ret == Z_DATA_ERROR);
|
|
||||||
mem_limit(&strm, 1);
|
|
||||||
ret = inflateSetDictionary(&strm, out, 0);
|
|
||||||
assert(ret == Z_MEM_ERROR);
|
|
||||||
mem_limit(&strm, 0);
|
|
||||||
((struct inflate_state *)strm.state)->mode = DICT;
|
|
||||||
ret = inflateSetDictionary(&strm, out, 0);
|
|
||||||
assert(ret == Z_OK);
|
|
||||||
ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_BUF_ERROR);
|
|
||||||
}
|
|
||||||
ret = inflateCopy(©, &strm); assert(ret == Z_OK);
|
|
||||||
ret = inflateEnd(©); assert(ret == Z_OK);
|
|
||||||
err = 9; /* don't care next time around */
|
|
||||||
have += strm.avail_in;
|
|
||||||
strm.avail_in = step > have ? have : step;
|
|
||||||
have -= strm.avail_in;
|
|
||||||
} while (strm.avail_in);
|
|
||||||
free(in);
|
|
||||||
free(out);
|
|
||||||
ret = inflateReset2(&strm, -8); assert(ret == Z_OK);
|
|
||||||
ret = inflateEnd(&strm); assert(ret == Z_OK);
|
|
||||||
mem_done(&strm, what);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* cover all of the lines in inflate.c up to inflate() */
|
|
||||||
static void cover_support(void)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
z_stream strm;
|
|
||||||
|
|
||||||
mem_setup(&strm);
|
|
||||||
strm.avail_in = 0;
|
|
||||||
strm.next_in = Z_NULL;
|
|
||||||
ret = inflateInit(&strm); assert(ret == Z_OK);
|
|
||||||
mem_used(&strm, "inflate init");
|
|
||||||
ret = inflatePrime(&strm, 5, 31); assert(ret == Z_OK);
|
|
||||||
ret = inflatePrime(&strm, -1, 0); assert(ret == Z_OK);
|
|
||||||
ret = inflateSetDictionary(&strm, Z_NULL, 0);
|
|
||||||
assert(ret == Z_STREAM_ERROR);
|
|
||||||
ret = inflateEnd(&strm); assert(ret == Z_OK);
|
|
||||||
mem_done(&strm, "prime");
|
|
||||||
|
|
||||||
inf("63 0", "force window allocation", 0, -15, 1, Z_OK);
|
|
||||||
inf("63 18 5", "force window replacement", 0, -8, 259, Z_OK);
|
|
||||||
inf("63 18 68 30 d0 0 0", "force split window update", 4, -8, 259, Z_OK);
|
|
||||||
inf("3 0", "use fixed blocks", 0, -15, 1, Z_STREAM_END);
|
|
||||||
inf("", "bad window size", 0, 1, 0, Z_STREAM_ERROR);
|
|
||||||
|
|
||||||
mem_setup(&strm);
|
|
||||||
strm.avail_in = 0;
|
|
||||||
strm.next_in = Z_NULL;
|
|
||||||
ret = inflateInit_(&strm, ZLIB_VERSION + 1, (int)sizeof(z_stream));
|
|
||||||
assert(ret == Z_VERSION_ERROR);
|
|
||||||
mem_done(&strm, "wrong version");
|
|
||||||
|
|
||||||
strm.avail_in = 0;
|
|
||||||
strm.next_in = Z_NULL;
|
|
||||||
ret = inflateInit(&strm); assert(ret == Z_OK);
|
|
||||||
ret = inflateEnd(&strm); assert(ret == Z_OK);
|
|
||||||
fputs("inflate built-in memory routines\n", stderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* cover all inflate() header and trailer cases and code after inflate() */
|
|
||||||
static void cover_wrap(void)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
z_stream strm, copy;
|
|
||||||
unsigned char dict[257];
|
|
||||||
|
|
||||||
ret = inflate(Z_NULL, 0); assert(ret == Z_STREAM_ERROR);
|
|
||||||
ret = inflateEnd(Z_NULL); assert(ret == Z_STREAM_ERROR);
|
|
||||||
ret = inflateCopy(Z_NULL, Z_NULL); assert(ret == Z_STREAM_ERROR);
|
|
||||||
fputs("inflate bad parameters\n", stderr);
|
|
||||||
|
|
||||||
inf("1f 8b 0 0", "bad gzip method", 0, 31, 0, Z_DATA_ERROR);
|
|
||||||
inf("1f 8b 8 80", "bad gzip flags", 0, 31, 0, Z_DATA_ERROR);
|
|
||||||
inf("77 85", "bad zlib method", 0, 15, 0, Z_DATA_ERROR);
|
|
||||||
inf("8 99", "set window size from header", 0, 0, 0, Z_OK);
|
|
||||||
inf("78 9c", "bad zlib window size", 0, 8, 0, Z_DATA_ERROR);
|
|
||||||
inf("78 9c 63 0 0 0 1 0 1", "check adler32", 0, 15, 1, Z_STREAM_END);
|
|
||||||
inf("1f 8b 8 1e 0 0 0 0 0 0 1 0 0 0 0 0 0", "bad header crc", 0, 47, 1,
|
|
||||||
Z_DATA_ERROR);
|
|
||||||
inf("1f 8b 8 2 0 0 0 0 0 0 1d 26 3 0 0 0 0 0 0 0 0 0", "check gzip length",
|
|
||||||
0, 47, 0, Z_STREAM_END);
|
|
||||||
inf("78 90", "bad zlib header check", 0, 47, 0, Z_DATA_ERROR);
|
|
||||||
inf("8 b8 0 0 0 1", "need dictionary", 0, 8, 0, Z_NEED_DICT);
|
|
||||||
inf("78 9c 63 0", "compute adler32", 0, 15, 1, Z_OK);
|
|
||||||
|
|
||||||
mem_setup(&strm);
|
|
||||||
strm.avail_in = 0;
|
|
||||||
strm.next_in = Z_NULL;
|
|
||||||
ret = inflateInit2(&strm, -8);
|
|
||||||
strm.avail_in = 2;
|
|
||||||
strm.next_in = (void *)"\x63";
|
|
||||||
strm.avail_out = 1;
|
|
||||||
strm.next_out = (void *)&ret;
|
|
||||||
mem_limit(&strm, 1);
|
|
||||||
ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR);
|
|
||||||
ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR);
|
|
||||||
mem_limit(&strm, 0);
|
|
||||||
memset(dict, 0, 257);
|
|
||||||
ret = inflateSetDictionary(&strm, dict, 257);
|
|
||||||
assert(ret == Z_OK);
|
|
||||||
mem_limit(&strm, (sizeof(struct inflate_state) << 1) + 256);
|
|
||||||
ret = inflatePrime(&strm, 16, 0); assert(ret == Z_OK);
|
|
||||||
strm.avail_in = 2;
|
|
||||||
strm.next_in = (void *)"\x80";
|
|
||||||
ret = inflateSync(&strm); assert(ret == Z_DATA_ERROR);
|
|
||||||
ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_STREAM_ERROR);
|
|
||||||
strm.avail_in = 4;
|
|
||||||
strm.next_in = (void *)"\0\0\xff\xff";
|
|
||||||
ret = inflateSync(&strm); assert(ret == Z_OK);
|
|
||||||
(void)inflateSyncPoint(&strm);
|
|
||||||
ret = inflateCopy(©, &strm); assert(ret == Z_MEM_ERROR);
|
|
||||||
mem_limit(&strm, 0);
|
|
||||||
ret = inflateUndermine(&strm, 1); assert(ret == Z_DATA_ERROR);
|
|
||||||
(void)inflateMark(&strm);
|
|
||||||
ret = inflateEnd(&strm); assert(ret == Z_OK);
|
|
||||||
mem_done(&strm, "miscellaneous, force memory errors");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* input and output functions for inflateBack() */
|
|
||||||
static unsigned pull(void *desc, const unsigned char **buf)
|
|
||||||
{
|
|
||||||
static unsigned int next = 0;
|
|
||||||
static unsigned char dat[] = {0x63, 0, 2, 0};
|
|
||||||
struct inflate_state *state;
|
|
||||||
|
|
||||||
if (desc == Z_NULL) {
|
|
||||||
next = 0;
|
|
||||||
return 0; /* no input (already provided at next_in) */
|
|
||||||
}
|
|
||||||
state = (void *)((z_stream *)desc)->state;
|
|
||||||
if (state != Z_NULL)
|
|
||||||
state->mode = SYNC; /* force an otherwise impossible situation */
|
|
||||||
return next < sizeof(dat) ? (*buf = dat + next++, 1) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int push(void *desc, unsigned char *buf, unsigned len)
|
|
||||||
{
|
|
||||||
buf += len;
|
|
||||||
return desc != Z_NULL; /* force error if desc not null */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* cover inflateBack() up to common deflate data cases and after those */
|
|
||||||
static void cover_back(void)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
z_stream strm;
|
|
||||||
unsigned char win[32768];
|
|
||||||
|
|
||||||
ret = inflateBackInit_(Z_NULL, 0, win, 0, 0);
|
|
||||||
assert(ret == Z_VERSION_ERROR);
|
|
||||||
ret = inflateBackInit(Z_NULL, 0, win); assert(ret == Z_STREAM_ERROR);
|
|
||||||
ret = inflateBack(Z_NULL, Z_NULL, Z_NULL, Z_NULL, Z_NULL);
|
|
||||||
assert(ret == Z_STREAM_ERROR);
|
|
||||||
ret = inflateBackEnd(Z_NULL); assert(ret == Z_STREAM_ERROR);
|
|
||||||
fputs("inflateBack bad parameters\n", stderr);
|
|
||||||
|
|
||||||
mem_setup(&strm);
|
|
||||||
ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK);
|
|
||||||
strm.avail_in = 2;
|
|
||||||
strm.next_in = (void *)"\x03";
|
|
||||||
ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL);
|
|
||||||
assert(ret == Z_STREAM_END);
|
|
||||||
/* force output error */
|
|
||||||
strm.avail_in = 3;
|
|
||||||
strm.next_in = (void *)"\x63\x00";
|
|
||||||
ret = inflateBack(&strm, pull, Z_NULL, push, &strm);
|
|
||||||
assert(ret == Z_BUF_ERROR);
|
|
||||||
/* force mode error by mucking with state */
|
|
||||||
ret = inflateBack(&strm, pull, &strm, push, Z_NULL);
|
|
||||||
assert(ret == Z_STREAM_ERROR);
|
|
||||||
ret = inflateBackEnd(&strm); assert(ret == Z_OK);
|
|
||||||
mem_done(&strm, "inflateBack bad state");
|
|
||||||
|
|
||||||
ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK);
|
|
||||||
ret = inflateBackEnd(&strm); assert(ret == Z_OK);
|
|
||||||
fputs("inflateBack built-in memory routines\n", stderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* do a raw inflate of data in hexadecimal with both inflate and inflateBack */
|
|
||||||
static int try(char *hex, char *id, int err)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
unsigned len, size;
|
|
||||||
unsigned char *in, *out, *win;
|
|
||||||
char *prefix;
|
|
||||||
z_stream strm;
|
|
||||||
|
|
||||||
/* convert to hex */
|
|
||||||
in = h2b(hex, &len);
|
|
||||||
assert(in != NULL);
|
|
||||||
|
|
||||||
/* allocate work areas */
|
|
||||||
size = len << 3;
|
|
||||||
out = malloc(size);
|
|
||||||
assert(out != NULL);
|
|
||||||
win = malloc(32768);
|
|
||||||
assert(win != NULL);
|
|
||||||
prefix = malloc(strlen(id) + 6);
|
|
||||||
assert(prefix != NULL);
|
|
||||||
|
|
||||||
/* first with inflate */
|
|
||||||
strcpy(prefix, id);
|
|
||||||
strcat(prefix, "-late");
|
|
||||||
mem_setup(&strm);
|
|
||||||
strm.avail_in = 0;
|
|
||||||
strm.next_in = Z_NULL;
|
|
||||||
ret = inflateInit2(&strm, err < 0 ? 47 : -15);
|
|
||||||
assert(ret == Z_OK);
|
|
||||||
strm.avail_in = len;
|
|
||||||
strm.next_in = in;
|
|
||||||
do {
|
|
||||||
strm.avail_out = size;
|
|
||||||
strm.next_out = out;
|
|
||||||
ret = inflate(&strm, Z_TREES);
|
|
||||||
assert(ret != Z_STREAM_ERROR && ret != Z_MEM_ERROR);
|
|
||||||
if (ret == Z_DATA_ERROR || ret == Z_NEED_DICT)
|
|
||||||
break;
|
|
||||||
} while (strm.avail_in || strm.avail_out == 0);
|
|
||||||
if (err) {
|
|
||||||
assert(ret == Z_DATA_ERROR);
|
|
||||||
assert(strcmp(id, strm.msg) == 0);
|
|
||||||
}
|
|
||||||
inflateEnd(&strm);
|
|
||||||
mem_done(&strm, prefix);
|
|
||||||
|
|
||||||
/* then with inflateBack */
|
|
||||||
if (err >= 0) {
|
|
||||||
strcpy(prefix, id);
|
|
||||||
strcat(prefix, "-back");
|
|
||||||
mem_setup(&strm);
|
|
||||||
ret = inflateBackInit(&strm, 15, win);
|
|
||||||
assert(ret == Z_OK);
|
|
||||||
strm.avail_in = len;
|
|
||||||
strm.next_in = in;
|
|
||||||
ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL);
|
|
||||||
assert(ret != Z_STREAM_ERROR);
|
|
||||||
if (err) {
|
|
||||||
assert(ret == Z_DATA_ERROR);
|
|
||||||
assert(strcmp(id, strm.msg) == 0);
|
|
||||||
}
|
|
||||||
inflateBackEnd(&strm);
|
|
||||||
mem_done(&strm, prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* clean up */
|
|
||||||
free(prefix);
|
|
||||||
free(win);
|
|
||||||
free(out);
|
|
||||||
free(in);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* cover deflate data cases in both inflate() and inflateBack() */
|
|
||||||
static void cover_inflate(void)
|
|
||||||
{
|
|
||||||
try("0 0 0 0 0", "invalid stored block lengths", 1);
|
|
||||||
try("3 0", "fixed", 0);
|
|
||||||
try("6", "invalid block type", 1);
|
|
||||||
try("1 1 0 fe ff 0", "stored", 0);
|
|
||||||
try("fc 0 0", "too many length or distance symbols", 1);
|
|
||||||
try("4 0 fe ff", "invalid code lengths set", 1);
|
|
||||||
try("4 0 24 49 0", "invalid bit length repeat", 1);
|
|
||||||
try("4 0 24 e9 ff ff", "invalid bit length repeat", 1);
|
|
||||||
try("4 0 24 e9 ff 6d", "invalid code -- missing end-of-block", 1);
|
|
||||||
try("4 80 49 92 24 49 92 24 71 ff ff 93 11 0",
|
|
||||||
"invalid literal/lengths set", 1);
|
|
||||||
try("4 80 49 92 24 49 92 24 f b4 ff ff c3 84", "invalid distances set", 1);
|
|
||||||
try("4 c0 81 8 0 0 0 0 20 7f eb b 0 0", "invalid literal/length code", 1);
|
|
||||||
try("2 7e ff ff", "invalid distance code", 1);
|
|
||||||
try("c c0 81 0 0 0 0 0 90 ff 6b 4 0", "invalid distance too far back", 1);
|
|
||||||
|
|
||||||
/* also trailer mismatch just in inflate() */
|
|
||||||
try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 1", "incorrect data check", -1);
|
|
||||||
try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 1",
|
|
||||||
"incorrect length check", -1);
|
|
||||||
try("5 c0 21 d 0 0 0 80 b0 fe 6d 2f 91 6c", "pull 17", 0);
|
|
||||||
try("5 e0 81 91 24 cb b2 2c 49 e2 f 2e 8b 9a 47 56 9f fb fe ec d2 ff 1f",
|
|
||||||
"long code", 0);
|
|
||||||
try("ed c0 1 1 0 0 0 40 20 ff 57 1b 42 2c 4f", "length extra", 0);
|
|
||||||
try("ed cf c1 b1 2c 47 10 c4 30 fa 6f 35 1d 1 82 59 3d fb be 2e 2a fc f c",
|
|
||||||
"long distance and extra", 0);
|
|
||||||
try("ed c0 81 0 0 0 0 80 a0 fd a9 17 a9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "
|
|
||||||
"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6", "window end", 0);
|
|
||||||
inf("2 8 20 80 0 3 0", "inflate_fast TYPE return", 0, -15, 258,
|
|
||||||
Z_STREAM_END);
|
|
||||||
inf("63 18 5 40 c 0", "window wrap", 3, -8, 300, Z_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* cover remaining lines in inftrees.c */
|
|
||||||
static void cover_trees(void)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
unsigned bits;
|
|
||||||
uint16_t lens[16], work[16];
|
|
||||||
code *next, table[ENOUGH_DISTS];
|
|
||||||
|
|
||||||
/* we need to call inflate_table() directly in order to manifest not-
|
|
||||||
enough errors, since zlib insures that enough is always enough */
|
|
||||||
for (bits = 0; bits < 15; bits++)
|
|
||||||
lens[bits] = (uint16_t)(bits + 1);
|
|
||||||
lens[15] = 15;
|
|
||||||
next = table;
|
|
||||||
bits = 15;
|
|
||||||
ret = inflate_table(DISTS, lens, 16, &next, &bits, work);
|
|
||||||
assert(ret == 1);
|
|
||||||
next = table;
|
|
||||||
bits = 1;
|
|
||||||
ret = inflate_table(DISTS, lens, 16, &next, &bits, work);
|
|
||||||
assert(ret == 1);
|
|
||||||
fputs("inflate_table not enough errors\n", stderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* cover remaining inffast.c decoding and window copying */
|
|
||||||
static void cover_fast(void)
|
|
||||||
{
|
|
||||||
inf("e5 e0 81 ad 6d cb b2 2c c9 01 1e 59 63 ae 7d ee fb 4d fd b5 35 41 68"
|
|
||||||
" ff 7f 0f 0 0 0", "fast length extra bits", 0, -8, 258, Z_DATA_ERROR);
|
|
||||||
inf("25 fd 81 b5 6d 59 b6 6a 49 ea af 35 6 34 eb 8c b9 f6 b9 1e ef 67 49"
|
|
||||||
" 50 fe ff ff 3f 0 0", "fast distance extra bits", 0, -8, 258,
|
|
||||||
Z_DATA_ERROR);
|
|
||||||
inf("3 7e 0 0 0 0 0", "fast invalid distance code", 0, -8, 258,
|
|
||||||
Z_DATA_ERROR);
|
|
||||||
inf("1b 7 0 0 0 0 0", "fast invalid literal/length code", 0, -8, 258,
|
|
||||||
Z_DATA_ERROR);
|
|
||||||
inf("d c7 1 ae eb 38 c 4 41 a0 87 72 de df fb 1f b8 36 b1 38 5d ff ff 0",
|
|
||||||
"fast 2nd level codes and too far back", 0, -8, 258, Z_DATA_ERROR);
|
|
||||||
inf("63 18 5 8c 10 8 0 0 0 0", "very common case", 0, -8, 259, Z_OK);
|
|
||||||
inf("63 60 60 18 c9 0 8 18 18 18 26 c0 28 0 29 0 0 0",
|
|
||||||
"contiguous and wrap around window", 6, -8, 259, Z_OK);
|
|
||||||
inf("63 0 3 0 0 0 0 0", "copy direct from output", 0, -8, 259,
|
|
||||||
Z_STREAM_END);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s\n", zlibVersion());
|
|
||||||
cover_support();
|
|
||||||
cover_wrap();
|
|
||||||
cover_back();
|
|
||||||
cover_inflate();
|
|
||||||
cover_trees();
|
|
||||||
cover_fast();
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,530 +0,0 @@
|
|||||||
/* minigzip.c -- simulate gzip using the zlib compression library
|
|
||||||
* Copyright (C) 1995-2006, 2010, 2011 Jean-loup Gailly.
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* minigzip is a minimal implementation of the gzip utility. This is
|
|
||||||
* only an example of using zlib and isn't meant to replace the
|
|
||||||
* full-featured gzip. No attempt is made to deal with file systems
|
|
||||||
* limiting names to 14 or 8+3 characters, etc... Error checking is
|
|
||||||
* very limited. So use minigzip only for testing; use gzip for the
|
|
||||||
* real thing.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* @(#) $Id$ */
|
|
||||||
|
|
||||||
#include "zlib.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#ifdef USE_MMAP
|
|
||||||
# include <sys/types.h>
|
|
||||||
# include <sys/mman.h>
|
|
||||||
# include <sys/stat.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(WIN32) || defined(__CYGWIN__)
|
|
||||||
# include <fcntl.h>
|
|
||||||
# include <io.h>
|
|
||||||
# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
|
|
||||||
#else
|
|
||||||
# define SET_BINARY_MODE(file)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
|
||||||
# define snprintf _snprintf
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE)
|
|
||||||
#ifndef WIN32 /* unlink already in stdio.h for WIN32 */
|
|
||||||
extern int unlink (const char *);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef GZ_SUFFIX
|
|
||||||
# define GZ_SUFFIX ".gz"
|
|
||||||
#endif
|
|
||||||
#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
|
|
||||||
|
|
||||||
#define BUFLEN 16384 /* read buffer size */
|
|
||||||
#define BUFLENW (BUFLEN * 3) /* write buffer size */
|
|
||||||
#define MAX_NAME_LEN 1024
|
|
||||||
|
|
||||||
#ifndef WITH_GZFILEOP
|
|
||||||
/* without WITH_GZFILEOP, create simplified gz* functions using deflate and inflate */
|
|
||||||
|
|
||||||
#if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE)
|
|
||||||
# include <unistd.h> /* for unlink() */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void *myalloc (void *, unsigned, unsigned);
|
|
||||||
void myfree (void *, void *);
|
|
||||||
|
|
||||||
void *myalloc(void *q, unsigned n, unsigned m)
|
|
||||||
{
|
|
||||||
(void)q;
|
|
||||||
return calloc(n, m);
|
|
||||||
}
|
|
||||||
|
|
||||||
void myfree(void *q, void *p)
|
|
||||||
{
|
|
||||||
(void)q;
|
|
||||||
free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct gzFile_s {
|
|
||||||
FILE *file;
|
|
||||||
int write;
|
|
||||||
int err;
|
|
||||||
const char *msg;
|
|
||||||
z_stream strm;
|
|
||||||
unsigned char *buf;
|
|
||||||
} *gzFile;
|
|
||||||
|
|
||||||
gzFile gzopen (const char *, const char *);
|
|
||||||
gzFile gzdopen (int, const char *);
|
|
||||||
gzFile gz_open (const char *, int, const char *);
|
|
||||||
|
|
||||||
gzFile gzopen(const char *path, const char *mode)
|
|
||||||
{
|
|
||||||
return gz_open(path, -1, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
gzFile gzdopen(int fd, const char *mode)
|
|
||||||
{
|
|
||||||
return gz_open(NULL, fd, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
gzFile gz_open(const char *path, int fd, const char *mode)
|
|
||||||
{
|
|
||||||
gzFile gz;
|
|
||||||
int ret;
|
|
||||||
int level = Z_DEFAULT_COMPRESSION;
|
|
||||||
const char *plevel = mode;
|
|
||||||
|
|
||||||
gz = malloc(sizeof(struct gzFile_s));
|
|
||||||
if (gz == NULL)
|
|
||||||
return NULL;
|
|
||||||
gz->write = strchr(mode, 'w') != NULL;
|
|
||||||
gz->strm.zalloc = myalloc;
|
|
||||||
gz->strm.zfree = myfree;
|
|
||||||
gz->strm.opaque = Z_NULL;
|
|
||||||
gz->buf = malloc(gz->write ? BUFLENW : BUFLEN);
|
|
||||||
|
|
||||||
if (gz->buf == NULL) {
|
|
||||||
free(gz);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (*plevel) {
|
|
||||||
if (*plevel >= '0' && *plevel <= '9') {
|
|
||||||
level = *plevel - '0';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
plevel++;
|
|
||||||
}
|
|
||||||
if (gz->write)
|
|
||||||
ret = deflateInit2(&(gz->strm), level, 8, 15 + 16, 8, 0);
|
|
||||||
else {
|
|
||||||
gz->strm.next_in = 0;
|
|
||||||
gz->strm.avail_in = Z_NULL;
|
|
||||||
ret = inflateInit2(&(gz->strm), 15 + 16);
|
|
||||||
}
|
|
||||||
if (ret != Z_OK) {
|
|
||||||
free(gz);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
gz->file = path == NULL ? fdopen(fd, gz->write ? "wb" : "rb") :
|
|
||||||
fopen(path, gz->write ? "wb" : "rb");
|
|
||||||
if (gz->file == NULL) {
|
|
||||||
gz->write ? deflateEnd(&(gz->strm)) : inflateEnd(&(gz->strm));
|
|
||||||
free(gz);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
gz->err = 0;
|
|
||||||
gz->msg = "";
|
|
||||||
return gz;
|
|
||||||
}
|
|
||||||
|
|
||||||
int gzwrite (gzFile, const void *, unsigned);
|
|
||||||
|
|
||||||
int gzwrite(gzFile gz, const void *buf, unsigned len)
|
|
||||||
{
|
|
||||||
z_stream *strm;
|
|
||||||
|
|
||||||
if (gz == NULL || !gz->write)
|
|
||||||
return 0;
|
|
||||||
strm = &(gz->strm);
|
|
||||||
strm->next_in = (void *)buf;
|
|
||||||
strm->avail_in = len;
|
|
||||||
do {
|
|
||||||
strm->next_out = gz->buf;
|
|
||||||
strm->avail_out = BUFLENW;
|
|
||||||
(void)deflate(strm, Z_NO_FLUSH);
|
|
||||||
fwrite(gz->buf, 1, BUFLENW - strm->avail_out, gz->file);
|
|
||||||
} while (strm->avail_out == 0);
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
int gzread (gzFile, void *, unsigned);
|
|
||||||
|
|
||||||
int gzread(gzFile gz, void *buf, unsigned len)
|
|
||||||
{
|
|
||||||
z_stream *strm;
|
|
||||||
|
|
||||||
if (gz == NULL || gz->write || gz->err)
|
|
||||||
return 0;
|
|
||||||
strm = &(gz->strm);
|
|
||||||
strm->next_out = buf;
|
|
||||||
strm->avail_out = len;
|
|
||||||
do {
|
|
||||||
if (strm->avail_in == 0)
|
|
||||||
{
|
|
||||||
strm->next_in = gz->buf;
|
|
||||||
strm->avail_in = (uint32_t)fread(gz->buf, 1, BUFLEN, gz->file);
|
|
||||||
}
|
|
||||||
if (strm->avail_in > 0)
|
|
||||||
{
|
|
||||||
int ret = inflate(strm, Z_NO_FLUSH);
|
|
||||||
if (ret == Z_DATA_ERROR) {
|
|
||||||
gz->err = ret;
|
|
||||||
gz->msg = strm->msg;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (ret == Z_STREAM_END)
|
|
||||||
inflateReset(strm);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
} while (strm->avail_out);
|
|
||||||
return len - strm->avail_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
int gzclose (gzFile);
|
|
||||||
|
|
||||||
int gzclose(gzFile gz)
|
|
||||||
{
|
|
||||||
z_stream *strm;
|
|
||||||
|
|
||||||
if (gz == NULL)
|
|
||||||
return Z_STREAM_ERROR;
|
|
||||||
strm = &(gz->strm);
|
|
||||||
if (gz->write) {
|
|
||||||
strm->next_in = Z_NULL;
|
|
||||||
strm->avail_in = 0;
|
|
||||||
do {
|
|
||||||
strm->next_out = gz->buf;
|
|
||||||
strm->avail_out = BUFLENW;
|
|
||||||
(void)deflate(strm, Z_FINISH);
|
|
||||||
fwrite(gz->buf, 1, BUFLENW - strm->avail_out, gz->file);
|
|
||||||
} while (strm->avail_out == 0);
|
|
||||||
deflateEnd(strm);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
inflateEnd(strm);
|
|
||||||
free(gz->buf);
|
|
||||||
fclose(gz->file);
|
|
||||||
free(gz);
|
|
||||||
return Z_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *gzerror (gzFile, int *);
|
|
||||||
|
|
||||||
const char *gzerror(gzFile gz, int *err)
|
|
||||||
{
|
|
||||||
*err = gz->err;
|
|
||||||
return gz->msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
char *prog;
|
|
||||||
|
|
||||||
void error (const char *msg);
|
|
||||||
void gz_compress (FILE *in, gzFile out);
|
|
||||||
#ifdef USE_MMAP
|
|
||||||
int gz_compress_mmap (FILE *in, gzFile out);
|
|
||||||
#endif
|
|
||||||
void gz_uncompress (gzFile in, FILE *out);
|
|
||||||
void file_compress (char *file, char *mode);
|
|
||||||
void file_uncompress (char *file);
|
|
||||||
int main (int argc, char *argv[]);
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Display error message and exit
|
|
||||||
*/
|
|
||||||
void error(const char *msg)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s: %s\n", prog, msg);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Compress input to output then close both files.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void gz_compress(FILE *in, gzFile out)
|
|
||||||
{
|
|
||||||
char buf[BUFLEN];
|
|
||||||
int len;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
#ifdef USE_MMAP
|
|
||||||
/* Try first compressing with mmap. If mmap fails (minigzip used in a
|
|
||||||
* pipe), use the normal fread loop.
|
|
||||||
*/
|
|
||||||
if (gz_compress_mmap(in, out) == Z_OK) return;
|
|
||||||
#endif
|
|
||||||
for (;;) {
|
|
||||||
len = (int)fread(buf, 1, sizeof(buf), in);
|
|
||||||
if (ferror(in)) {
|
|
||||||
perror("fread");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (len == 0) break;
|
|
||||||
|
|
||||||
if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
|
|
||||||
}
|
|
||||||
fclose(in);
|
|
||||||
if (gzclose(out) != Z_OK) error("failed gzclose");
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */
|
|
||||||
|
|
||||||
/* Try compressing the input file at once using mmap. Return Z_OK if
|
|
||||||
* if success, Z_ERRNO otherwise.
|
|
||||||
*/
|
|
||||||
int gz_compress_mmap(FILE *in, gzFile out)
|
|
||||||
{
|
|
||||||
int len;
|
|
||||||
int err;
|
|
||||||
int ifd = fileno(in);
|
|
||||||
caddr_t buf; /* mmap'ed buffer for the entire input file */
|
|
||||||
off_t buf_len; /* length of the input file */
|
|
||||||
struct stat sb;
|
|
||||||
|
|
||||||
/* Determine the size of the file, needed for mmap: */
|
|
||||||
if (fstat(ifd, &sb) < 0) return Z_ERRNO;
|
|
||||||
buf_len = sb.st_size;
|
|
||||||
if (buf_len <= 0) return Z_ERRNO;
|
|
||||||
|
|
||||||
/* Now do the actual mmap: */
|
|
||||||
buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);
|
|
||||||
if (buf == (caddr_t)(-1)) return Z_ERRNO;
|
|
||||||
|
|
||||||
/* Compress the whole file at once: */
|
|
||||||
len = gzwrite(out, (char *)buf, (unsigned)buf_len);
|
|
||||||
|
|
||||||
if (len != (int)buf_len) error(gzerror(out, &err));
|
|
||||||
|
|
||||||
munmap(buf, buf_len);
|
|
||||||
fclose(in);
|
|
||||||
if (gzclose(out) != Z_OK) error("failed gzclose");
|
|
||||||
return Z_OK;
|
|
||||||
}
|
|
||||||
#endif /* USE_MMAP */
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Uncompress input to output then close both files.
|
|
||||||
*/
|
|
||||||
void gz_uncompress(gzFile in, FILE *out)
|
|
||||||
{
|
|
||||||
char buf[BUFLENW];
|
|
||||||
int len;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
len = gzread(in, buf, sizeof(buf));
|
|
||||||
if (len < 0) error (gzerror(in, &err));
|
|
||||||
if (len == 0) break;
|
|
||||||
|
|
||||||
if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
|
|
||||||
error("failed fwrite");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fclose(out)) error("failed fclose");
|
|
||||||
|
|
||||||
if (gzclose(in) != Z_OK) error("failed gzclose");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Compress the given file: create a corresponding .gz file and remove the
|
|
||||||
* original.
|
|
||||||
*/
|
|
||||||
void file_compress(char *file, char *mode)
|
|
||||||
{
|
|
||||||
char outfile[MAX_NAME_LEN];
|
|
||||||
FILE *in;
|
|
||||||
gzFile out;
|
|
||||||
|
|
||||||
if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) {
|
|
||||||
fprintf(stderr, "%s: filename too long\n", prog);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(outfile, sizeof(outfile), "%s%s", file, GZ_SUFFIX);
|
|
||||||
|
|
||||||
in = fopen(file, "rb");
|
|
||||||
if (in == NULL) {
|
|
||||||
perror(file);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
out = gzopen(outfile, mode);
|
|
||||||
if (out == NULL) {
|
|
||||||
fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
gz_compress(in, out);
|
|
||||||
|
|
||||||
unlink(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Uncompress the given file and remove the original.
|
|
||||||
*/
|
|
||||||
void file_uncompress(char *file)
|
|
||||||
{
|
|
||||||
char buf[MAX_NAME_LEN];
|
|
||||||
char *infile, *outfile;
|
|
||||||
FILE *out;
|
|
||||||
gzFile in;
|
|
||||||
size_t len = strlen(file);
|
|
||||||
|
|
||||||
if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) {
|
|
||||||
fprintf(stderr, "%s: filename too long\n", prog);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "%s", file);
|
|
||||||
|
|
||||||
if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
|
|
||||||
infile = file;
|
|
||||||
outfile = buf;
|
|
||||||
outfile[len-3] = '\0';
|
|
||||||
} else {
|
|
||||||
outfile = file;
|
|
||||||
infile = buf;
|
|
||||||
snprintf(buf + len, sizeof(buf) - len, "%s", GZ_SUFFIX);
|
|
||||||
}
|
|
||||||
in = gzopen(infile, "rb");
|
|
||||||
if (in == NULL) {
|
|
||||||
fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
out = fopen(outfile, "wb");
|
|
||||||
if (out == NULL) {
|
|
||||||
perror(file);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
gz_uncompress(in, out);
|
|
||||||
|
|
||||||
unlink(infile);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
* Usage: minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...]
|
|
||||||
* -c : write to standard output
|
|
||||||
* -d : decompress
|
|
||||||
* -f : compress with Z_FILTERED
|
|
||||||
* -h : compress with Z_HUFFMAN_ONLY
|
|
||||||
* -r : compress with Z_RLE
|
|
||||||
* -1 to -9 : compression level
|
|
||||||
*/
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
int copyout = 0;
|
|
||||||
int uncompr = 0;
|
|
||||||
gzFile file;
|
|
||||||
char *bname, outmode[20];
|
|
||||||
|
|
||||||
snprintf(outmode, sizeof(outmode), "%s", "wb6 ");
|
|
||||||
|
|
||||||
prog = argv[0];
|
|
||||||
bname = strrchr(argv[0], '/');
|
|
||||||
if (bname)
|
|
||||||
bname++;
|
|
||||||
else
|
|
||||||
bname = argv[0];
|
|
||||||
argc--, argv++;
|
|
||||||
|
|
||||||
if (!strcmp(bname, "gunzip"))
|
|
||||||
uncompr = 1;
|
|
||||||
else if (!strcmp(bname, "zcat"))
|
|
||||||
copyout = uncompr = 1;
|
|
||||||
|
|
||||||
while (argc > 0) {
|
|
||||||
if (strcmp(*argv, "-c") == 0)
|
|
||||||
copyout = 1;
|
|
||||||
else if (strcmp(*argv, "-d") == 0)
|
|
||||||
uncompr = 1;
|
|
||||||
else if (strcmp(*argv, "-f") == 0)
|
|
||||||
outmode[3] = 'f';
|
|
||||||
else if (strcmp(*argv, "-h") == 0)
|
|
||||||
outmode[3] = 'h';
|
|
||||||
else if (strcmp(*argv, "-r") == 0)
|
|
||||||
outmode[3] = 'R';
|
|
||||||
else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&
|
|
||||||
(*argv)[2] == 0)
|
|
||||||
outmode[2] = (*argv)[1];
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
argc--, argv++;
|
|
||||||
}
|
|
||||||
if (outmode[3] == ' ')
|
|
||||||
outmode[3] = 0;
|
|
||||||
if (argc == 0) {
|
|
||||||
SET_BINARY_MODE(stdin);
|
|
||||||
SET_BINARY_MODE(stdout);
|
|
||||||
if (uncompr) {
|
|
||||||
file = gzdopen(fileno(stdin), "rb");
|
|
||||||
if (file == NULL) error("can't gzdopen stdin");
|
|
||||||
gz_uncompress(file, stdout);
|
|
||||||
} else {
|
|
||||||
file = gzdopen(fileno(stdout), outmode);
|
|
||||||
if (file == NULL) error("can't gzdopen stdout");
|
|
||||||
gz_compress(stdin, file);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (copyout) {
|
|
||||||
SET_BINARY_MODE(stdout);
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
if (uncompr) {
|
|
||||||
if (copyout) {
|
|
||||||
file = gzopen(*argv, "rb");
|
|
||||||
if (file == NULL)
|
|
||||||
fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv);
|
|
||||||
else
|
|
||||||
gz_uncompress(file, stdout);
|
|
||||||
} else {
|
|
||||||
file_uncompress(*argv);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (copyout) {
|
|
||||||
FILE * in = fopen(*argv, "rb");
|
|
||||||
|
|
||||||
if (in == NULL) {
|
|
||||||
perror(*argv);
|
|
||||||
} else {
|
|
||||||
file = gzdopen(fileno(stdout), outmode);
|
|
||||||
if (file == NULL) error("can't gzdopen stdout");
|
|
||||||
|
|
||||||
gz_compress(in, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
file_compress(*argv, outmode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (argv++, --argc);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
TESTDIR="$(dirname "$0")"
|
|
||||||
|
|
||||||
CVEs="CVE-2002-0059 CVE-2004-0797 CVE-2005-1849 CVE-2005-2096"
|
|
||||||
|
|
||||||
for CVE in $CVEs; do
|
|
||||||
fail=0
|
|
||||||
for testcase in ${TESTDIR}/${CVE}/*.gz; do
|
|
||||||
../minigzip -d < "$testcase"
|
|
||||||
# we expect that a 1 error code is OK
|
|
||||||
# for a vulnerable failure we'd expect 134 or similar
|
|
||||||
if [ $? -ne 1 ]; then
|
|
||||||
fail=1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if [ $fail -eq 0 ]; then
|
|
||||||
echo " --- zlib not vulnerable to $CVE ---";
|
|
||||||
else
|
|
||||||
echo " --- zlib VULNERABLE to $CVE ---"; exit 1;
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
@ -1,116 +0,0 @@
|
|||||||
<?xml version="1.0" ?>
|
|
||||||
<package name="zlib" version="1.2.8">
|
|
||||||
<library name="zlib" dlversion="1.2.8" dlname="z">
|
|
||||||
<property name="description"> zip compression library </property>
|
|
||||||
<property name="include-target-dir" value="$(@PACKAGE/install-includedir)" />
|
|
||||||
|
|
||||||
<!-- fixme: not implemented yet -->
|
|
||||||
<property name="compiler/c/inline" value="yes" />
|
|
||||||
|
|
||||||
<include-file name="zlib.h" scope="public" mode="644" />
|
|
||||||
<include-file name="zconf.h" scope="public" mode="644" />
|
|
||||||
|
|
||||||
<source name="adler32.c">
|
|
||||||
<depend name="zlib.h" />
|
|
||||||
<depend name="zconf.h" />
|
|
||||||
</source>
|
|
||||||
<source name="compress.c">
|
|
||||||
<depend name="zlib.h" />
|
|
||||||
<depend name="zconf.h" />
|
|
||||||
</source>
|
|
||||||
<source name="crc32.c">
|
|
||||||
<depend name="zlib.h" />
|
|
||||||
<depend name="zconf.h" />
|
|
||||||
<depend name="crc32.h" />
|
|
||||||
</source>
|
|
||||||
<source name="gzclose.c">
|
|
||||||
<depend name="zlib.h" />
|
|
||||||
<depend name="zconf.h" />
|
|
||||||
<depend name="gzguts.h" />
|
|
||||||
</source>
|
|
||||||
<source name="gzlib.c">
|
|
||||||
<depend name="zlib.h" />
|
|
||||||
<depend name="zconf.h" />
|
|
||||||
<depend name="gzguts.h" />
|
|
||||||
</source>
|
|
||||||
<source name="gzread.c">
|
|
||||||
<depend name="zlib.h" />
|
|
||||||
<depend name="zconf.h" />
|
|
||||||
<depend name="gzguts.h" />
|
|
||||||
</source>
|
|
||||||
<source name="gzwrite.c">
|
|
||||||
<depend name="zlib.h" />
|
|
||||||
<depend name="zconf.h" />
|
|
||||||
<depend name="gzguts.h" />
|
|
||||||
</source>
|
|
||||||
<source name="uncompr.c">
|
|
||||||
<depend name="zlib.h" />
|
|
||||||
<depend name="zconf.h" />
|
|
||||||
</source>
|
|
||||||
<source name="deflate.c">
|
|
||||||
<depend name="zlib.h" />
|
|
||||||
<depend name="zconf.h" />
|
|
||||||
<depend name="zutil.h" />
|
|
||||||
<depend name="deflate.h" />
|
|
||||||
</source>
|
|
||||||
<source name="trees.c">
|
|
||||||
<depend name="zlib.h" />
|
|
||||||
<depend name="zconf.h" />
|
|
||||||
<depend name="zutil.h" />
|
|
||||||
<depend name="deflate.h" />
|
|
||||||
<depend name="trees.h" />
|
|
||||||
</source>
|
|
||||||
<source name="zutil.c">
|
|
||||||
<depend name="zlib.h" />
|
|
||||||
<depend name="zconf.h" />
|
|
||||||
<depend name="zutil.h" />
|
|
||||||
</source>
|
|
||||||
<source name="inflate.c">
|
|
||||||
<depend name="zlib.h" />
|
|
||||||
<depend name="zconf.h" />
|
|
||||||
<depend name="zutil.h" />
|
|
||||||
<depend name="inftrees.h" />
|
|
||||||
<depend name="inflate.h" />
|
|
||||||
<depend name="inffast.h" />
|
|
||||||
</source>
|
|
||||||
<source name="infback.c">
|
|
||||||
<depend name="zlib.h" />
|
|
||||||
<depend name="zconf.h" />
|
|
||||||
<depend name="zutil.h" />
|
|
||||||
<depend name="inftrees.h" />
|
|
||||||
<depend name="inflate.h" />
|
|
||||||
<depend name="inffast.h" />
|
|
||||||
</source>
|
|
||||||
<source name="inftrees.c">
|
|
||||||
<depend name="zlib.h" />
|
|
||||||
<depend name="zconf.h" />
|
|
||||||
<depend name="zutil.h" />
|
|
||||||
<depend name="inftrees.h" />
|
|
||||||
</source>
|
|
||||||
<source name="inffast.c">
|
|
||||||
<depend name="zlib.h" />
|
|
||||||
<depend name="zconf.h" />
|
|
||||||
<depend name="zutil.h" />
|
|
||||||
<depend name="inftrees.h" />
|
|
||||||
<depend name="inflate.h" />
|
|
||||||
<depend name="inffast.h" />
|
|
||||||
</source>
|
|
||||||
</library>
|
|
||||||
</package>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
CFLAGS=-O
|
|
||||||
#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
|
|
||||||
#CFLAGS=-g -DDEBUG
|
|
||||||
#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
|
|
||||||
# -Wstrict-prototypes -Wmissing-prototypes
|
|
||||||
|
|
||||||
# OBJA =
|
|
||||||
# to use the asm code: make OBJA=match.o
|
|
||||||
#
|
|
||||||
match.o: match.S
|
|
||||||
$(CPP) match.S > _match.s
|
|
||||||
$(CC) -c _match.s
|
|
||||||
mv _match.o match.o
|
|
||||||
rm -f _match.s
|
|
||||||
-->
|
|
File diff suppressed because it is too large
Load Diff
@ -1,132 +0,0 @@
|
|||||||
#ifndef TREES_H_
|
|
||||||
#define TREES_H_
|
|
||||||
|
|
||||||
/* header created automatically with -DGEN_TREES_H */
|
|
||||||
|
|
||||||
ZLIB_INTERNAL const ct_data static_ltree[L_CODES+2] = {
|
|
||||||
{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}},
|
|
||||||
{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}},
|
|
||||||
{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}},
|
|
||||||
{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}},
|
|
||||||
{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}},
|
|
||||||
{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}},
|
|
||||||
{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}},
|
|
||||||
{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}},
|
|
||||||
{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}},
|
|
||||||
{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}},
|
|
||||||
{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}},
|
|
||||||
{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}},
|
|
||||||
{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}},
|
|
||||||
{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}},
|
|
||||||
{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}},
|
|
||||||
{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}},
|
|
||||||
{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}},
|
|
||||||
{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}},
|
|
||||||
{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}},
|
|
||||||
{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}},
|
|
||||||
{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}},
|
|
||||||
{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}},
|
|
||||||
{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}},
|
|
||||||
{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}},
|
|
||||||
{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}},
|
|
||||||
{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}},
|
|
||||||
{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}},
|
|
||||||
{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}},
|
|
||||||
{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}},
|
|
||||||
{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}},
|
|
||||||
{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}},
|
|
||||||
{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}},
|
|
||||||
{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}},
|
|
||||||
{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}},
|
|
||||||
{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}},
|
|
||||||
{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}},
|
|
||||||
{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}},
|
|
||||||
{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}},
|
|
||||||
{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}},
|
|
||||||
{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}},
|
|
||||||
{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}},
|
|
||||||
{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}},
|
|
||||||
{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}},
|
|
||||||
{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}},
|
|
||||||
{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}},
|
|
||||||
{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}},
|
|
||||||
{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}},
|
|
||||||
{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}},
|
|
||||||
{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}},
|
|
||||||
{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}},
|
|
||||||
{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}},
|
|
||||||
{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}},
|
|
||||||
{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}},
|
|
||||||
{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}},
|
|
||||||
{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}},
|
|
||||||
{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}},
|
|
||||||
{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}},
|
|
||||||
{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}}
|
|
||||||
};
|
|
||||||
|
|
||||||
local const ct_data static_dtree[D_CODES] = {
|
|
||||||
{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
|
|
||||||
{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
|
|
||||||
{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
|
|
||||||
{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
|
|
||||||
{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
|
|
||||||
{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
|
|
||||||
};
|
|
||||||
|
|
||||||
const unsigned char ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {
|
|
||||||
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
|
|
||||||
8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
|
|
||||||
10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
|
|
||||||
11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
|
|
||||||
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
|
|
||||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
|
||||||
13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
|
||||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
|
||||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
|
||||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
|
|
||||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
|
||||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
|
||||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
|
|
||||||
18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
|
|
||||||
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
||||||
24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
|
||||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
|
||||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
|
|
||||||
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
|
||||||
27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
|
||||||
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
|
||||||
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
|
||||||
28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
|
||||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
|
||||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
|
||||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
|
|
||||||
};
|
|
||||||
|
|
||||||
const unsigned char ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {
|
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
|
|
||||||
13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
|
|
||||||
17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
|
|
||||||
19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
|
|
||||||
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
|
|
||||||
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
|
|
||||||
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
||||||
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
||||||
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
|
||||||
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
|
|
||||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
|
||||||
26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
|
||||||
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
|
|
||||||
};
|
|
||||||
|
|
||||||
local const int base_length[LENGTH_CODES] = {
|
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
|
|
||||||
64, 80, 96, 112, 128, 160, 192, 224, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
local const int base_dist[D_CODES] = {
|
|
||||||
0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
|
|
||||||
32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
|
|
||||||
1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* TREES_H_ */
|
|
@ -1,75 +0,0 @@
|
|||||||
/* uncompr.c -- decompress a memory buffer
|
|
||||||
* Copyright (C) 1995-2003, 2010, 2014 Jean-loup Gailly, Mark Adler.
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* @(#) $Id$ */
|
|
||||||
|
|
||||||
#define ZLIB_INTERNAL
|
|
||||||
#include "zlib.h"
|
|
||||||
|
|
||||||
/* ===========================================================================
|
|
||||||
Decompresses the source buffer into the destination buffer. sourceLen is
|
|
||||||
the byte length of the source buffer. Upon entry, destLen is the total
|
|
||||||
size of the destination buffer, which must be large enough to hold the
|
|
||||||
entire uncompressed data. (The size of the uncompressed data must have
|
|
||||||
been saved previously by the compressor and transmitted to the decompressor
|
|
||||||
by some mechanism outside the scope of this compression library.)
|
|
||||||
Upon exit, destLen is the actual size of the compressed buffer.
|
|
||||||
|
|
||||||
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
|
|
||||||
enough memory, Z_BUF_ERROR if there was not enough room in the output
|
|
||||||
buffer, or Z_DATA_ERROR if the input data was corrupted, including if the
|
|
||||||
input data is an incomplete zlib stream.
|
|
||||||
*/
|
|
||||||
int ZEXPORT uncompress(unsigned char *dest, size_t *destLen, const unsigned char *source, size_t sourceLen) {
|
|
||||||
z_stream stream;
|
|
||||||
int err;
|
|
||||||
const unsigned int max = (unsigned int)0 - 1;
|
|
||||||
size_t left;
|
|
||||||
unsigned char buf[1]; /* for detection of incomplete stream when *destLen == 0 */
|
|
||||||
|
|
||||||
if (*destLen) {
|
|
||||||
left = *destLen;
|
|
||||||
*destLen = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
left = 1;
|
|
||||||
dest = buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
stream.next_in = (const unsigned char *)source;
|
|
||||||
stream.avail_in = 0;
|
|
||||||
stream.zalloc = (alloc_func)0;
|
|
||||||
stream.zfree = (free_func)0;
|
|
||||||
stream.opaque = NULL;
|
|
||||||
|
|
||||||
err = inflateInit(&stream);
|
|
||||||
if (err != Z_OK) return err;
|
|
||||||
|
|
||||||
stream.next_out = dest;
|
|
||||||
stream.avail_out = 0;
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (stream.avail_out == 0) {
|
|
||||||
stream.avail_out = left > (unsigned long)max ? max : (unsigned int)left;
|
|
||||||
left -= stream.avail_out;
|
|
||||||
}
|
|
||||||
if (stream.avail_in == 0) {
|
|
||||||
stream.avail_in = sourceLen > (unsigned long)max ? max : (unsigned int)sourceLen;
|
|
||||||
sourceLen -= stream.avail_in;
|
|
||||||
}
|
|
||||||
err = inflate(&stream, Z_NO_FLUSH);
|
|
||||||
} while (err == Z_OK);
|
|
||||||
|
|
||||||
if (dest != buf)
|
|
||||||
*destLen = stream.total_out;
|
|
||||||
else if (stream.total_out && err == Z_BUF_ERROR)
|
|
||||||
left = 1;
|
|
||||||
|
|
||||||
inflateEnd(&stream);
|
|
||||||
return err == Z_STREAM_END ? Z_OK :
|
|
||||||
err == Z_NEED_DICT ? Z_DATA_ERROR :
|
|
||||||
err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR :
|
|
||||||
err;
|
|
||||||
}
|
|
@ -1,397 +0,0 @@
|
|||||||
|
|
||||||
Frequently Asked Questions about ZLIB1.DLL
|
|
||||||
|
|
||||||
|
|
||||||
This document describes the design, the rationale, and the usage
|
|
||||||
of the official DLL build of zlib, named ZLIB1.DLL. If you have
|
|
||||||
general questions about zlib, you should see the file "FAQ" found
|
|
||||||
in the zlib distribution, or at the following location:
|
|
||||||
http://www.gzip.org/zlib/zlib_faq.html
|
|
||||||
|
|
||||||
|
|
||||||
1. What is ZLIB1.DLL, and how can I get it?
|
|
||||||
|
|
||||||
- ZLIB1.DLL is the official build of zlib as a DLL.
|
|
||||||
(Please remark the character '1' in the name.)
|
|
||||||
|
|
||||||
Pointers to a precompiled ZLIB1.DLL can be found in the zlib
|
|
||||||
web site at:
|
|
||||||
http://www.zlib.net/
|
|
||||||
|
|
||||||
Applications that link to ZLIB1.DLL can rely on the following
|
|
||||||
specification:
|
|
||||||
|
|
||||||
* The exported symbols are exclusively defined in the source
|
|
||||||
files "zlib.h" and "zlib.def", found in an official zlib
|
|
||||||
source distribution.
|
|
||||||
* The symbols are exported by name, not by ordinal.
|
|
||||||
* The exported names are undecorated.
|
|
||||||
* The calling convention of functions is "C" (CDECL).
|
|
||||||
* The ZLIB1.DLL binary is linked to MSVCRT.DLL.
|
|
||||||
|
|
||||||
The archive in which ZLIB1.DLL is bundled contains compiled
|
|
||||||
test programs that must run with a valid build of ZLIB1.DLL.
|
|
||||||
It is recommended to download the prebuilt DLL from the zlib
|
|
||||||
web site, instead of building it yourself, to avoid potential
|
|
||||||
incompatibilities that could be introduced by your compiler
|
|
||||||
and build settings. If you do build the DLL yourself, please
|
|
||||||
make sure that it complies with all the above requirements,
|
|
||||||
and it runs with the precompiled test programs, bundled with
|
|
||||||
the original ZLIB1.DLL distribution.
|
|
||||||
|
|
||||||
If, for any reason, you need to build an incompatible DLL,
|
|
||||||
please use a different file name.
|
|
||||||
|
|
||||||
|
|
||||||
2. Why did you change the name of the DLL to ZLIB1.DLL?
|
|
||||||
What happened to the old ZLIB.DLL?
|
|
||||||
|
|
||||||
- The old ZLIB.DLL, built from zlib-1.1.4 or earlier, required
|
|
||||||
compilation settings that were incompatible to those used by
|
|
||||||
a static build. The DLL settings were supposed to be enabled
|
|
||||||
by defining the macro ZLIB_DLL, before including "zlib.h".
|
|
||||||
Incorrect handling of this macro was silently accepted at
|
|
||||||
build time, resulting in two major problems:
|
|
||||||
|
|
||||||
* ZLIB_DLL was missing from the old makefile. When building
|
|
||||||
the DLL, not all people added it to the build options. In
|
|
||||||
consequence, incompatible incarnations of ZLIB.DLL started
|
|
||||||
to circulate around the net.
|
|
||||||
|
|
||||||
* When switching from using the static library to using the
|
|
||||||
DLL, applications had to define the ZLIB_DLL macro and
|
|
||||||
to recompile all the sources that contained calls to zlib
|
|
||||||
functions. Failure to do so resulted in creating binaries
|
|
||||||
that were unable to run with the official ZLIB.DLL build.
|
|
||||||
|
|
||||||
The only possible solution that we could foresee was to make
|
|
||||||
a binary-incompatible change in the DLL interface, in order to
|
|
||||||
remove the dependency on the ZLIB_DLL macro, and to release
|
|
||||||
the new DLL under a different name.
|
|
||||||
|
|
||||||
We chose the name ZLIB1.DLL, where '1' indicates the major
|
|
||||||
zlib version number. We hope that we will not have to break
|
|
||||||
the binary compatibility again, at least not as long as the
|
|
||||||
zlib-1.x series will last.
|
|
||||||
|
|
||||||
There is still a ZLIB_DLL macro, that can trigger a more
|
|
||||||
efficient build and use of the DLL, but compatibility no
|
|
||||||
longer dependents on it.
|
|
||||||
|
|
||||||
|
|
||||||
3. Can I build ZLIB.DLL from the new zlib sources, and replace
|
|
||||||
an old ZLIB.DLL, that was built from zlib-1.1.4 or earlier?
|
|
||||||
|
|
||||||
- In principle, you can do it by assigning calling convention
|
|
||||||
keywords to the macros ZEXPORT and ZEXPORTVA. In practice,
|
|
||||||
it depends on what you mean by "an old ZLIB.DLL", because the
|
|
||||||
old DLL exists in several mutually-incompatible versions.
|
|
||||||
You have to find out first what kind of calling convention is
|
|
||||||
being used in your particular ZLIB.DLL build, and to use the
|
|
||||||
same one in the new build. If you don't know what this is all
|
|
||||||
about, you might be better off if you would just leave the old
|
|
||||||
DLL intact.
|
|
||||||
|
|
||||||
|
|
||||||
4. Can I compile my application using the new zlib interface, and
|
|
||||||
link it to an old ZLIB.DLL, that was built from zlib-1.1.4 or
|
|
||||||
earlier?
|
|
||||||
|
|
||||||
- The official answer is "no"; the real answer depends again on
|
|
||||||
what kind of ZLIB.DLL you have. Even if you are lucky, this
|
|
||||||
course of action is unreliable.
|
|
||||||
|
|
||||||
If you rebuild your application and you intend to use a newer
|
|
||||||
version of zlib (post- 1.1.4), it is strongly recommended to
|
|
||||||
link it to the new ZLIB1.DLL.
|
|
||||||
|
|
||||||
|
|
||||||
5. Why are the zlib symbols exported by name, and not by ordinal?
|
|
||||||
|
|
||||||
- Although exporting symbols by ordinal is a little faster, it
|
|
||||||
is risky. Any single glitch in the maintenance or use of the
|
|
||||||
DEF file that contains the ordinals can result in incompatible
|
|
||||||
builds and frustrating crashes. Simply put, the benefits of
|
|
||||||
exporting symbols by ordinal do not justify the risks.
|
|
||||||
|
|
||||||
Technically, it should be possible to maintain ordinals in
|
|
||||||
the DEF file, and still export the symbols by name. Ordinals
|
|
||||||
exist in every DLL, and even if the dynamic linking performed
|
|
||||||
at the DLL startup is searching for names, ordinals serve as
|
|
||||||
hints, for a faster name lookup. However, if the DEF file
|
|
||||||
contains ordinals, the Microsoft linker automatically builds
|
|
||||||
an implib that will cause the executables linked to it to use
|
|
||||||
those ordinals, and not the names. It is interesting to
|
|
||||||
notice that the GNU linker for Win32 does not suffer from this
|
|
||||||
problem.
|
|
||||||
|
|
||||||
It is possible to avoid the DEF file if the exported symbols
|
|
||||||
are accompanied by a "__declspec(dllexport)" attribute in the
|
|
||||||
source files. You can do this in zlib by predefining the
|
|
||||||
ZLIB_DLL macro.
|
|
||||||
|
|
||||||
|
|
||||||
6. I see that the ZLIB1.DLL functions use the "C" (CDECL) calling
|
|
||||||
convention. Why not use the STDCALL convention?
|
|
||||||
STDCALL is the standard convention in Win32, and I need it in
|
|
||||||
my Visual Basic project!
|
|
||||||
|
|
||||||
(For readability, we use CDECL to refer to the convention
|
|
||||||
triggered by the "__cdecl" keyword, STDCALL to refer to
|
|
||||||
the convention triggered by "__stdcall", and FASTCALL to
|
|
||||||
refer to the convention triggered by "__fastcall".)
|
|
||||||
|
|
||||||
- Most of the native Windows API functions (without varargs) use
|
|
||||||
indeed the WINAPI convention (which translates to STDCALL in
|
|
||||||
Win32), but the standard C functions use CDECL. If a user
|
|
||||||
application is intrinsically tied to the Windows API (e.g.
|
|
||||||
it calls native Windows API functions such as CreateFile()),
|
|
||||||
sometimes it makes sense to decorate its own functions with
|
|
||||||
WINAPI. But if ANSI C or POSIX portability is a goal (e.g.
|
|
||||||
it calls standard C functions such as fopen()), it is not a
|
|
||||||
sound decision to request the inclusion of <windows.h>, or to
|
|
||||||
use non-ANSI constructs, for the sole purpose to make the user
|
|
||||||
functions STDCALL-able.
|
|
||||||
|
|
||||||
The functionality offered by zlib is not in the category of
|
|
||||||
"Windows functionality", but is more like "C functionality".
|
|
||||||
|
|
||||||
Technically, STDCALL is not bad; in fact, it is slightly
|
|
||||||
faster than CDECL, and it works with variable-argument
|
|
||||||
functions, just like CDECL. It is unfortunate that, in spite
|
|
||||||
of using STDCALL in the Windows API, it is not the default
|
|
||||||
convention used by the C compilers that run under Windows.
|
|
||||||
The roots of the problem reside deep inside the unsafety of
|
|
||||||
the K&R-style function prototypes, where the argument types
|
|
||||||
are not specified; but that is another story for another day.
|
|
||||||
|
|
||||||
The remaining fact is that CDECL is the default convention.
|
|
||||||
Even if an explicit convention is hard-coded into the function
|
|
||||||
prototypes inside C headers, problems may appear. The
|
|
||||||
necessity to expose the convention in users' callbacks is one
|
|
||||||
of these problems.
|
|
||||||
|
|
||||||
The calling convention issues are also important when using
|
|
||||||
zlib in other programming languages. Some of them, like Ada
|
|
||||||
(GNAT) and Fortran (GNU G77), have C bindings implemented
|
|
||||||
initially on Unix, and relying on the C calling convention.
|
|
||||||
On the other hand, the pre- .NET versions of Microsoft Visual
|
|
||||||
Basic require STDCALL, while Borland Delphi prefers, although
|
|
||||||
it does not require, FASTCALL.
|
|
||||||
|
|
||||||
In fairness to all possible uses of zlib outside the C
|
|
||||||
programming language, we choose the default "C" convention.
|
|
||||||
Anyone interested in different bindings or conventions is
|
|
||||||
encouraged to maintain specialized projects. The "contrib/"
|
|
||||||
directory from the zlib distribution already holds a couple
|
|
||||||
of foreign bindings, such as Ada, C++, and Delphi.
|
|
||||||
|
|
||||||
|
|
||||||
7. I need a DLL for my Visual Basic project. What can I do?
|
|
||||||
|
|
||||||
- Define the ZLIB_WINAPI macro before including "zlib.h", when
|
|
||||||
building both the DLL and the user application (except that
|
|
||||||
you don't need to define anything when using the DLL in Visual
|
|
||||||
Basic). The ZLIB_WINAPI macro will switch on the WINAPI
|
|
||||||
(STDCALL) convention. The name of this DLL must be different
|
|
||||||
than the official ZLIB1.DLL.
|
|
||||||
|
|
||||||
Gilles Vollant has contributed a build named ZLIBWAPI.DLL,
|
|
||||||
with the ZLIB_WINAPI macro turned on, and with the minizip
|
|
||||||
functionality built in. For more information, please read
|
|
||||||
the notes inside "contrib/vstudio/readme.txt", found in the
|
|
||||||
zlib distribution.
|
|
||||||
|
|
||||||
|
|
||||||
8. I need to use zlib in my Microsoft .NET project. What can I
|
|
||||||
do?
|
|
||||||
|
|
||||||
- Henrik Ravn has contributed a .NET wrapper around zlib. Look
|
|
||||||
into contrib/dotzlib/, inside the zlib distribution.
|
|
||||||
|
|
||||||
|
|
||||||
9. If my application uses ZLIB1.DLL, should I link it to
|
|
||||||
MSVCRT.DLL? Why?
|
|
||||||
|
|
||||||
- It is not required, but it is recommended to link your
|
|
||||||
application to MSVCRT.DLL, if it uses ZLIB1.DLL.
|
|
||||||
|
|
||||||
The executables (.EXE, .DLL, etc.) that are involved in the
|
|
||||||
same process and are using the C run-time library (i.e. they
|
|
||||||
are calling standard C functions), must link to the same
|
|
||||||
library. There are several libraries in the Win32 system:
|
|
||||||
CRTDLL.DLL, MSVCRT.DLL, the static C libraries, etc.
|
|
||||||
Since ZLIB1.DLL is linked to MSVCRT.DLL, the executables that
|
|
||||||
depend on it should also be linked to MSVCRT.DLL.
|
|
||||||
|
|
||||||
|
|
||||||
10. Why are you saying that ZLIB1.DLL and my application should
|
|
||||||
be linked to the same C run-time (CRT) library? I linked my
|
|
||||||
application and my DLLs to different C libraries (e.g. my
|
|
||||||
application to a static library, and my DLLs to MSVCRT.DLL),
|
|
||||||
and everything works fine.
|
|
||||||
|
|
||||||
- If a user library invokes only pure Win32 API (accessible via
|
|
||||||
<windows.h> and the related headers), its DLL build will work
|
|
||||||
in any context. But if this library invokes standard C API,
|
|
||||||
things get more complicated.
|
|
||||||
|
|
||||||
There is a single Win32 library in a Win32 system. Every
|
|
||||||
function in this library resides in a single DLL module, that
|
|
||||||
is safe to call from anywhere. On the other hand, there are
|
|
||||||
multiple versions of the C library, and each of them has its
|
|
||||||
own separate internal state. Standalone executables and user
|
|
||||||
DLLs that call standard C functions must link to a C run-time
|
|
||||||
(CRT) library, be it static or shared (DLL). Intermixing
|
|
||||||
occurs when an executable (not necessarily standalone) and a
|
|
||||||
DLL are linked to different CRTs, and both are running in the
|
|
||||||
same process.
|
|
||||||
|
|
||||||
Intermixing multiple CRTs is possible, as long as their
|
|
||||||
internal states are kept intact. The Microsoft Knowledge Base
|
|
||||||
articles KB94248 "HOWTO: Use the C Run-Time" and KB140584
|
|
||||||
"HOWTO: Link with the Correct C Run-Time (CRT) Library"
|
|
||||||
mention the potential problems raised by intermixing.
|
|
||||||
|
|
||||||
If intermixing works for you, it's because your application
|
|
||||||
and DLLs are avoiding the corruption of each of the CRTs'
|
|
||||||
internal states, maybe by careful design, or maybe by fortune.
|
|
||||||
|
|
||||||
Also note that linking ZLIB1.DLL to non-Microsoft CRTs, such
|
|
||||||
as those provided by Borland, raises similar problems.
|
|
||||||
|
|
||||||
|
|
||||||
11. Why are you linking ZLIB1.DLL to MSVCRT.DLL?
|
|
||||||
|
|
||||||
- MSVCRT.DLL exists on every Windows 95 with a new service pack
|
|
||||||
installed, or with Microsoft Internet Explorer 4 or later, and
|
|
||||||
on all other Windows 4.x or later (Windows 98, Windows NT 4,
|
|
||||||
or later). It is freely distributable; if not present in the
|
|
||||||
system, it can be downloaded from Microsoft or from other
|
|
||||||
software provider for free.
|
|
||||||
|
|
||||||
The fact that MSVCRT.DLL does not exist on a virgin Windows 95
|
|
||||||
is not so problematic. Windows 95 is scarcely found nowadays,
|
|
||||||
Microsoft ended its support a long time ago, and many recent
|
|
||||||
applications from various vendors, including Microsoft, do not
|
|
||||||
even run on it. Furthermore, no serious user should run
|
|
||||||
Windows 95 without a proper update installed.
|
|
||||||
|
|
||||||
|
|
||||||
12. Why are you not linking ZLIB1.DLL to
|
|
||||||
<<my favorite C run-time library>> ?
|
|
||||||
|
|
||||||
- We considered and abandoned the following alternatives:
|
|
||||||
|
|
||||||
* Linking ZLIB1.DLL to a static C library (LIBC.LIB, or
|
|
||||||
LIBCMT.LIB) is not a good option. People are using the DLL
|
|
||||||
mainly to save disk space. If you are linking your program
|
|
||||||
to a static C library, you may as well consider linking zlib
|
|
||||||
in statically, too.
|
|
||||||
|
|
||||||
* Linking ZLIB1.DLL to CRTDLL.DLL looks appealing, because
|
|
||||||
CRTDLL.DLL is present on every Win32 installation.
|
|
||||||
Unfortunately, it has a series of problems: it does not
|
|
||||||
work properly with Microsoft's C++ libraries, it does not
|
|
||||||
provide support for 64-bit file offsets, (and so on...),
|
|
||||||
and Microsoft discontinued its support a long time ago.
|
|
||||||
|
|
||||||
* Linking ZLIB1.DLL to MSVCR70.DLL or MSVCR71.DLL, supplied
|
|
||||||
with the Microsoft .NET platform, and Visual C++ 7.0/7.1,
|
|
||||||
raises problems related to the status of ZLIB1.DLL as a
|
|
||||||
system component. According to the Microsoft Knowledge Base
|
|
||||||
article KB326922 "INFO: Redistribution of the Shared C
|
|
||||||
Runtime Component in Visual C++ .NET", MSVCR70.DLL and
|
|
||||||
MSVCR71.DLL are not supposed to function as system DLLs,
|
|
||||||
because they may clash with MSVCRT.DLL. Instead, the
|
|
||||||
application's installer is supposed to put these DLLs
|
|
||||||
(if needed) in the application's private directory.
|
|
||||||
If ZLIB1.DLL depends on a non-system runtime, it cannot
|
|
||||||
function as a redistributable system component.
|
|
||||||
|
|
||||||
* Linking ZLIB1.DLL to non-Microsoft runtimes, such as
|
|
||||||
Borland's, or Cygwin's, raises problems related to the
|
|
||||||
reliable presence of these runtimes on Win32 systems.
|
|
||||||
It's easier to let the DLL build of zlib up to the people
|
|
||||||
who distribute these runtimes, and who may proceed as
|
|
||||||
explained in the answer to Question 14.
|
|
||||||
|
|
||||||
|
|
||||||
13. If ZLIB1.DLL cannot be linked to MSVCR70.DLL or MSVCR71.DLL,
|
|
||||||
how can I build/use ZLIB1.DLL in Microsoft Visual C++ 7.0
|
|
||||||
(Visual Studio .NET) or newer?
|
|
||||||
|
|
||||||
- Due to the problems explained in the Microsoft Knowledge Base
|
|
||||||
article KB326922 (see the previous answer), the C runtime that
|
|
||||||
comes with the VC7 environment is no longer considered a
|
|
||||||
system component. That is, it should not be assumed that this
|
|
||||||
runtime exists, or may be installed in a system directory.
|
|
||||||
Since ZLIB1.DLL is supposed to be a system component, it may
|
|
||||||
not depend on a non-system component.
|
|
||||||
|
|
||||||
In order to link ZLIB1.DLL and your application to MSVCRT.DLL
|
|
||||||
in VC7, you need the library of Visual C++ 6.0 or older. If
|
|
||||||
you don't have this library at hand, it's probably best not to
|
|
||||||
use ZLIB1.DLL.
|
|
||||||
|
|
||||||
We are hoping that, in the future, Microsoft will provide a
|
|
||||||
way to build applications linked to a proper system runtime,
|
|
||||||
from the Visual C++ environment. Until then, you have a
|
|
||||||
couple of alternatives, such as linking zlib in statically.
|
|
||||||
If your application requires dynamic linking, you may proceed
|
|
||||||
as explained in the answer to Question 14.
|
|
||||||
|
|
||||||
|
|
||||||
14. I need to link my own DLL build to a CRT different than
|
|
||||||
MSVCRT.DLL. What can I do?
|
|
||||||
|
|
||||||
- Feel free to rebuild the DLL from the zlib sources, and link
|
|
||||||
it the way you want. You should, however, clearly state that
|
|
||||||
your build is unofficial. You should give it a different file
|
|
||||||
name, and/or install it in a private directory that can be
|
|
||||||
accessed by your application only, and is not visible to the
|
|
||||||
others (i.e. it's neither in the PATH, nor in the SYSTEM or
|
|
||||||
SYSTEM32 directories). Otherwise, your build may clash with
|
|
||||||
applications that link to the official build.
|
|
||||||
|
|
||||||
For example, in Cygwin, zlib is linked to the Cygwin runtime
|
|
||||||
CYGWIN1.DLL, and it is distributed under the name CYGZ.DLL.
|
|
||||||
|
|
||||||
|
|
||||||
15. May I include additional pieces of code that I find useful,
|
|
||||||
link them in ZLIB1.DLL, and export them?
|
|
||||||
|
|
||||||
- No. A legitimate build of ZLIB1.DLL must not include code
|
|
||||||
that does not originate from the official zlib source code.
|
|
||||||
But you can make your own private DLL build, under a different
|
|
||||||
file name, as suggested in the previous answer.
|
|
||||||
|
|
||||||
For example, zlib is a part of the VCL library, distributed
|
|
||||||
with Borland Delphi and C++ Builder. The DLL build of VCL
|
|
||||||
is a redistributable file, named VCLxx.DLL.
|
|
||||||
|
|
||||||
|
|
||||||
16. May I remove some functionality out of ZLIB1.DLL, by enabling
|
|
||||||
macros like NO_GZCOMPRESS or NO_GZIP at compile time?
|
|
||||||
|
|
||||||
- No. A legitimate build of ZLIB1.DLL must provide the complete
|
|
||||||
zlib functionality, as implemented in the official zlib source
|
|
||||||
code. But you can make your own private DLL build, under a
|
|
||||||
different file name, as suggested in the previous answer.
|
|
||||||
|
|
||||||
|
|
||||||
17. I made my own ZLIB1.DLL build. Can I test it for compliance?
|
|
||||||
|
|
||||||
- We prefer that you download the official DLL from the zlib
|
|
||||||
web site. If you need something peculiar from this DLL, you
|
|
||||||
can send your suggestion to the zlib mailing list.
|
|
||||||
|
|
||||||
However, in case you do rebuild the DLL yourself, you can run
|
|
||||||
it with the test programs found in the DLL distribution.
|
|
||||||
Running these test programs is not a guarantee of compliance,
|
|
||||||
but a failure can imply a detected problem.
|
|
||||||
|
|
||||||
**
|
|
||||||
|
|
||||||
This document is written and maintained by
|
|
||||||
Cosmin Truta <cosmint@cs.ubbcluj.ro>
|
|
@ -1,154 +0,0 @@
|
|||||||
# Makefile for zlib using Microsoft (Visual) C
|
|
||||||
# zlib is copyright (C) 1995-2006 Jean-loup Gailly and Mark Adler
|
|
||||||
#
|
|
||||||
# Usage:
|
|
||||||
# nmake -f win32/Makefile.msc (standard build)
|
|
||||||
# nmake -f win32/Makefile.msc LOC=-DFOO (nonstandard build)
|
|
||||||
|
|
||||||
# The toplevel directory of the source tree.
|
|
||||||
#
|
|
||||||
TOP = .
|
|
||||||
|
|
||||||
# optional build flags
|
|
||||||
LOC =
|
|
||||||
|
|
||||||
# variables
|
|
||||||
STATICLIB = zlib.lib
|
|
||||||
SHAREDLIB = zlib1.dll
|
|
||||||
IMPLIB = zdll.lib
|
|
||||||
|
|
||||||
CC = cl
|
|
||||||
LD = link
|
|
||||||
AR = lib
|
|
||||||
RC = rc
|
|
||||||
CP = copy /y
|
|
||||||
CFLAGS = -nologo -MD -W3 -O2 -Oy- -Zi -Fd"zlib" $(LOC)
|
|
||||||
WFLAGS = -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DX86_PCLMULQDQ_CRC -DX86_SSE2_FILL_WINDOW -DX86_CPUID -DX86_SSE4_2_CRC_HASH -DUNALIGNED_OK -DUNROLL_LESS -DX86_QUICK_STRATEGY
|
|
||||||
LDFLAGS = -nologo -debug -incremental:no -opt:ref -manifest
|
|
||||||
ARFLAGS = -nologo
|
|
||||||
RCFLAGS = /dWIN32 /r
|
|
||||||
DEFFILE = zlib.def
|
|
||||||
WITH_GZFILEOP =
|
|
||||||
|
|
||||||
OBJS = adler32.obj compress.obj crc32.obj deflate.obj deflate_fast.obj deflate_quick.obj deflate_slow.obj \
|
|
||||||
infback.obj inflate.obj inftrees.obj inffast.obj match.obj trees.obj uncompr.obj zutil.obj x86.obj fill_window_sse.obj insert_string_sse.obj crc_folding.obj
|
|
||||||
!if "$(WITH_GZFILEOP)" != ""
|
|
||||||
WFLAGS = $(WFLAGS) -DWITH_GZFILEOP
|
|
||||||
OBJS = $(OBJS) gzclose.obj gzlib.obj gzread.obj gzwrite.obj
|
|
||||||
DEFFILE = zlibcompat.def
|
|
||||||
!endif
|
|
||||||
|
|
||||||
# targets
|
|
||||||
all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \
|
|
||||||
example.exe minigzip.exe example_d.exe minigzip_d.exe
|
|
||||||
|
|
||||||
$(STATICLIB): $(OBJS)
|
|
||||||
$(AR) $(ARFLAGS) -out:$@ $(OBJS)
|
|
||||||
|
|
||||||
$(IMPLIB): $(SHAREDLIB)
|
|
||||||
|
|
||||||
$(SHAREDLIB): $(TOP)/win32/zlib.def $(OBJS) zlib1.res
|
|
||||||
$(LD) $(LDFLAGS) -def:$(TOP)/win32/$(DEFFILE) -dll -implib:$(IMPLIB) \
|
|
||||||
-out:$@ -base:0x5A4C0000 $(OBJS) zlib1.res
|
|
||||||
if exist $@.manifest \
|
|
||||||
mt -nologo -manifest $@.manifest -outputresource:$@;2
|
|
||||||
|
|
||||||
example.exe: example.obj $(STATICLIB)
|
|
||||||
$(LD) $(LDFLAGS) example.obj $(STATICLIB)
|
|
||||||
if exist $@.manifest \
|
|
||||||
mt -nologo -manifest $@.manifest -outputresource:$@;1
|
|
||||||
|
|
||||||
minigzip.exe: minigzip.obj $(STATICLIB)
|
|
||||||
$(LD) $(LDFLAGS) minigzip.obj $(STATICLIB)
|
|
||||||
if exist $@.manifest \
|
|
||||||
mt -nologo -manifest $@.manifest -outputresource:$@;1
|
|
||||||
|
|
||||||
example_d.exe: example.obj $(IMPLIB)
|
|
||||||
$(LD) $(LDFLAGS) -out:$@ example.obj $(IMPLIB)
|
|
||||||
if exist $@.manifest \
|
|
||||||
mt -nologo -manifest $@.manifest -outputresource:$@;1
|
|
||||||
|
|
||||||
minigzip_d.exe: minigzip.obj $(IMPLIB)
|
|
||||||
$(LD) $(LDFLAGS) -out:$@ minigzip.obj $(IMPLIB)
|
|
||||||
if exist $@.manifest \
|
|
||||||
mt -nologo -manifest $@.manifest -outputresource:$@;1
|
|
||||||
|
|
||||||
{$(TOP)}.c.obj:
|
|
||||||
$(CC) -c $(WFLAGS) $(CFLAGS) $<
|
|
||||||
|
|
||||||
{$(TOP)/arch/x86}.c.obj:
|
|
||||||
$(CC) -c -I$(TOP) $(WFLAGS) $(CFLAGS) $<
|
|
||||||
|
|
||||||
{$(TOP)/test}.c.obj:
|
|
||||||
$(CC) -c -I$(TOP) $(WFLAGS) $(CFLAGS) $<
|
|
||||||
|
|
||||||
$(TOP)/zconf.h: $(TOP)/zconf.h.in
|
|
||||||
$(CP) $(TOP)\zconf.h.in $(TOP)\zconf.h
|
|
||||||
|
|
||||||
adler32.obj: $(TOP)/adler32.c $(TOP)/zlib.h $(TOP)/zconf.h
|
|
||||||
|
|
||||||
compress.obj: $(TOP)/compress.c $(TOP)/zlib.h $(TOP)/zconf.h
|
|
||||||
|
|
||||||
crc32.obj: $(TOP)/crc32.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/crc32.h
|
|
||||||
|
|
||||||
deflate.obj: $(TOP)/deflate.c $(TOP)/deflate.h $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h
|
|
||||||
|
|
||||||
gzclose.obj: $(TOP)/gzclose.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h
|
|
||||||
|
|
||||||
gzlib.obj: $(TOP)/gzlib.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h
|
|
||||||
|
|
||||||
gzread.obj: $(TOP)/gzread.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h
|
|
||||||
|
|
||||||
gzwrite.obj: $(TOP)/gzwrite.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h
|
|
||||||
|
|
||||||
infback.obj: $(TOP)/infback.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \
|
|
||||||
$(TOP)/inffast.h $(TOP)/inffixed.h
|
|
||||||
|
|
||||||
inffast.obj: $(TOP)/inffast.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \
|
|
||||||
$(TOP)/inffast.h
|
|
||||||
|
|
||||||
inflate.obj: $(TOP)/inflate.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \
|
|
||||||
$(TOP)/inffast.h $(TOP)/inffixed.h
|
|
||||||
|
|
||||||
inftrees.obj: $(TOP)/inftrees.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h
|
|
||||||
|
|
||||||
match.obj: $(TOP)/match.c $(TOP)/deflate.h
|
|
||||||
|
|
||||||
trees.obj: $(TOP)/trees.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/deflate.h $(TOP)/trees.h
|
|
||||||
|
|
||||||
uncompr.obj: $(TOP)/uncompr.c $(TOP)/zlib.h $(TOP)/zconf.h
|
|
||||||
|
|
||||||
zutil.obj: $(TOP)/zutil.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h
|
|
||||||
|
|
||||||
example.obj: $(TOP)/test/example.c $(TOP)/zlib.h $(TOP)/zconf.h
|
|
||||||
|
|
||||||
minigzip.obj: $(TOP)/test/minigzip.c $(TOP)/zlib.h $(TOP)/zconf.h
|
|
||||||
|
|
||||||
zlib1.res: $(TOP)/win32/zlib1.rc
|
|
||||||
$(RC) $(RCFLAGS) /fo$@ $(TOP)/win32/zlib1.rc
|
|
||||||
|
|
||||||
# testing
|
|
||||||
test: example.exe minigzip.exe
|
|
||||||
example
|
|
||||||
echo hello world | minigzip | minigzip -d
|
|
||||||
|
|
||||||
testdll: example_d.exe minigzip_d.exe
|
|
||||||
example_d
|
|
||||||
echo hello world | minigzip_d | minigzip_d -d
|
|
||||||
|
|
||||||
|
|
||||||
# cleanup
|
|
||||||
clean:
|
|
||||||
-del $(STATICLIB)
|
|
||||||
-del $(SHAREDLIB)
|
|
||||||
-del $(IMPLIB)
|
|
||||||
-del *.obj
|
|
||||||
-del *.res
|
|
||||||
-del *.exp
|
|
||||||
-del *.exe
|
|
||||||
-del *.pdb
|
|
||||||
-del *.manifest
|
|
||||||
-del foo.gz
|
|
||||||
|
|
||||||
distclean: clean
|
|
||||||
-del zconf.h
|
|
@ -1,103 +0,0 @@
|
|||||||
ZLIB DATA COMPRESSION LIBRARY
|
|
||||||
|
|
||||||
zlib 1.2.8 is a general purpose data compression library. All the code is
|
|
||||||
thread safe. The data format used by the zlib library is described by RFCs
|
|
||||||
(Request for Comments) 1950 to 1952 in the files
|
|
||||||
http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
|
|
||||||
and rfc1952.txt (gzip format).
|
|
||||||
|
|
||||||
All functions of the compression library are documented in the file zlib.h
|
|
||||||
(volunteer to write man pages welcome, contact zlib@gzip.org). Two compiled
|
|
||||||
examples are distributed in this package, example and minigzip. The example_d
|
|
||||||
and minigzip_d flavors validate that the zlib1.dll file is working correctly.
|
|
||||||
|
|
||||||
Questions about zlib should be sent to <zlib@gzip.org>. The zlib home page
|
|
||||||
is http://zlib.net/ . Before reporting a problem, please check this site to
|
|
||||||
verify that you have the latest version of zlib; otherwise get the latest
|
|
||||||
version and check whether the problem still exists or not.
|
|
||||||
|
|
||||||
PLEASE read DLL_FAQ.txt, and the the zlib FAQ http://zlib.net/zlib_faq.html
|
|
||||||
before asking for help.
|
|
||||||
|
|
||||||
|
|
||||||
Manifest:
|
|
||||||
|
|
||||||
The package zlib-1.2.8-win32-x86.zip will contain the following files:
|
|
||||||
|
|
||||||
README-WIN32.txt This document
|
|
||||||
ChangeLog Changes since previous zlib packages
|
|
||||||
DLL_FAQ.txt Frequently asked questions about zlib1.dll
|
|
||||||
zlib.3.pdf Documentation of this library in Adobe Acrobat format
|
|
||||||
|
|
||||||
example.exe A statically-bound example (using zlib.lib, not the dll)
|
|
||||||
example.pdb Symbolic information for debugging example.exe
|
|
||||||
|
|
||||||
example_d.exe A zlib1.dll bound example (using zdll.lib)
|
|
||||||
example_d.pdb Symbolic information for debugging example_d.exe
|
|
||||||
|
|
||||||
minigzip.exe A statically-bound test program (using zlib.lib, not the dll)
|
|
||||||
minigzip.pdb Symbolic information for debugging minigzip.exe
|
|
||||||
|
|
||||||
minigzip_d.exe A zlib1.dll bound test program (using zdll.lib)
|
|
||||||
minigzip_d.pdb Symbolic information for debugging minigzip_d.exe
|
|
||||||
|
|
||||||
zlib.h Install these files into the compilers' INCLUDE path to
|
|
||||||
zconf.h compile programs which use zlib.lib or zdll.lib
|
|
||||||
|
|
||||||
zdll.lib Install these files into the compilers' LIB path if linking
|
|
||||||
zdll.exp a compiled program to the zlib1.dll binary
|
|
||||||
|
|
||||||
zlib.lib Install these files into the compilers' LIB path to link zlib
|
|
||||||
zlib.pdb into compiled programs, without zlib1.dll runtime dependency
|
|
||||||
(zlib.pdb provides debugging info to the compile time linker)
|
|
||||||
|
|
||||||
zlib1.dll Install this binary shared library into the system PATH, or
|
|
||||||
the program's runtime directory (where the .exe resides)
|
|
||||||
zlib1.pdb Install in the same directory as zlib1.dll, in order to debug
|
|
||||||
an application crash using WinDbg or similar tools.
|
|
||||||
|
|
||||||
All .pdb files above are entirely optional, but are very useful to a developer
|
|
||||||
attempting to diagnose program misbehavior or a crash. Many additional
|
|
||||||
important files for developers can be found in the zlib127.zip source package
|
|
||||||
available from http://zlib.net/ - review that package's README file for details.
|
|
||||||
|
|
||||||
|
|
||||||
Acknowledgments:
|
|
||||||
|
|
||||||
The deflate format used by zlib was defined by Phil Katz. The deflate and
|
|
||||||
zlib specifications were written by L. Peter Deutsch. Thanks to all the
|
|
||||||
people who reported problems and suggested various improvements in zlib; they
|
|
||||||
are too numerous to cite here.
|
|
||||||
|
|
||||||
|
|
||||||
Copyright notice:
|
|
||||||
|
|
||||||
(C) 1995-2012 Jean-loup Gailly and Mark Adler
|
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
|
||||||
warranty. In no event will the authors be held liable for any damages
|
|
||||||
arising from the use of this software.
|
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
|
||||||
including commercial applications, and to alter it and redistribute it
|
|
||||||
freely, subject to the following restrictions:
|
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
|
||||||
claim that you wrote the original software. If you use this software
|
|
||||||
in a product, an acknowledgment in the product documentation would be
|
|
||||||
appreciated but is not required.
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
|
||||||
misrepresented as being the original software.
|
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
|
||||||
|
|
||||||
Jean-loup Gailly Mark Adler
|
|
||||||
jloup@gzip.org madler@alumni.caltech.edu
|
|
||||||
|
|
||||||
If you use the zlib library in a product, we would appreciate *not* receiving
|
|
||||||
lengthy legal documents to sign. The sources are provided for free but without
|
|
||||||
warranty of any kind. The library has been entirely written by Jean-loup
|
|
||||||
Gailly and Mark Adler; it does not include third-party code.
|
|
||||||
|
|
||||||
If you redistribute modified sources, we would appreciate that you include in
|
|
||||||
the file ChangeLog history information documenting your changes. Please read
|
|
||||||
the FAQ for more information on the distribution of modified source versions.
|
|
@ -1,3 +0,0 @@
|
|||||||
|
|
||||||
To build zlib using the Microsoft Visual C++ environment,
|
|
||||||
use the appropriate project from the projects/ directory.
|
|
@ -1,55 +0,0 @@
|
|||||||
; zlib data compression library
|
|
||||||
EXPORTS
|
|
||||||
; basic functions
|
|
||||||
zlibVersion
|
|
||||||
deflate
|
|
||||||
deflateEnd
|
|
||||||
inflate
|
|
||||||
inflateEnd
|
|
||||||
; advanced functions
|
|
||||||
deflateSetDictionary
|
|
||||||
deflateCopy
|
|
||||||
deflateReset
|
|
||||||
deflateParams
|
|
||||||
deflateTune
|
|
||||||
deflateBound
|
|
||||||
deflatePending
|
|
||||||
deflatePrime
|
|
||||||
deflateSetHeader
|
|
||||||
inflateSetDictionary
|
|
||||||
inflateGetDictionary
|
|
||||||
inflateSync
|
|
||||||
inflateCopy
|
|
||||||
inflateReset
|
|
||||||
inflateReset2
|
|
||||||
inflatePrime
|
|
||||||
inflateMark
|
|
||||||
inflateGetHeader
|
|
||||||
inflateBack
|
|
||||||
inflateBackEnd
|
|
||||||
zlibCompileFlags
|
|
||||||
; utility functions
|
|
||||||
compress
|
|
||||||
compress2
|
|
||||||
compressBound
|
|
||||||
uncompress
|
|
||||||
; large file functions
|
|
||||||
adler32_combine64
|
|
||||||
crc32_combine64
|
|
||||||
; checksum functions
|
|
||||||
adler32
|
|
||||||
crc32
|
|
||||||
adler32_combine
|
|
||||||
crc32_combine
|
|
||||||
; various hacks, don't look :)
|
|
||||||
deflateInit_
|
|
||||||
deflateInit2_
|
|
||||||
inflateInit_
|
|
||||||
inflateInit2_
|
|
||||||
inflateBackInit_
|
|
||||||
zError
|
|
||||||
inflateSyncPoint
|
|
||||||
get_crc_table
|
|
||||||
inflateUndermine
|
|
||||||
inflateResetKeep
|
|
||||||
deflateResetKeep
|
|
@ -1,40 +0,0 @@
|
|||||||
#include <winver.h>
|
|
||||||
#include "../zlib.h"
|
|
||||||
|
|
||||||
#ifdef GCC_WINDRES
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
|
||||||
#else
|
|
||||||
VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
|
|
||||||
#endif
|
|
||||||
FILEVERSION ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0
|
|
||||||
PRODUCTVERSION ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0
|
|
||||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
|
||||||
#ifdef _DEBUG
|
|
||||||
FILEFLAGS 1
|
|
||||||
#else
|
|
||||||
FILEFLAGS 0
|
|
||||||
#endif
|
|
||||||
FILEOS VOS__WINDOWS32
|
|
||||||
FILETYPE VFT_DLL
|
|
||||||
FILESUBTYPE 0 // not used
|
|
||||||
BEGIN
|
|
||||||
BLOCK "StringFileInfo"
|
|
||||||
BEGIN
|
|
||||||
BLOCK "040904E4"
|
|
||||||
//language ID = U.S. English, char set = Windows, Multilingual
|
|
||||||
BEGIN
|
|
||||||
VALUE "FileDescription", "zlib data compression library\0"
|
|
||||||
VALUE "FileVersion", ZLIB_VERSION "\0"
|
|
||||||
VALUE "InternalName", "zlib1.dll\0"
|
|
||||||
VALUE "LegalCopyright", "(C) 1995-2013 Jean-loup Gailly & Mark Adler\0"
|
|
||||||
VALUE "OriginalFilename", "zlib1.dll\0"
|
|
||||||
VALUE "ProductName", "zlib\0"
|
|
||||||
VALUE "ProductVersion", ZLIB_VERSION "\0"
|
|
||||||
VALUE "Comments", "For more information visit http://www.zlib.net/\0"
|
|
||||||
END
|
|
||||||
END
|
|
||||||
BLOCK "VarFileInfo"
|
|
||||||
BEGIN
|
|
||||||
VALUE "Translation", 0x0409, 1252
|
|
||||||
END
|
|
||||||
END
|
|
@ -1,86 +0,0 @@
|
|||||||
; zlib data compression library
|
|
||||||
EXPORTS
|
|
||||||
; basic functions
|
|
||||||
zlibVersion
|
|
||||||
deflate
|
|
||||||
deflateEnd
|
|
||||||
inflate
|
|
||||||
inflateEnd
|
|
||||||
; advanced functions
|
|
||||||
deflateSetDictionary
|
|
||||||
deflateCopy
|
|
||||||
deflateReset
|
|
||||||
deflateParams
|
|
||||||
deflateTune
|
|
||||||
deflateBound
|
|
||||||
deflatePending
|
|
||||||
deflatePrime
|
|
||||||
deflateSetHeader
|
|
||||||
inflateSetDictionary
|
|
||||||
inflateGetDictionary
|
|
||||||
inflateSync
|
|
||||||
inflateCopy
|
|
||||||
inflateReset
|
|
||||||
inflateReset2
|
|
||||||
inflatePrime
|
|
||||||
inflateMark
|
|
||||||
inflateGetHeader
|
|
||||||
inflateBack
|
|
||||||
inflateBackEnd
|
|
||||||
zlibCompileFlags
|
|
||||||
; utility functions
|
|
||||||
compress
|
|
||||||
compress2
|
|
||||||
compressBound
|
|
||||||
uncompress
|
|
||||||
gzopen
|
|
||||||
gzdopen
|
|
||||||
gzbuffer
|
|
||||||
gzsetparams
|
|
||||||
gzread
|
|
||||||
gzwrite
|
|
||||||
gzprintf
|
|
||||||
gzvprintf
|
|
||||||
gzputs
|
|
||||||
gzgets
|
|
||||||
gzputc
|
|
||||||
gzgetc
|
|
||||||
gzungetc
|
|
||||||
gzflush
|
|
||||||
gzseek
|
|
||||||
gzrewind
|
|
||||||
gztell
|
|
||||||
gzoffset
|
|
||||||
gzeof
|
|
||||||
gzdirect
|
|
||||||
gzclose
|
|
||||||
gzclose_r
|
|
||||||
gzclose_w
|
|
||||||
gzerror
|
|
||||||
gzclearerr
|
|
||||||
; large file functions
|
|
||||||
gzopen64
|
|
||||||
gzseek64
|
|
||||||
gztell64
|
|
||||||
gzoffset64
|
|
||||||
adler32_combine64
|
|
||||||
crc32_combine64
|
|
||||||
; checksum functions
|
|
||||||
adler32
|
|
||||||
crc32
|
|
||||||
adler32_combine
|
|
||||||
crc32_combine
|
|
||||||
; various hacks, don't look :)
|
|
||||||
deflateInit_
|
|
||||||
deflateInit2_
|
|
||||||
inflateInit_
|
|
||||||
inflateInit2_
|
|
||||||
inflateBackInit_
|
|
||||||
gzgetc_
|
|
||||||
zError
|
|
||||||
inflateSyncPoint
|
|
||||||
get_crc_table
|
|
||||||
inflateUndermine
|
|
||||||
inflateResetKeep
|
|
||||||
deflateResetKeep
|
|
||||||
gzopen_w
|
|
@ -1,176 +0,0 @@
|
|||||||
/* zconf.h -- configuration of the zlib compression library
|
|
||||||
* Copyright (C) 1995-2013 Jean-loup Gailly.
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* @(#) $Id$ */
|
|
||||||
|
|
||||||
#ifndef ZCONF_H
|
|
||||||
#define ZCONF_H
|
|
||||||
|
|
||||||
#if defined(_WINDOWS) && !defined(WINDOWS)
|
|
||||||
# define WINDOWS
|
|
||||||
#endif
|
|
||||||
#if defined(_WIN32) || defined(__WIN32__)
|
|
||||||
# ifndef WIN32
|
|
||||||
# define WIN32
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __STDC_VERSION__
|
|
||||||
# if __STDC_VERSION__ >= 199901L
|
|
||||||
# ifndef STDC99
|
|
||||||
# define STDC99
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Maximum value for memLevel in deflateInit2 */
|
|
||||||
#ifndef MAX_MEM_LEVEL
|
|
||||||
# define MAX_MEM_LEVEL 9
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Maximum value for windowBits in deflateInit2 and inflateInit2.
|
|
||||||
* WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
|
|
||||||
* created by gzip. (Files created by minigzip can still be extracted by
|
|
||||||
* gzip.)
|
|
||||||
*/
|
|
||||||
#ifndef MAX_WBITS
|
|
||||||
# define MAX_WBITS 15 /* 32K LZ77 window */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The memory requirements for deflate are (in bytes):
|
|
||||||
(1 << (windowBits+2)) + (1 << (memLevel+9))
|
|
||||||
that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
|
|
||||||
plus a few kilobytes for small objects. For example, if you want to reduce
|
|
||||||
the default memory requirements from 256K to 128K, compile with
|
|
||||||
make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
|
|
||||||
Of course this will generally degrade compression (there's no free lunch).
|
|
||||||
|
|
||||||
The memory requirements for inflate are (in bytes) 1 << windowBits
|
|
||||||
that is, 32K for windowBits=15 (default value) plus a few kilobytes
|
|
||||||
for small objects.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Type declarations */
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(WINDOWS) || defined(WIN32)
|
|
||||||
/* If building or using zlib as a DLL, define ZLIB_DLL.
|
|
||||||
* This is not mandatory, but it offers a little performance increase.
|
|
||||||
*/
|
|
||||||
# ifdef ZLIB_DLL
|
|
||||||
# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
|
|
||||||
# ifdef ZLIB_INTERNAL
|
|
||||||
# define ZEXTERN extern __declspec(dllexport)
|
|
||||||
# else
|
|
||||||
# define ZEXTERN extern __declspec(dllimport)
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
# endif /* ZLIB_DLL */
|
|
||||||
/* If building or using zlib with the WINAPI/WINAPIV calling convention,
|
|
||||||
* define ZLIB_WINAPI.
|
|
||||||
* Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
|
|
||||||
*/
|
|
||||||
# ifdef ZLIB_WINAPI
|
|
||||||
# include <windows.h>
|
|
||||||
/* No need for _export, use ZLIB.DEF instead. */
|
|
||||||
/* For complete Windows compatibility, use WINAPI, not __stdcall. */
|
|
||||||
# define ZEXPORT WINAPI
|
|
||||||
# define ZEXPORTVA WINAPIV
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ZEXTERN
|
|
||||||
# define ZEXTERN extern
|
|
||||||
#endif
|
|
||||||
#ifndef ZEXPORT
|
|
||||||
# define ZEXPORT
|
|
||||||
#endif
|
|
||||||
#ifndef ZEXPORTVA
|
|
||||||
# define ZEXPORTVA
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Fallback for something that includes us. */
|
|
||||||
typedef unsigned char Byte;
|
|
||||||
typedef Byte Bytef;
|
|
||||||
|
|
||||||
typedef unsigned int uInt; /* 16 bits or more */
|
|
||||||
typedef unsigned long uLong; /* 32 bits or more */
|
|
||||||
|
|
||||||
typedef char charf;
|
|
||||||
typedef int intf;
|
|
||||||
typedef uInt uIntf;
|
|
||||||
typedef uLong uLongf;
|
|
||||||
|
|
||||||
typedef void const *voidpc;
|
|
||||||
typedef void *voidpf;
|
|
||||||
typedef void *voidp;
|
|
||||||
|
|
||||||
#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
|
|
||||||
# define Z_HAVE_UNISTD_H
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */
|
|
||||||
# define Z_HAVE_STDARG_H
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/types.h> /* for off_t */
|
|
||||||
#include <stdarg.h> /* for va_list */
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
# include <stddef.h> /* for wchar_t */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
|
|
||||||
* "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
|
|
||||||
* though the former does not conform to the LFS document), but considering
|
|
||||||
* both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
|
|
||||||
* equivalently requesting no 64-bit operations
|
|
||||||
*/
|
|
||||||
#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
|
|
||||||
# undef _LARGEFILE64_SOURCE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
|
|
||||||
# include <unistd.h> /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
|
|
||||||
# ifndef z_off_t
|
|
||||||
# define z_off_t off_t
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
|
|
||||||
# define Z_LFS64
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
|
|
||||||
# define Z_LARGE64
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
|
|
||||||
# define Z_WANT64
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(SEEK_SET) && defined(WITH_GZFILEOP)
|
|
||||||
# define SEEK_SET 0 /* Seek from beginning of file. */
|
|
||||||
# define SEEK_CUR 1 /* Seek from current position. */
|
|
||||||
# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef z_off_t
|
|
||||||
# define z_off_t long
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(WIN32) && defined(Z_LARGE64)
|
|
||||||
# define z_off64_t off64_t
|
|
||||||
#else
|
|
||||||
# if defined(__MSYS__)
|
|
||||||
# define z_off64_t _off64_t
|
|
||||||
# elif defined(WIN32) && !defined(__GNUC__)
|
|
||||||
# define z_off64_t __int64
|
|
||||||
# else
|
|
||||||
# define z_off64_t z_off_t
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* ZCONF_H */
|
|
@ -1,169 +0,0 @@
|
|||||||
.TH ZLIB 3 "7 July 2015"
|
|
||||||
.SH NAME
|
|
||||||
zlib \- compression/decompression library
|
|
||||||
.SH SYNOPSIS
|
|
||||||
[see
|
|
||||||
.I zlib.h
|
|
||||||
for full description]
|
|
||||||
.SH DESCRIPTION
|
|
||||||
The
|
|
||||||
.I zlib
|
|
||||||
library is a general purpose data compression library.
|
|
||||||
The code is thread safe, assuming that the standard library functions
|
|
||||||
used are thread safe, such as memory allocation routines.
|
|
||||||
It provides in-memory compression and decompression functions,
|
|
||||||
including integrity checks of the uncompressed data.
|
|
||||||
This version of the library supports only one compression method (deflation)
|
|
||||||
but other algorithms may be added later
|
|
||||||
with the same stream interface.
|
|
||||||
.LP
|
|
||||||
Compression can be done in a single step if the buffers are large enough
|
|
||||||
or can be done by repeated calls of the compression function.
|
|
||||||
In the latter case,
|
|
||||||
the application must provide more input and/or consume the output
|
|
||||||
(providing more output space) before each call.
|
|
||||||
.LP
|
|
||||||
The library also supports reading and writing files in
|
|
||||||
.IR gzip (1)
|
|
||||||
(.gz) format
|
|
||||||
with an interface similar to that of stdio.
|
|
||||||
.LP
|
|
||||||
The library does not install any signal handler.
|
|
||||||
The decoder checks the consistency of the compressed data,
|
|
||||||
so the library should never crash even in the case of corrupted input.
|
|
||||||
.LP
|
|
||||||
All functions of the compression library are documented in the file
|
|
||||||
.IR zlib.h .
|
|
||||||
The distribution source includes examples of use of the library
|
|
||||||
in the files
|
|
||||||
.I test/example.c
|
|
||||||
and
|
|
||||||
.IR test/minigzip.c,
|
|
||||||
as well as other examples in the
|
|
||||||
.IR examples/
|
|
||||||
directory.
|
|
||||||
.LP
|
|
||||||
Changes to this version are documented in the file
|
|
||||||
.I ChangeLog
|
|
||||||
that accompanies the source.
|
|
||||||
.LP
|
|
||||||
.I zlib
|
|
||||||
is available in Java using the java.util.zip package:
|
|
||||||
.IP
|
|
||||||
http://java.sun.com/developer/technicalArticles/Programming/compression/
|
|
||||||
.LP
|
|
||||||
A Perl interface to
|
|
||||||
.IR zlib ,
|
|
||||||
written by Paul Marquess (pmqs@cpan.org),
|
|
||||||
is available at CPAN (Comprehensive Perl Archive Network) sites,
|
|
||||||
including:
|
|
||||||
.IP
|
|
||||||
http://search.cpan.org/~pmqs/IO-Compress-Zlib/
|
|
||||||
.LP
|
|
||||||
A Python interface to
|
|
||||||
.IR zlib ,
|
|
||||||
written by A.M. Kuchling (amk@magnet.com),
|
|
||||||
is available in Python 1.5 and later versions:
|
|
||||||
.IP
|
|
||||||
http://docs.python.org/library/zlib.html
|
|
||||||
.LP
|
|
||||||
.I zlib
|
|
||||||
is built into
|
|
||||||
.IR tcl:
|
|
||||||
.IP
|
|
||||||
http://wiki.tcl.tk/4610
|
|
||||||
.LP
|
|
||||||
An experimental package to read and write files in .zip format,
|
|
||||||
written on top of
|
|
||||||
.I zlib
|
|
||||||
by Gilles Vollant (info@winimage.com),
|
|
||||||
is available at:
|
|
||||||
.IP
|
|
||||||
http://www.winimage.com/zLibDll/minizip.html
|
|
||||||
and also in the
|
|
||||||
.I contrib/minizip
|
|
||||||
directory of the main
|
|
||||||
.I zlib
|
|
||||||
source distribution.
|
|
||||||
.SH "SEE ALSO"
|
|
||||||
The
|
|
||||||
.I zlib
|
|
||||||
web site can be found at:
|
|
||||||
.IP
|
|
||||||
http://zlib.net/
|
|
||||||
.LP
|
|
||||||
The data format used by the zlib library is described by RFC
|
|
||||||
(Request for Comments) 1950 to 1952 in the files:
|
|
||||||
.IP
|
|
||||||
http://tools.ietf.org/html/rfc1950 (for the zlib header and trailer format)
|
|
||||||
.br
|
|
||||||
http://tools.ietf.org/html/rfc1951 (for the deflate compressed data format)
|
|
||||||
.br
|
|
||||||
http://tools.ietf.org/html/rfc1952 (for the gzip header and trailer format)
|
|
||||||
.LP
|
|
||||||
Mark Nelson wrote an article about
|
|
||||||
.I zlib
|
|
||||||
for the Jan. 1997 issue of Dr. Dobb's Journal;
|
|
||||||
a copy of the article is available at:
|
|
||||||
.IP
|
|
||||||
http://marknelson.us/1997/01/01/zlib-engine/
|
|
||||||
.SH "REPORTING PROBLEMS"
|
|
||||||
Before reporting a problem,
|
|
||||||
please check the
|
|
||||||
.I zlib
|
|
||||||
web site to verify that you have the latest version of
|
|
||||||
.IR zlib ;
|
|
||||||
otherwise,
|
|
||||||
obtain the latest version and see if the problem still exists.
|
|
||||||
Please read the
|
|
||||||
.I zlib
|
|
||||||
FAQ at:
|
|
||||||
.IP
|
|
||||||
http://zlib.net/zlib_faq.html
|
|
||||||
.LP
|
|
||||||
before asking for help.
|
|
||||||
Send questions and/or comments to zlib@gzip.org,
|
|
||||||
or (for the Windows DLL version) to Gilles Vollant (info@winimage.com).
|
|
||||||
.SH AUTHORS AND LICENSE
|
|
||||||
Version 1.2.8.1
|
|
||||||
.LP
|
|
||||||
Copyright (C) 1995-2015 Jean-loup Gailly and Mark Adler
|
|
||||||
.LP
|
|
||||||
This software is provided 'as-is', without any express or implied
|
|
||||||
warranty. In no event will the authors be held liable for any damages
|
|
||||||
arising from the use of this software.
|
|
||||||
.LP
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
|
||||||
including commercial applications, and to alter it and redistribute it
|
|
||||||
freely, subject to the following restrictions:
|
|
||||||
.LP
|
|
||||||
.nr step 1 1
|
|
||||||
.IP \n[step]. 3
|
|
||||||
The origin of this software must not be misrepresented; you must not
|
|
||||||
claim that you wrote the original software. If you use this software
|
|
||||||
in a product, an acknowledgment in the product documentation would be
|
|
||||||
appreciated but is not required.
|
|
||||||
.IP \n+[step].
|
|
||||||
Altered source versions must be plainly marked as such, and must not be
|
|
||||||
misrepresented as being the original software.
|
|
||||||
.IP \n+[step].
|
|
||||||
This notice may not be removed or altered from any source distribution.
|
|
||||||
.LP
|
|
||||||
Jean-loup Gailly Mark Adler
|
|
||||||
.br
|
|
||||||
jloup@gzip.org madler@alumni.caltech.edu
|
|
||||||
.LP
|
|
||||||
The deflate format used by
|
|
||||||
.I zlib
|
|
||||||
was defined by Phil Katz.
|
|
||||||
The deflate and
|
|
||||||
.I zlib
|
|
||||||
specifications were written by L. Peter Deutsch.
|
|
||||||
Thanks to all the people who reported problems and suggested various
|
|
||||||
improvements in
|
|
||||||
.IR zlib ;
|
|
||||||
who are too numerous to cite here.
|
|
||||||
.LP
|
|
||||||
UNIX manual page by R. P. C. Rodgers,
|
|
||||||
U.S. National Library of Medicine (rodgers@nlm.nih.gov).
|
|
||||||
.\" end of man page
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -1,83 +0,0 @@
|
|||||||
ZLIB_1.2.0 {
|
|
||||||
global:
|
|
||||||
compressBound;
|
|
||||||
deflateBound;
|
|
||||||
inflateBack;
|
|
||||||
inflateBackEnd;
|
|
||||||
inflateBackInit_;
|
|
||||||
inflateCopy;
|
|
||||||
local:
|
|
||||||
deflate_copyright;
|
|
||||||
inflate_copyright;
|
|
||||||
inflate_fast;
|
|
||||||
inflate_table;
|
|
||||||
zcalloc;
|
|
||||||
zcfree;
|
|
||||||
z_errmsg;
|
|
||||||
gz_error;
|
|
||||||
gz_intmax;
|
|
||||||
_*;
|
|
||||||
};
|
|
||||||
|
|
||||||
ZLIB_1.2.0.2 {
|
|
||||||
gzclearerr;
|
|
||||||
gzungetc;
|
|
||||||
zlibCompileFlags;
|
|
||||||
} ZLIB_1.2.0;
|
|
||||||
|
|
||||||
ZLIB_1.2.0.8 {
|
|
||||||
deflatePrime;
|
|
||||||
} ZLIB_1.2.0.2;
|
|
||||||
|
|
||||||
ZLIB_1.2.2 {
|
|
||||||
adler32_combine;
|
|
||||||
crc32_combine;
|
|
||||||
deflateSetHeader;
|
|
||||||
inflateGetHeader;
|
|
||||||
} ZLIB_1.2.0.8;
|
|
||||||
|
|
||||||
ZLIB_1.2.2.3 {
|
|
||||||
deflateTune;
|
|
||||||
gzdirect;
|
|
||||||
} ZLIB_1.2.2;
|
|
||||||
|
|
||||||
ZLIB_1.2.2.4 {
|
|
||||||
inflatePrime;
|
|
||||||
} ZLIB_1.2.2.3;
|
|
||||||
|
|
||||||
ZLIB_1.2.3.3 {
|
|
||||||
adler32_combine64;
|
|
||||||
crc32_combine64;
|
|
||||||
gzopen64;
|
|
||||||
gzseek64;
|
|
||||||
gztell64;
|
|
||||||
inflateUndermine;
|
|
||||||
} ZLIB_1.2.2.4;
|
|
||||||
|
|
||||||
ZLIB_1.2.3.4 {
|
|
||||||
inflateReset2;
|
|
||||||
inflateMark;
|
|
||||||
} ZLIB_1.2.3.3;
|
|
||||||
|
|
||||||
ZLIB_1.2.3.5 {
|
|
||||||
gzbuffer;
|
|
||||||
gzoffset;
|
|
||||||
gzoffset64;
|
|
||||||
gzclose_r;
|
|
||||||
gzclose_w;
|
|
||||||
} ZLIB_1.2.3.4;
|
|
||||||
|
|
||||||
ZLIB_1.2.5.1 {
|
|
||||||
deflatePending;
|
|
||||||
} ZLIB_1.2.3.5;
|
|
||||||
|
|
||||||
ZLIB_1.2.5.2 {
|
|
||||||
deflateResetKeep;
|
|
||||||
gzgetc_;
|
|
||||||
inflateResetKeep;
|
|
||||||
} ZLIB_1.2.5.1;
|
|
||||||
|
|
||||||
ZLIB_1.2.7.1 {
|
|
||||||
inflateGetDictionary;
|
|
||||||
gzvprintf;
|
|
||||||
} ZLIB_1.2.5.2;
|
|
@ -1,13 +0,0 @@
|
|||||||
prefix=@CMAKE_INSTALL_PREFIX@
|
|
||||||
exec_prefix=@CMAKE_INSTALL_PREFIX@
|
|
||||||
libdir=@INSTALL_LIB_DIR@
|
|
||||||
sharedlibdir=@INSTALL_LIB_DIR@
|
|
||||||
includedir=@INSTALL_INC_DIR@
|
|
||||||
|
|
||||||
Name: zlib
|
|
||||||
Description: zlib compression library
|
|
||||||
Version: @VERSION@
|
|
||||||
|
|
||||||
Requires:
|
|
||||||
Libs: -L${libdir} -L${sharedlibdir} -lz
|
|
||||||
Cflags: -I${includedir}
|
|
@ -1,13 +0,0 @@
|
|||||||
prefix=@prefix@
|
|
||||||
exec_prefix=@exec_prefix@
|
|
||||||
libdir=@libdir@
|
|
||||||
sharedlibdir=@sharedlibdir@
|
|
||||||
includedir=@includedir@
|
|
||||||
|
|
||||||
Name: zlib
|
|
||||||
Description: zlib compression library
|
|
||||||
Version: @VERSION@
|
|
||||||
|
|
||||||
Requires:
|
|
||||||
Libs: -L${libdir} -L${sharedlibdir} -lz
|
|
||||||
Cflags: -I${includedir}
|
|
@ -1,124 +0,0 @@
|
|||||||
/* zutil.c -- target dependent utility functions for the compression library
|
|
||||||
* Copyright (C) 1995-2005, 2010, 2011, 2012 Jean-loup Gailly.
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* @(#) $Id$ */
|
|
||||||
|
|
||||||
#include "zutil.h"
|
|
||||||
#ifdef WITH_GZFILEOP
|
|
||||||
# include "gzguts.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const char * const z_errmsg[10] = {
|
|
||||||
"need dictionary", /* Z_NEED_DICT 2 */
|
|
||||||
"stream end", /* Z_STREAM_END 1 */
|
|
||||||
"", /* Z_OK 0 */
|
|
||||||
"file error", /* Z_ERRNO (-1) */
|
|
||||||
"stream error", /* Z_STREAM_ERROR (-2) */
|
|
||||||
"data error", /* Z_DATA_ERROR (-3) */
|
|
||||||
"insufficient memory", /* Z_MEM_ERROR (-4) */
|
|
||||||
"buffer error", /* Z_BUF_ERROR (-5) */
|
|
||||||
"incompatible version",/* Z_VERSION_ERROR (-6) */
|
|
||||||
""};
|
|
||||||
|
|
||||||
const char zlibng_string[] =
|
|
||||||
" zlib-ng 1.9.9 forked from zlib 1.2.8 ";
|
|
||||||
|
|
||||||
const char * ZEXPORT zlibVersion(void)
|
|
||||||
{
|
|
||||||
return ZLIB_VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long ZEXPORT zlibCompileFlags(void)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
flags = 0;
|
|
||||||
switch ((int)(sizeof(unsigned int))) {
|
|
||||||
case 2: break;
|
|
||||||
case 4: flags += 1; break;
|
|
||||||
case 8: flags += 2; break;
|
|
||||||
default: flags += 3;
|
|
||||||
}
|
|
||||||
switch ((int)(sizeof(unsigned long))) {
|
|
||||||
case 2: break;
|
|
||||||
case 4: flags += 1 << 2; break;
|
|
||||||
case 8: flags += 2 << 2; break;
|
|
||||||
default: flags += 3 << 2;
|
|
||||||
}
|
|
||||||
switch ((int)(sizeof(void *))) {
|
|
||||||
case 2: break;
|
|
||||||
case 4: flags += 1 << 4; break;
|
|
||||||
case 8: flags += 2 << 4; break;
|
|
||||||
default: flags += 3 << 4;
|
|
||||||
}
|
|
||||||
switch ((int)(sizeof(z_off_t))) {
|
|
||||||
case 2: break;
|
|
||||||
case 4: flags += 1 << 6; break;
|
|
||||||
case 8: flags += 2 << 6; break;
|
|
||||||
default: flags += 3 << 6;
|
|
||||||
}
|
|
||||||
#ifdef DEBUG
|
|
||||||
flags += 1 << 8;
|
|
||||||
#endif
|
|
||||||
#ifdef ZLIB_WINAPI
|
|
||||||
flags += 1 << 10;
|
|
||||||
#endif
|
|
||||||
#ifdef BUILDFIXED
|
|
||||||
flags += 1 << 12;
|
|
||||||
#endif
|
|
||||||
#ifdef DYNAMIC_CRC_TABLE
|
|
||||||
flags += 1 << 13;
|
|
||||||
#endif
|
|
||||||
#ifdef NO_GZCOMPRESS
|
|
||||||
flags += 1L << 16;
|
|
||||||
#endif
|
|
||||||
#ifdef NO_GZIP
|
|
||||||
flags += 1L << 17;
|
|
||||||
#endif
|
|
||||||
#ifdef PKZIP_BUG_WORKAROUND
|
|
||||||
flags += 1L << 20;
|
|
||||||
#endif
|
|
||||||
return flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
|
|
||||||
# ifndef verbose
|
|
||||||
# define verbose 0
|
|
||||||
# endif
|
|
||||||
int ZLIB_INTERNAL z_verbose = verbose;
|
|
||||||
|
|
||||||
void ZLIB_INTERNAL z_error (m)
|
|
||||||
char *m;
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s\n", m);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* exported to allow conversion of error code to string for compress() and
|
|
||||||
* uncompress()
|
|
||||||
*/
|
|
||||||
const char * ZEXPORT zError(int err)
|
|
||||||
{
|
|
||||||
return ERR_MSG(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef MY_ZCALLOC /* Any system without a special alloc function */
|
|
||||||
|
|
||||||
void ZLIB_INTERNAL *zcalloc (void *opaque, unsigned items, unsigned size)
|
|
||||||
{
|
|
||||||
(void)opaque;
|
|
||||||
return sizeof(unsigned int) > 2 ? (void *)malloc(items * size) :
|
|
||||||
(void *)calloc(items, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZLIB_INTERNAL zcfree (void *opaque, void *ptr)
|
|
||||||
{
|
|
||||||
(void)opaque;
|
|
||||||
free(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* MY_ZCALLOC */
|
|
@ -1,185 +0,0 @@
|
|||||||
#ifndef ZUTIL_H_
|
|
||||||
#define ZUTIL_H_
|
|
||||||
/* zutil.h -- internal interface and configuration of the compression library
|
|
||||||
* Copyright (C) 1995-2013 Jean-loup Gailly.
|
|
||||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* WARNING: this file should *not* be used by applications. It is
|
|
||||||
part of the implementation of the compression library and is
|
|
||||||
subject to change. Applications should only use zlib.h.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* @(#) $Id$ */
|
|
||||||
|
|
||||||
#if defined(HAVE_INTERNAL)
|
|
||||||
# define ZLIB_INTERNAL __attribute__((visibility ("internal")))
|
|
||||||
#elif defined(HAVE_HIDDEN)
|
|
||||||
# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
|
|
||||||
#else
|
|
||||||
# define ZLIB_INTERNAL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "zlib.h"
|
|
||||||
|
|
||||||
#ifndef local
|
|
||||||
# define local static
|
|
||||||
#endif
|
|
||||||
/* compile with -Dlocal if your debugger can't find static symbols */
|
|
||||||
|
|
||||||
typedef unsigned char uch; /* Included for compatibility with external code only */
|
|
||||||
typedef uint16_t ush; /* Included for compatibility with external code only */
|
|
||||||
typedef unsigned long ulg;
|
|
||||||
|
|
||||||
extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
|
||||||
/* (size given to avoid silly warnings with Visual C++) */
|
|
||||||
|
|
||||||
#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
|
|
||||||
|
|
||||||
#define ERR_RETURN(strm, err) return (strm->msg = ERR_MSG(err), (err))
|
|
||||||
/* To be used only when the state is known to be valid */
|
|
||||||
|
|
||||||
/* common constants */
|
|
||||||
|
|
||||||
#ifndef DEF_WBITS
|
|
||||||
# define DEF_WBITS MAX_WBITS
|
|
||||||
#endif
|
|
||||||
/* default windowBits for decompression. MAX_WBITS is for compression only */
|
|
||||||
|
|
||||||
#if MAX_MEM_LEVEL >= 8
|
|
||||||
# define DEF_MEM_LEVEL 8
|
|
||||||
#else
|
|
||||||
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
|
|
||||||
#endif
|
|
||||||
/* default memLevel */
|
|
||||||
|
|
||||||
#define STORED_BLOCK 0
|
|
||||||
#define STATIC_TREES 1
|
|
||||||
#define DYN_TREES 2
|
|
||||||
/* The three kinds of block type */
|
|
||||||
|
|
||||||
#define MIN_MATCH 3
|
|
||||||
#define MAX_MATCH 258
|
|
||||||
/* The minimum and maximum match lengths */
|
|
||||||
|
|
||||||
#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
|
|
||||||
|
|
||||||
/* target dependencies */
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */
|
|
||||||
# define OS_CODE 0x0b
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (defined(_MSC_VER) && (_MSC_VER > 600))
|
|
||||||
# define fdopen(fd, type) _fdopen(fd, type)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* provide prototypes for these when building zlib without LFS */
|
|
||||||
#if !defined(WIN32) && !defined(__MSYS__) && (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
|
|
||||||
ZEXTERN uint32_t ZEXPORT adler32_combine64(uint32_t, uint32_t, z_off_t);
|
|
||||||
ZEXTERN uint32_t ZEXPORT crc32_combine64(uint32_t, uint32_t, z_off_t);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* MS Visual Studio does not allow inline in C, only C++.
|
|
||||||
But it provides __inline instead, so use that. */
|
|
||||||
#if defined(_MSC_VER) && !defined(inline)
|
|
||||||
# define inline __inline
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* common defaults */
|
|
||||||
|
|
||||||
#ifndef OS_CODE
|
|
||||||
# define OS_CODE 0x03 /* assume Unix */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef F_OPEN
|
|
||||||
# define F_OPEN(name, mode) fopen((name), (mode))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* functions */
|
|
||||||
|
|
||||||
/* Diagnostic functions */
|
|
||||||
#ifdef DEBUG
|
|
||||||
# include <stdio.h>
|
|
||||||
extern int ZLIB_INTERNAL z_verbose;
|
|
||||||
extern void ZLIB_INTERNAL z_error(char *m);
|
|
||||||
# define Assert(cond, msg) {if(!(cond)) z_error(msg);}
|
|
||||||
# define Trace(x) {if (z_verbose >= 0) fprintf x;}
|
|
||||||
# define Tracev(x) {if (z_verbose > 0) fprintf x;}
|
|
||||||
# define Tracevv(x) {if (z_verbose > 1) fprintf x;}
|
|
||||||
# define Tracec(c, x) {if (z_verbose > 0 && (c)) fprintf x;}
|
|
||||||
# define Tracecv(c, x) {if (z_verbose > 1 && (c)) fprintf x;}
|
|
||||||
#else
|
|
||||||
# define Assert(cond, msg)
|
|
||||||
# define Trace(x)
|
|
||||||
# define Tracev(x)
|
|
||||||
# define Tracevv(x)
|
|
||||||
# define Tracec(c, x)
|
|
||||||
# define Tracecv(c, x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void ZLIB_INTERNAL *zcalloc(void *opaque, unsigned items, unsigned size);
|
|
||||||
void ZLIB_INTERNAL zcfree(void *opaque, void *ptr);
|
|
||||||
|
|
||||||
#define ZALLOC(strm, items, size) (*((strm)->zalloc))((strm)->opaque, (items), (size))
|
|
||||||
#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (void *)(addr))
|
|
||||||
#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
|
|
||||||
|
|
||||||
/* Reverse the bytes in a 32-bit value. Use compiler intrinsics when
|
|
||||||
possible to take advantage of hardware implementations. */
|
|
||||||
#if defined(WIN32) && (_MSC_VER >= 1300)
|
|
||||||
# pragma intrinsic(_byteswap_ulong)
|
|
||||||
# define ZSWAP32(q) _byteswap_ulong(q)
|
|
||||||
|
|
||||||
#elif defined(__Clang__) || (defined(__GNUC__) && \
|
|
||||||
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)))
|
|
||||||
# define ZSWAP32(q) __builtin_bswap32(q)
|
|
||||||
|
|
||||||
#elif defined(__GNUC__) && (__GNUC__ >= 2) && defined(__linux__)
|
|
||||||
# include <byteswap.h>
|
|
||||||
# define ZSWAP32(q) bswap_32(q)
|
|
||||||
|
|
||||||
#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
|
|
||||||
# include <sys/endian.h>
|
|
||||||
# define ZSWAP32(q) bswap32(q)
|
|
||||||
|
|
||||||
#elif defined(__INTEL_COMPILER)
|
|
||||||
# define ZSWAP32(q) _bswap(q)
|
|
||||||
|
|
||||||
#else
|
|
||||||
# define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
|
|
||||||
(((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
|
|
||||||
#endif /* ZSWAP32 */
|
|
||||||
|
|
||||||
/* Only enable likely/unlikely if the compiler is known to support it */
|
|
||||||
#if (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__INTEL_COMPILER) || defined(__Clang__)
|
|
||||||
# ifndef likely
|
|
||||||
# define likely(x) __builtin_expect(!!(x), 1)
|
|
||||||
# endif
|
|
||||||
# ifndef unlikely
|
|
||||||
# define unlikely(x) __builtin_expect(!!(x), 0)
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
# ifndef likely
|
|
||||||
# define likely(x) x
|
|
||||||
# endif
|
|
||||||
# ifndef unlikely
|
|
||||||
# define unlikely(x) x
|
|
||||||
# endif
|
|
||||||
#endif /* (un)likely */
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#define ALIGNED_(x) __declspec(align(x))
|
|
||||||
#else
|
|
||||||
#if defined(__GNUC__)
|
|
||||||
#define ALIGNED_(x) __attribute__ ((aligned(x)))
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* ZUTIL_H_ */
|
|
2
contrib/poco
vendored
2
contrib/poco
vendored
@ -1 +1 @@
|
|||||||
Subproject commit e30352c2c24eebecbd82d41f7054d908ac7fdc37
|
Subproject commit bcf9ebad48b2162d25f5fc432b176d74a09f498d
|
1
contrib/zlib-ng
vendored
Submodule
1
contrib/zlib-ng
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit e07a52dbaa35d003f5659b221b29d220c091667b
|
@ -36,7 +36,12 @@ set(dbms_headers)
|
|||||||
set(dbms_sources)
|
set(dbms_sources)
|
||||||
|
|
||||||
include(${ClickHouse_SOURCE_DIR}/cmake/dbms_glob_sources.cmake)
|
include(${ClickHouse_SOURCE_DIR}/cmake/dbms_glob_sources.cmake)
|
||||||
add_headers_and_sources(dbms src/Parsers)
|
|
||||||
|
add_headers_and_sources(clickhouse_common_io src/Common)
|
||||||
|
add_headers_and_sources(clickhouse_common_io src/Common/HashTable)
|
||||||
|
add_headers_and_sources(clickhouse_common_io src/Common/ZooKeeper)
|
||||||
|
add_headers_and_sources(clickhouse_common_io src/IO)
|
||||||
|
|
||||||
add_headers_and_sources(dbms src/Analyzers)
|
add_headers_and_sources(dbms src/Analyzers)
|
||||||
add_headers_and_sources(dbms src/Core)
|
add_headers_and_sources(dbms src/Core)
|
||||||
add_headers_and_sources(dbms src/DataStreams)
|
add_headers_and_sources(dbms src/DataStreams)
|
||||||
@ -46,20 +51,15 @@ add_headers_and_sources(dbms src/Dictionaries)
|
|||||||
add_headers_and_sources(dbms src/Dictionaries/Embedded)
|
add_headers_and_sources(dbms src/Dictionaries/Embedded)
|
||||||
add_headers_and_sources(dbms src/Interpreters)
|
add_headers_and_sources(dbms src/Interpreters)
|
||||||
add_headers_and_sources(dbms src/Interpreters/ClusterProxy)
|
add_headers_and_sources(dbms src/Interpreters/ClusterProxy)
|
||||||
add_headers_and_sources(dbms src/Common)
|
|
||||||
add_headers_and_sources(dbms src/Common/HashTable)
|
|
||||||
add_headers_and_sources(dbms src/Common/ZooKeeper)
|
|
||||||
add_headers_and_sources(dbms src/IO)
|
|
||||||
add_headers_and_sources(dbms src/Columns)
|
add_headers_and_sources(dbms src/Columns)
|
||||||
add_headers_and_sources(dbms src/Storages)
|
add_headers_and_sources(dbms src/Storages)
|
||||||
add_headers_and_sources(dbms src/Storages/Distributed)
|
add_headers_and_sources(dbms src/Storages/Distributed)
|
||||||
add_headers_and_sources(dbms src/Storages/MergeTree)
|
add_headers_and_sources(dbms src/Storages/MergeTree)
|
||||||
add_headers_and_sources(dbms src/Core)
|
|
||||||
add_headers_and_sources(dbms src/Client)
|
add_headers_and_sources(dbms src/Client)
|
||||||
add_headers_only(dbms src/Server)
|
add_headers_only(dbms src/Server)
|
||||||
|
|
||||||
list (APPEND dbms_sources ${CONFIG_BUILD})
|
list (APPEND clickhouse_common_io_sources ${CONFIG_BUILD})
|
||||||
list (APPEND dbms_headers ${CONFIG_VERSION} ${CONFIG_COMMON})
|
list (APPEND clickhouse_common_io_headers ${CONFIG_VERSION} ${CONFIG_COMMON})
|
||||||
|
|
||||||
list (APPEND dbms_sources src/Functions/IFunction.cpp src/Functions/FunctionFactory.cpp src/Functions/FunctionHelpers.cpp)
|
list (APPEND dbms_sources src/Functions/IFunction.cpp src/Functions/FunctionFactory.cpp src/Functions/FunctionHelpers.cpp)
|
||||||
list (APPEND dbms_headers src/Functions/IFunction.h src/Functions/FunctionFactory.h src/Functions/FunctionHelpers.h)
|
list (APPEND dbms_headers src/Functions/IFunction.h src/Functions/FunctionFactory.h src/Functions/FunctionHelpers.h)
|
||||||
@ -91,19 +91,23 @@ list (APPEND dbms_sources src/TableFunctions/TableFunctionFactory.cpp)
|
|||||||
list (APPEND dbms_headers src/TableFunctions/ITableFunction.h src/TableFunctions/TableFunctionFactory.h)
|
list (APPEND dbms_headers src/TableFunctions/ITableFunction.h src/TableFunctions/TableFunctionFactory.h)
|
||||||
|
|
||||||
|
|
||||||
list(REMOVE_ITEM dbms_sources
|
list(REMOVE_ITEM clickhouse_common_io_sources
|
||||||
src/Common/StringUtils.cpp)
|
src/Common/StringUtils.cpp)
|
||||||
|
list(REMOVE_ITEM clickhouse_common_io_headers
|
||||||
|
src/Common/StringUtils.h)
|
||||||
|
|
||||||
if (APPLE OR CMAKE_SYSTEM MATCHES "FreeBSD")
|
if (APPLE OR CMAKE_SYSTEM MATCHES "FreeBSD")
|
||||||
list(REMOVE_ITEM dbms_headers
|
list(REMOVE_ITEM clickhouse_common_io_headers
|
||||||
src/Common/AIO.h
|
src/Common/AIO.h
|
||||||
src/IO/WriteBufferAIO.h
|
src/IO/WriteBufferAIO.h
|
||||||
src/IO/ReadBufferAIO.h)
|
src/IO/ReadBufferAIO.h)
|
||||||
list(REMOVE_ITEM dbms_sources
|
list(REMOVE_ITEM clickhouse_common_io_sources
|
||||||
src/IO/ReadBufferAIO.cpp
|
src/IO/ReadBufferAIO.cpp
|
||||||
src/IO/WriteBufferAIO.cpp)
|
src/IO/WriteBufferAIO.cpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
add_library(clickhouse_common_io ${SPLIT_SHARED} ${clickhouse_common_io_headers} ${clickhouse_common_io_sources})
|
||||||
|
|
||||||
if (MAKE_STATIC_LIBRARIES)
|
if (MAKE_STATIC_LIBRARIES)
|
||||||
add_library(dbms ${dbms_headers} ${dbms_sources})
|
add_library(dbms ${dbms_headers} ${dbms_sources})
|
||||||
else ()
|
else ()
|
||||||
@ -144,18 +148,24 @@ else()
|
|||||||
set(PLATFORM_LIBS "")
|
set(PLATFORM_LIBS "")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries (dbms
|
target_link_libraries (clickhouse_common_io
|
||||||
common
|
common
|
||||||
${MYSQLXX_LIBRARY}
|
string_utils
|
||||||
${FARMHASH_LIBRARIES}
|
${LINK_LIBRARIES_ONLY_ON_X86_64}
|
||||||
${METROHASH_LIBRARIES}
|
|
||||||
${LZ4_LIBRARY}
|
${LZ4_LIBRARY}
|
||||||
${ZSTD_LIBRARY}
|
${ZSTD_LIBRARY}
|
||||||
${ZOOKEEPER_LIBRARY}
|
${ZOOKEEPER_LIBRARY}
|
||||||
string_utils
|
|
||||||
${DOUBLE_CONVERSION_LIBRARIES}
|
${DOUBLE_CONVERSION_LIBRARIES}
|
||||||
|
${Poco_Net_LIBRARY}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries (dbms
|
||||||
|
clickhouse_common_io
|
||||||
|
clickhouse_parsers
|
||||||
|
${MYSQLXX_LIBRARY}
|
||||||
|
${FARMHASH_LIBRARIES}
|
||||||
|
${METROHASH_LIBRARIES}
|
||||||
${ZLIB_LIBRARIES}
|
${ZLIB_LIBRARIES}
|
||||||
${LINK_LIBRARIES_ONLY_ON_X86_64}
|
|
||||||
${RE2_LIBRARY}
|
${RE2_LIBRARY}
|
||||||
${RE2_ST_LIBRARY}
|
${RE2_ST_LIBRARY}
|
||||||
${OPENSSL_CRYPTO_LIBRARY}
|
${OPENSSL_CRYPTO_LIBRARY}
|
||||||
@ -173,7 +183,7 @@ if (Poco_MongoDB_FOUND)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (Poco_NetSSL_FOUND)
|
if (Poco_NetSSL_FOUND)
|
||||||
target_link_libraries (dbms ${Poco_NetSSL_LIBRARY})
|
target_link_libraries (clickhouse_common_io ${Poco_NetSSL_LIBRARY})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries (dbms ${Poco_Foundation_LIBRARY})
|
target_link_libraries (dbms ${Poco_Foundation_LIBRARY})
|
||||||
@ -203,16 +213,16 @@ if (NOT USE_INTERNAL_ZSTD_LIBRARY)
|
|||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
target_include_directories (dbms PUBLIC ${DBMS_INCLUDE_DIR})
|
target_include_directories (dbms PUBLIC ${DBMS_INCLUDE_DIR})
|
||||||
target_include_directories (dbms PUBLIC ${PCG_RANDOM_INCLUDE_DIR})
|
target_include_directories (clickhouse_common_io PUBLIC ${DBMS_INCLUDE_DIR})
|
||||||
|
target_include_directories (clickhouse_common_io PUBLIC ${PCG_RANDOM_INCLUDE_DIR})
|
||||||
|
target_include_directories (clickhouse_common_io BEFORE PUBLIC ${DOUBLE_CONVERSION_INCLUDE_DIR})
|
||||||
|
|
||||||
if (USE_RDKAFKA)
|
if (USE_RDKAFKA)
|
||||||
target_link_libraries (dbms ${RDKAFKA_LIBRARY})
|
target_link_libraries (dbms ${RDKAFKA_LIBRARY})
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# only for copy_headers.sh:
|
# also for copy_headers.sh:
|
||||||
target_include_directories (dbms BEFORE PRIVATE ${COMMON_INCLUDE_DIR})
|
target_include_directories (clickhouse_common_io BEFORE PRIVATE ${COMMON_INCLUDE_DIR})
|
||||||
target_include_directories (dbms BEFORE PRIVATE ${DOUBLE_CONVERSION_INCLUDE_DIR})
|
|
||||||
|
|
||||||
|
|
||||||
if (ENABLE_TESTS)
|
if (ENABLE_TESTS)
|
||||||
add_subdirectory (tests)
|
add_subdirectory (tests)
|
||||||
|
@ -26,6 +26,6 @@ list(REMOVE_ITEM clickhouse_aggregate_functions_headers
|
|||||||
parseAggregateFunctionParameters.h
|
parseAggregateFunctionParameters.h
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(clickhouse_aggregate_functions ${clickhouse_aggregate_functions_sources})
|
add_library(clickhouse_aggregate_functions ${SPLIT_SHARED} ${clickhouse_aggregate_functions_sources})
|
||||||
target_link_libraries(clickhouse_aggregate_functions dbms)
|
target_link_libraries(clickhouse_aggregate_functions dbms)
|
||||||
target_include_directories (clickhouse_aggregate_functions BEFORE PRIVATE ${COMMON_INCLUDE_DIR})
|
target_include_directories (clickhouse_aggregate_functions BEFORE PRIVATE ${COMMON_INCLUDE_DIR})
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include <Common/Collator.h>
|
#include <Columns/Collator.h>
|
||||||
|
|
||||||
#include <Common/config.h>
|
#include <Common/config.h>
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
#include <Core/Defines.h>
|
#include <Core/Defines.h>
|
||||||
|
|
||||||
#include <Common/Collator.h>
|
#include <Columns/Collator.h>
|
||||||
#include <Columns/ColumnString.h>
|
#include <Columns/ColumnString.h>
|
||||||
#include <Columns/ColumnsCommon.h>
|
#include <Columns/ColumnsCommon.h>
|
||||||
#include <DataStreams/ColumnGathererStream.h>
|
#include <DataStreams/ColumnGathererStream.h>
|
||||||
|
@ -57,7 +57,7 @@ void * Allocator<clear_memory_>::alloc(size_t size, size_t alignment)
|
|||||||
if (size >= MMAP_THRESHOLD)
|
if (size >= MMAP_THRESHOLD)
|
||||||
{
|
{
|
||||||
if (alignment > MMAP_MIN_ALIGNMENT)
|
if (alignment > MMAP_MIN_ALIGNMENT)
|
||||||
throw DB::Exception("Too large alignment " + formatReadableSizeWithBinarySuffix(alignment) + ": more than page size when allocating "
|
throw DB::Exception("Too large alignment " + formatReadableSizeWithBinarySuffix(alignment) + ": more than page size when allocating "
|
||||||
+ formatReadableSizeWithBinarySuffix(size) + ".", DB::ErrorCodes::BAD_ARGUMENTS);
|
+ formatReadableSizeWithBinarySuffix(size) + ".", DB::ErrorCodes::BAD_ARGUMENTS);
|
||||||
|
|
||||||
buf = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
buf = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||||
@ -115,7 +115,11 @@ void Allocator<clear_memory_>::free(void * buf, size_t size)
|
|||||||
template <bool clear_memory_>
|
template <bool clear_memory_>
|
||||||
void * Allocator<clear_memory_>::realloc(void * buf, size_t old_size, size_t new_size, size_t alignment)
|
void * Allocator<clear_memory_>::realloc(void * buf, size_t old_size, size_t new_size, size_t alignment)
|
||||||
{
|
{
|
||||||
if (old_size < MMAP_THRESHOLD && new_size < MMAP_THRESHOLD && alignment <= MALLOC_MIN_ALIGNMENT)
|
if (old_size == new_size)
|
||||||
|
{
|
||||||
|
/// nothing to do.
|
||||||
|
}
|
||||||
|
else if (old_size < MMAP_THRESHOLD && new_size < MMAP_THRESHOLD && alignment <= MALLOC_MIN_ALIGNMENT)
|
||||||
{
|
{
|
||||||
CurrentMemoryTracker::realloc(old_size, new_size);
|
CurrentMemoryTracker::realloc(old_size, new_size);
|
||||||
|
|
||||||
@ -124,7 +128,7 @@ void * Allocator<clear_memory_>::realloc(void * buf, size_t old_size, size_t new
|
|||||||
if (nullptr == buf)
|
if (nullptr == buf)
|
||||||
DB::throwFromErrno("Allocator: Cannot realloc from " + formatReadableSizeWithBinarySuffix(old_size) + " to " + formatReadableSizeWithBinarySuffix(new_size) + ".", DB::ErrorCodes::CANNOT_ALLOCATE_MEMORY);
|
DB::throwFromErrno("Allocator: Cannot realloc from " + formatReadableSizeWithBinarySuffix(old_size) + " to " + formatReadableSizeWithBinarySuffix(new_size) + ".", DB::ErrorCodes::CANNOT_ALLOCATE_MEMORY);
|
||||||
|
|
||||||
if (clear_memory)
|
if (clear_memory && new_size > old_size)
|
||||||
memset(reinterpret_cast<char *>(buf) + old_size, 0, new_size - old_size);
|
memset(reinterpret_cast<char *>(buf) + old_size, 0, new_size - old_size);
|
||||||
}
|
}
|
||||||
else if (old_size >= MMAP_THRESHOLD && new_size >= MMAP_THRESHOLD)
|
else if (old_size >= MMAP_THRESHOLD && new_size >= MMAP_THRESHOLD)
|
||||||
@ -138,6 +142,17 @@ void * Allocator<clear_memory_>::realloc(void * buf, size_t old_size, size_t new
|
|||||||
|
|
||||||
/// No need for zero-fill, because mmap guarantees it.
|
/// No need for zero-fill, because mmap guarantees it.
|
||||||
}
|
}
|
||||||
|
else if (old_size >= MMAP_THRESHOLD && new_size < MMAP_THRESHOLD)
|
||||||
|
{
|
||||||
|
void * new_buf = alloc(new_size, alignment);
|
||||||
|
memcpy(new_buf, buf, new_size);
|
||||||
|
if (0 != munmap(buf, old_size))
|
||||||
|
{
|
||||||
|
::free(new_buf);
|
||||||
|
DB::throwFromErrno("Allocator: Cannot munmap " + formatReadableSizeWithBinarySuffix(old_size) + ".", DB::ErrorCodes::CANNOT_MUNMAP);
|
||||||
|
}
|
||||||
|
buf = new_buf;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
void * new_buf = alloc(new_size, alignment);
|
void * new_buf = alloc(new_size, alignment);
|
||||||
|
257
dbms/src/Common/BackgroundSchedulePool.cpp
Normal file
257
dbms/src/Common/BackgroundSchedulePool.cpp
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
#include <Common/BackgroundSchedulePool.h>
|
||||||
|
#include <Common/MemoryTracker.h>
|
||||||
|
#include <Common/CurrentMetrics.h>
|
||||||
|
#include <Common/Exception.h>
|
||||||
|
#include <Common/setThreadName.h>
|
||||||
|
#include <Common/Stopwatch.h>
|
||||||
|
#include <common/logger_useful.h>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
namespace CurrentMetrics
|
||||||
|
{
|
||||||
|
extern const Metric BackgroundSchedulePoolTask;
|
||||||
|
extern const Metric MemoryTrackingInBackgroundSchedulePool;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
// TaskNotification
|
||||||
|
|
||||||
|
class TaskNotification final : public Poco::Notification
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit TaskNotification(const BackgroundSchedulePool::TaskHandle & task) : task(task) {}
|
||||||
|
void execute() { task->execute(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
BackgroundSchedulePool::TaskHandle task;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// BackgroundSchedulePool::TaskInfo
|
||||||
|
|
||||||
|
BackgroundSchedulePool::TaskInfo::TaskInfo(BackgroundSchedulePool & pool, const std::string & name, const Task & function):
|
||||||
|
name(name),
|
||||||
|
pool(pool),
|
||||||
|
function(function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool BackgroundSchedulePool::TaskInfo::schedule()
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex);
|
||||||
|
|
||||||
|
if (deactivated || scheduled)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
scheduled = true;
|
||||||
|
|
||||||
|
if (delayed)
|
||||||
|
pool.cancelDelayedTask(shared_from_this(), lock);
|
||||||
|
|
||||||
|
pool.queue.enqueueNotification(new TaskNotification(shared_from_this()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool BackgroundSchedulePool::TaskInfo::scheduleAfter(size_t ms)
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex);
|
||||||
|
|
||||||
|
if (deactivated || scheduled)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
pool.scheduleDelayedTask(shared_from_this(), ms, lock);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BackgroundSchedulePool::TaskInfo::deactivate()
|
||||||
|
{
|
||||||
|
if (deactivated)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::lock_guard lock(mutex);
|
||||||
|
deactivated = true;
|
||||||
|
scheduled = false;
|
||||||
|
|
||||||
|
if (delayed)
|
||||||
|
pool.cancelDelayedTask(shared_from_this(), lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BackgroundSchedulePool::TaskInfo::activate()
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex);
|
||||||
|
deactivated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BackgroundSchedulePool::TaskInfo::execute()
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex);
|
||||||
|
|
||||||
|
if (deactivated)
|
||||||
|
return;
|
||||||
|
|
||||||
|
scheduled = false;
|
||||||
|
CurrentMetrics::Increment metric_increment{CurrentMetrics::BackgroundSchedulePoolTask};
|
||||||
|
|
||||||
|
Stopwatch watch;
|
||||||
|
function();
|
||||||
|
UInt64 milliseconds = watch.elapsedMilliseconds();
|
||||||
|
|
||||||
|
/// If the task is executed longer than specified time, it will be logged.
|
||||||
|
static const int32_t slow_execution_threshold_ms = 50;
|
||||||
|
|
||||||
|
if (milliseconds >= slow_execution_threshold_ms)
|
||||||
|
LOG_INFO(&Logger::get("BackgroundSchedulePool"), "Executing " << name << " took " << milliseconds << " ms.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// BackgroundSchedulePool
|
||||||
|
|
||||||
|
BackgroundSchedulePool::BackgroundSchedulePool(size_t size)
|
||||||
|
: size(size)
|
||||||
|
{
|
||||||
|
LOG_INFO(&Logger::get("BackgroundSchedulePool"), "Create BackgroundSchedulePool with " << size << " threads");
|
||||||
|
|
||||||
|
threads.resize(size);
|
||||||
|
for (auto & thread : threads)
|
||||||
|
thread = std::thread([this] { threadFunction(); });
|
||||||
|
|
||||||
|
delayed_thread = std::thread([this] { delayExecutionThreadFunction(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BackgroundSchedulePool::~BackgroundSchedulePool()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
shutdown = true;
|
||||||
|
wakeup_event.notify_all();
|
||||||
|
queue.wakeUpAll();
|
||||||
|
|
||||||
|
delayed_thread.join();
|
||||||
|
|
||||||
|
LOG_TRACE(&Logger::get("BackgroundSchedulePool"), "Waiting for threads to finish.");
|
||||||
|
for (std::thread & thread : threads)
|
||||||
|
thread.join();
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
tryLogCurrentException(__PRETTY_FUNCTION__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BackgroundSchedulePool::TaskHandle BackgroundSchedulePool::addTask(const std::string & name, const Task & task)
|
||||||
|
{
|
||||||
|
return std::make_shared<TaskInfo>(*this, name, task);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BackgroundSchedulePool::removeTask(const TaskHandle & task)
|
||||||
|
{
|
||||||
|
task->deactivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BackgroundSchedulePool::scheduleDelayedTask(const TaskHandle & task, size_t ms, std::lock_guard<std::recursive_mutex> &)
|
||||||
|
{
|
||||||
|
Poco::Timestamp current_time;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard lock(delayed_tasks_lock);
|
||||||
|
|
||||||
|
if (task->delayed)
|
||||||
|
delayed_tasks.erase(task->iterator);
|
||||||
|
|
||||||
|
task->iterator = delayed_tasks.emplace(current_time + (ms * 1000), task);
|
||||||
|
task->delayed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
wakeup_event.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BackgroundSchedulePool::cancelDelayedTask(const TaskHandle & task, std::lock_guard<std::recursive_mutex> &)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::lock_guard lock(delayed_tasks_lock);
|
||||||
|
delayed_tasks.erase(task->iterator);
|
||||||
|
task->delayed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wakeup_event.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BackgroundSchedulePool::threadFunction()
|
||||||
|
{
|
||||||
|
setThreadName("BackgrSchedPool");
|
||||||
|
|
||||||
|
MemoryTracker memory_tracker;
|
||||||
|
memory_tracker.setMetric(CurrentMetrics::MemoryTrackingInBackgroundSchedulePool);
|
||||||
|
current_memory_tracker = &memory_tracker;
|
||||||
|
|
||||||
|
while (!shutdown)
|
||||||
|
{
|
||||||
|
if (Poco::AutoPtr<Poco::Notification> notification = queue.waitDequeueNotification())
|
||||||
|
{
|
||||||
|
TaskNotification & task_notification = static_cast<TaskNotification &>(*notification);
|
||||||
|
task_notification.execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
current_memory_tracker = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BackgroundSchedulePool::delayExecutionThreadFunction()
|
||||||
|
{
|
||||||
|
setThreadName("BckSchPoolDelay");
|
||||||
|
|
||||||
|
while (!shutdown)
|
||||||
|
{
|
||||||
|
Poco::Timestamp min_time;
|
||||||
|
TaskHandle task;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard lock(delayed_tasks_lock);
|
||||||
|
|
||||||
|
if (!delayed_tasks.empty())
|
||||||
|
{
|
||||||
|
auto t = delayed_tasks.begin();
|
||||||
|
min_time = t->first;
|
||||||
|
task = t->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shutdown)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!task)
|
||||||
|
{
|
||||||
|
std::unique_lock lock(delayed_tasks_lock);
|
||||||
|
wakeup_event.wait(lock);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Poco::Timestamp current_time;
|
||||||
|
if (min_time > current_time)
|
||||||
|
{
|
||||||
|
std::unique_lock lock(delayed_tasks_lock);
|
||||||
|
wakeup_event.wait_for(lock, std::chrono::microseconds(min_time - current_time));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
task->schedule();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user