mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-29 19:12:03 +00:00
Merge pull request #304 from yandex/METR-23582
Implement zlib buffers [#METR-23582]
This commit is contained in:
commit
6eb9bac6eb
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,6 +1,7 @@
|
||||
# emacs files
|
||||
*~
|
||||
*\#
|
||||
.tramp_history
|
||||
|
||||
# auto generated files
|
||||
*.logrt
|
||||
|
@ -167,6 +167,10 @@ include_directories (BEFORE ${ClickHouse_SOURCE_DIR}/contrib/libpoco/MongoDB/inc
|
||||
include_directories (BEFORE ${ClickHouse_SOURCE_DIR}/contrib/libpoco/Zip/include/)
|
||||
include_directories (BEFORE ${ClickHouse_SOURCE_DIR}/contrib/libboost/boost_1_62_0/)
|
||||
|
||||
if (USE_STATIC_LIBRARIES)
|
||||
include_directories (BEFORE ${ClickHouse_SOURCE_DIR}/contrib/libzlib-ng/)
|
||||
endif ()
|
||||
|
||||
include_directories (BEFORE ${ClickHouse_SOURCE_DIR}/libs/libcommon/include/)
|
||||
include_directories (BEFORE ${ClickHouse_BINARY_DIR}/libs/libcommon/include/)
|
||||
include_directories (BEFORE ${ClickHouse_SOURCE_DIR}/libs/libdaemon/include/)
|
||||
|
1
contrib/CMakeLists.txt
vendored
1
contrib/CMakeLists.txt
vendored
@ -13,6 +13,7 @@ add_subdirectory (libzookeeper)
|
||||
add_subdirectory (libcityhash)
|
||||
add_subdirectory (libfarmhash)
|
||||
add_subdirectory (libmetrohash)
|
||||
add_subdirectory (libzlib-ng)
|
||||
|
||||
if (ENABLE_LIBTCMALLOC)
|
||||
add_subdirectory (libtcmalloc)
|
||||
|
@ -117,9 +117,9 @@ endif ()
|
||||
|
||||
if (POCO_UNBUNDLED)
|
||||
add_definitions( -DPOCO_UNBUNDLED)
|
||||
message(STATUS "Build with using external sqlite, libz, pcre, expat ...")
|
||||
message(STATUS "Build with using external sqlite, pcre, expat ...")
|
||||
else ()
|
||||
message(STATUS "Build with using internal copy of sqlite, libz, pcre, expat, ...")
|
||||
message(STATUS "Build with using internal copy of sqlite, pcre, expat, ...")
|
||||
endif ()
|
||||
|
||||
include(CheckTypeSize)
|
||||
|
@ -44,10 +44,6 @@ if (POCO_UNBUNDLED)
|
||||
src/pcre_ucd.c
|
||||
src/pcre_tables.c
|
||||
)
|
||||
|
||||
find_package(ZLIB REQUIRED)
|
||||
set(SYSLIBS ${SYSLIBS} ${ZLIB_LIBRARIES})
|
||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
else()
|
||||
# pcre
|
||||
POCO_SOURCES( SRCS pcre
|
||||
@ -73,27 +69,18 @@ else()
|
||||
src/pcre_valid_utf8.c
|
||||
src/pcre_xclass.c
|
||||
)
|
||||
|
||||
# zlib
|
||||
POCO_HEADERS( SRCS zlib
|
||||
include/Poco/zconf.h
|
||||
include/Poco/zlib.h
|
||||
)
|
||||
|
||||
POCO_SOURCES( SRCS zlib
|
||||
src/adler32.c
|
||||
src/compress.c
|
||||
src/crc32.c
|
||||
src/deflate.c
|
||||
src/infback.c
|
||||
src/inffast.c
|
||||
src/inflate.c
|
||||
src/inftrees.c
|
||||
src/trees.c
|
||||
src/zutil.c
|
||||
)
|
||||
endif (POCO_UNBUNDLED)
|
||||
|
||||
if (USE_STATIC_LIBRARIES)
|
||||
# Use zlib from clickhouse contrib.
|
||||
set(SYSLIBS ${SYSLIBS} zlibstatic)
|
||||
include_directories("${ClickHouse_SOURCE_DIR}/contrib/libzlib-ng/")
|
||||
else()
|
||||
find_package(ZLIB REQUIRED)
|
||||
set(SYSLIBS ${SYSLIBS} ${ZLIB_LIBRARIES})
|
||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
endif (USE_STATIC_LIBRARIES)
|
||||
|
||||
if(WIN32)
|
||||
set(SYSLIBS ${SYSLIBS} iphlpapi)
|
||||
endif(WIN32)
|
||||
|
@ -24,11 +24,7 @@
|
||||
#include "Poco/BufferedStreamBuf.h"
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
#if defined(POCO_UNBUNDLED)
|
||||
#include <zlib.h>
|
||||
#else
|
||||
#include "Poco/zlib.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
@ -24,11 +24,7 @@
|
||||
#include "Poco/BufferedStreamBuf.h"
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
#if defined(POCO_UNBUNDLED)
|
||||
#include <zlib.h>
|
||||
#else
|
||||
#include "Poco/zlib.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
@ -15,11 +15,7 @@
|
||||
|
||||
|
||||
#include "Poco/Checksum.h"
|
||||
#if defined(POCO_UNBUNDLED)
|
||||
#include <zlib.h>
|
||||
#else
|
||||
#include "Poco/zlib.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
@ -23,11 +23,7 @@
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/InflatingStream.h"
|
||||
#include "Poco/DeflatingStream.h"
|
||||
#if defined(POCO_UNBUNDLED)
|
||||
#include <zlib.h>
|
||||
#else
|
||||
#include "Poco/zlib.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
52
contrib/libzlib-ng/.gitignore
vendored
Normal file
52
contrib/libzlib-ng/.gitignore
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
*.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
|
12
contrib/libzlib-ng/.travis.yml
Normal file
12
contrib/libzlib-ng/.travis.yml
Normal file
@ -0,0 +1,12 @@
|
||||
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
|
555
contrib/libzlib-ng/CMakeLists.txt
Normal file
555
contrib/libzlib-ng/CMakeLists.txt
Normal file
@ -0,0 +1,555 @@
|
||||
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_STRATEGIES "Use new strategies" 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_STRATEGIES WITH_NEW_STRATEGIES "Use new strategies")
|
||||
|
||||
#
|
||||
# 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_STRATEGIES)
|
||||
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")
|
||||
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)
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/x86.c)
|
||||
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_STRATEGIES)
|
||||
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)
|
||||
add_definitions(-DX86_PCLMULQDQ_CRC)
|
||||
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
|
||||
#============================================================================
|
||||
|
||||
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()
|
||||
|
||||
FEATURE_SUMMARY(WHAT ALL INCLUDE_QUIET_PACKAGES)
|
1478
contrib/libzlib-ng/ChangeLog.zlib
Normal file
1478
contrib/libzlib-ng/ChangeLog.zlib
Normal file
File diff suppressed because it is too large
Load Diff
374
contrib/libzlib-ng/FAQ.zlib
Normal file
374
contrib/libzlib-ng/FAQ.zlib
Normal file
@ -0,0 +1,374 @@
|
||||
##
|
||||
# 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.
|
55
contrib/libzlib-ng/INDEX
Normal file
55
contrib/libzlib-ng/INDEX
Normal file
@ -0,0 +1,55 @@
|
||||
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
|
19
contrib/libzlib-ng/LICENSE.md
Normal file
19
contrib/libzlib-ng/LICENSE.md
Normal file
@ -0,0 +1,19 @@
|
||||
(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.
|
329
contrib/libzlib-ng/Makefile.in
Normal file
329
contrib/libzlib-ng/Makefile.in
Normal file
@ -0,0 +1,329 @@
|
||||
# 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
|
63
contrib/libzlib-ng/README
Normal file
63
contrib/libzlib-ng/README
Normal file
@ -0,0 +1,63 @@
|
||||
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).
|
12
contrib/libzlib-ng/README.clickhouse
Normal file
12
contrib/libzlib-ng/README.clickhouse
Normal file
@ -0,0 +1,12 @@
|
||||
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
|
||||
)
|
65
contrib/libzlib-ng/README.md
Normal file
65
contrib/libzlib-ng/README.md
Normal file
@ -0,0 +1,65 @@
|
||||
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).
|
121
contrib/libzlib-ng/README.zlib
Normal file
121
contrib/libzlib-ng/README.zlib
Normal file
@ -0,0 +1,121 @@
|
||||
##
|
||||
# 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.
|
177
contrib/libzlib-ng/adler32.c
Normal file
177
contrib/libzlib-ng/adler32.c
Normal file
@ -0,0 +1,177 @@
|
||||
/* 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
Normal file
2
contrib/libzlib-ng/arch/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# ignore Makefiles; they're all automatically generated
|
||||
Makefile
|
20
contrib/libzlib-ng/arch/arm/Makefile.in
Normal file
20
contrib/libzlib-ng/arch/arm/Makefile.in
Normal file
@ -0,0 +1,20 @@
|
||||
# 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
|
20
contrib/libzlib-ng/arch/generic/Makefile.in
Normal file
20
contrib/libzlib-ng/arch/generic/Makefile.in
Normal file
@ -0,0 +1,20 @@
|
||||
# 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
|
3
contrib/libzlib-ng/arch/x86/INDEX
Normal file
3
contrib/libzlib-ng/arch/x86/INDEX
Normal file
@ -0,0 +1,3 @@
|
||||
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
|
53
contrib/libzlib-ng/arch/x86/Makefile.in
Normal file
53
contrib/libzlib-ng/arch/x86/Makefile.in
Normal file
@ -0,0 +1,53 @@
|
||||
# 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
|
465
contrib/libzlib-ng/arch/x86/crc_folding.c
Normal file
465
contrib/libzlib-ng/arch/x86/crc_folding.c
Normal file
@ -0,0 +1,465 @@
|
||||
/*
|
||||
* 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
|
||||
|
2371
contrib/libzlib-ng/arch/x86/deflate_quick.c
Normal file
2371
contrib/libzlib-ng/arch/x86/deflate_quick.c
Normal file
File diff suppressed because it is too large
Load Diff
165
contrib/libzlib-ng/arch/x86/fill_window_sse.c
Normal file
165
contrib/libzlib-ng/arch/x86/fill_window_sse.c
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* 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
|
50
contrib/libzlib-ng/arch/x86/insert_string_sse.c
Normal file
50
contrib/libzlib-ng/arch/x86/insert_string_sse.c
Normal file
@ -0,0 +1,50 @@
|
||||
/* 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
|
53
contrib/libzlib-ng/arch/x86/x86.c
Normal file
53
contrib/libzlib-ng/arch/x86/x86.c
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
23
contrib/libzlib-ng/arch/x86/x86.h
Normal file
23
contrib/libzlib-ng/arch/x86/x86.h
Normal file
@ -0,0 +1,23 @@
|
||||
/* 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_ */
|
74
contrib/libzlib-ng/compress.c
Normal file
74
contrib/libzlib-ng/compress.c
Normal file
@ -0,0 +1,74 @@
|
||||
/* 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
Executable file
923
contrib/libzlib-ng/configure
vendored
Executable file
@ -0,0 +1,923 @@
|
||||
#!/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
|
458
contrib/libzlib-ng/crc32.c
Normal file
458
contrib/libzlib-ng/crc32.c
Normal file
@ -0,0 +1,458 @@
|
||||
/* 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);
|
||||
}
|
||||
|
444
contrib/libzlib-ng/crc32.h
Normal file
444
contrib/libzlib-ng/crc32.h
Normal file
@ -0,0 +1,444 @@
|
||||
#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_ */
|
1407
contrib/libzlib-ng/deflate.c
Normal file
1407
contrib/libzlib-ng/deflate.c
Normal file
File diff suppressed because it is too large
Load Diff
459
contrib/libzlib-ng/deflate.h
Normal file
459
contrib/libzlib-ng/deflate.h
Normal file
@ -0,0 +1,459 @@
|
||||
#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_ */
|
114
contrib/libzlib-ng/deflate_fast.c
Normal file
114
contrib/libzlib-ng/deflate_fast.c
Normal file
@ -0,0 +1,114 @@
|
||||
/* 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;
|
||||
}
|
322
contrib/libzlib-ng/deflate_medium.c
Normal file
322
contrib/libzlib-ng/deflate_medium.c
Normal file
@ -0,0 +1,322 @@
|
||||
/* 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
|
96
contrib/libzlib-ng/deflate_p.h
Normal file
96
contrib/libzlib-ng/deflate_p.h
Normal file
@ -0,0 +1,96 @@
|
||||
/* 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
|
160
contrib/libzlib-ng/deflate_slow.c
Normal file
160
contrib/libzlib-ng/deflate_slow.c
Normal file
@ -0,0 +1,160 @@
|
||||
/* 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;
|
||||
}
|
209
contrib/libzlib-ng/doc/algorithm.txt
Normal file
209
contrib/libzlib-ng/doc/algorithm.txt
Normal file
@ -0,0 +1,209 @@
|
||||
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
|
619
contrib/libzlib-ng/doc/rfc1950.txt
Normal file
619
contrib/libzlib-ng/doc/rfc1950.txt
Normal file
@ -0,0 +1,619 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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]
|
||||
|
955
contrib/libzlib-ng/doc/rfc1951.txt
Normal file
955
contrib/libzlib-ng/doc/rfc1951.txt
Normal file
@ -0,0 +1,955 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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]
|
||||
|
675
contrib/libzlib-ng/doc/rfc1952.txt
Normal file
675
contrib/libzlib-ng/doc/rfc1952.txt
Normal file
@ -0,0 +1,675 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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]
|
||||
|
107
contrib/libzlib-ng/doc/txtvsbin.txt
Normal file
107
contrib/libzlib-ng/doc/txtvsbin.txt
Normal file
@ -0,0 +1,107 @@
|
||||
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
|
23
contrib/libzlib-ng/gzclose.c
Normal file
23
contrib/libzlib-ng/gzclose.c
Normal file
@ -0,0 +1,23 @@
|
||||
/* 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
|
||||
}
|
158
contrib/libzlib-ng/gzguts.h
Normal file
158
contrib/libzlib-ng/gzguts.h
Normal file
@ -0,0 +1,158 @@
|
||||
#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_ */
|
518
contrib/libzlib-ng/gzlib.c
Normal file
518
contrib/libzlib-ng/gzlib.c
Normal file
@ -0,0 +1,518 @@
|
||||
/* 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
|
538
contrib/libzlib-ng/gzread.c
Normal file
538
contrib/libzlib-ng/gzread.c
Normal file
@ -0,0 +1,538 @@
|
||||
/* 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;
|
||||
}
|
457
contrib/libzlib-ng/gzwrite.c
Normal file
457
contrib/libzlib-ng/gzwrite.c
Normal file
@ -0,0 +1,457 @@
|
||||
/* 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;
|
||||
}
|
612
contrib/libzlib-ng/infback.c
Normal file
612
contrib/libzlib-ng/infback.c
Normal file
@ -0,0 +1,612 @@
|
||||
/* 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;
|
||||
}
|
328
contrib/libzlib-ng/inffast.c
Normal file
328
contrib/libzlib-ng/inffast.c
Normal file
@ -0,0 +1,328 @@
|
||||
/* 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
|
||||
*/
|
15
contrib/libzlib-ng/inffast.h
Normal file
15
contrib/libzlib-ng/inffast.h
Normal file
@ -0,0 +1,15 @@
|
||||
#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_ */
|
94
contrib/libzlib-ng/inffixed.h
Normal file
94
contrib/libzlib-ng/inffixed.h
Normal file
@ -0,0 +1,94 @@
|
||||
/* 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}
|
||||
};
|
1467
contrib/libzlib-ng/inflate.c
Normal file
1467
contrib/libzlib-ng/inflate.c
Normal file
File diff suppressed because it is too large
Load Diff
127
contrib/libzlib-ng/inflate.h
Normal file
127
contrib/libzlib-ng/inflate.h
Normal file
@ -0,0 +1,127 @@
|
||||
/* 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_ */
|
298
contrib/libzlib-ng/inftrees.c
Normal file
298
contrib/libzlib-ng/inftrees.c
Normal file
@ -0,0 +1,298 @@
|
||||
/* 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;
|
||||
}
|
66
contrib/libzlib-ng/inftrees.h
Normal file
66
contrib/libzlib-ng/inftrees.h
Normal file
@ -0,0 +1,66 @@
|
||||
#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_ */
|
471
contrib/libzlib-ng/match.c
Normal file
471
contrib/libzlib-ng/match.c
Normal file
@ -0,0 +1,471 @@
|
||||
/*
|
||||
* 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
|
6
contrib/libzlib-ng/match.h
Normal file
6
contrib/libzlib-ng/match.h
Normal file
@ -0,0 +1,6 @@
|
||||
#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
Normal file
2
contrib/libzlib-ng/test/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# ignore Makefiles; they're all automatically generated
|
||||
Makefile
|
BIN
contrib/libzlib-ng/test/CVE-2002-0059/test.gz
Normal file
BIN
contrib/libzlib-ng/test/CVE-2002-0059/test.gz
Normal file
Binary file not shown.
20
contrib/libzlib-ng/test/CVE-2003-0107.c
Normal file
20
contrib/libzlib-ng/test/CVE-2003-0107.c
Normal file
@ -0,0 +1,20 @@
|
||||
// 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);
|
||||
}
|
BIN
contrib/libzlib-ng/test/CVE-2004-0797/test.gz
Normal file
BIN
contrib/libzlib-ng/test/CVE-2004-0797/test.gz
Normal file
Binary file not shown.
BIN
contrib/libzlib-ng/test/CVE-2005-1849/test.gz
Normal file
BIN
contrib/libzlib-ng/test/CVE-2005-1849/test.gz
Normal file
Binary file not shown.
BIN
contrib/libzlib-ng/test/CVE-2005-2096/test.gz
Normal file
BIN
contrib/libzlib-ng/test/CVE-2005-2096/test.gz
Normal file
Binary file not shown.
10
contrib/libzlib-ng/test/INDEX
Normal file
10
contrib/libzlib-ng/test/INDEX
Normal file
@ -0,0 +1,10 @@
|
||||
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
|
||||
|
77
contrib/libzlib-ng/test/Makefile.in
Normal file
77
contrib/libzlib-ng/test/Makefile.in
Normal file
@ -0,0 +1,77 @@
|
||||
# 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
|
544
contrib/libzlib-ng/test/example.c
Normal file
544
contrib/libzlib-ng/test/example.c
Normal file
@ -0,0 +1,544 @@
|
||||
/* 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;
|
||||
}
|
668
contrib/libzlib-ng/test/infcover.c
Normal file
668
contrib/libzlib-ng/test/infcover.c
Normal file
@ -0,0 +1,668 @@
|
||||
/* 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;
|
||||
}
|
530
contrib/libzlib-ng/test/minigzip.c
Normal file
530
contrib/libzlib-ng/test/minigzip.c
Normal file
@ -0,0 +1,530 @@
|
||||
/* 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;
|
||||
}
|
22
contrib/libzlib-ng/test/testCVEinputs.sh
Executable file
22
contrib/libzlib-ng/test/testCVEinputs.sh
Executable file
@ -0,0 +1,22 @@
|
||||
#!/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
|
||||
|
116
contrib/libzlib-ng/treebuild.xml
Normal file
116
contrib/libzlib-ng/treebuild.xml
Normal file
@ -0,0 +1,116 @@
|
||||
<?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
|
||||
-->
|
1119
contrib/libzlib-ng/trees.c
Normal file
1119
contrib/libzlib-ng/trees.c
Normal file
File diff suppressed because it is too large
Load Diff
132
contrib/libzlib-ng/trees.h
Normal file
132
contrib/libzlib-ng/trees.h
Normal file
@ -0,0 +1,132 @@
|
||||
#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_ */
|
75
contrib/libzlib-ng/uncompr.c
Normal file
75
contrib/libzlib-ng/uncompr.c
Normal file
@ -0,0 +1,75 @@
|
||||
/* 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;
|
||||
}
|
397
contrib/libzlib-ng/win32/DLL_FAQ.txt
Normal file
397
contrib/libzlib-ng/win32/DLL_FAQ.txt
Normal file
@ -0,0 +1,397 @@
|
||||
|
||||
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>
|
154
contrib/libzlib-ng/win32/Makefile.msc
Normal file
154
contrib/libzlib-ng/win32/Makefile.msc
Normal file
@ -0,0 +1,154 @@
|
||||
# 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
|
103
contrib/libzlib-ng/win32/README-WIN32.txt
Normal file
103
contrib/libzlib-ng/win32/README-WIN32.txt
Normal file
@ -0,0 +1,103 @@
|
||||
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.
|
3
contrib/libzlib-ng/win32/VisualC.txt
Normal file
3
contrib/libzlib-ng/win32/VisualC.txt
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
To build zlib using the Microsoft Visual C++ environment,
|
||||
use the appropriate project from the projects/ directory.
|
55
contrib/libzlib-ng/win32/zlib.def
Normal file
55
contrib/libzlib-ng/win32/zlib.def
Normal file
@ -0,0 +1,55 @@
|
||||
; 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
|
40
contrib/libzlib-ng/win32/zlib1.rc
Normal file
40
contrib/libzlib-ng/win32/zlib1.rc
Normal file
@ -0,0 +1,40 @@
|
||||
#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
|
86
contrib/libzlib-ng/win32/zlibcompat.def
Normal file
86
contrib/libzlib-ng/win32/zlibcompat.def
Normal file
@ -0,0 +1,86 @@
|
||||
; 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
|
176
contrib/libzlib-ng/zconf.h.in
Normal file
176
contrib/libzlib-ng/zconf.h.in
Normal file
@ -0,0 +1,176 @@
|
||||
/* 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 */
|
169
contrib/libzlib-ng/zlib.3
Normal file
169
contrib/libzlib-ng/zlib.3
Normal file
@ -0,0 +1,169 @@
|
||||
.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
|
BIN
contrib/libzlib-ng/zlib.3.pdf
Normal file
BIN
contrib/libzlib-ng/zlib.3.pdf
Normal file
Binary file not shown.
1728
contrib/libzlib-ng/zlib.h
Normal file
1728
contrib/libzlib-ng/zlib.h
Normal file
File diff suppressed because it is too large
Load Diff
83
contrib/libzlib-ng/zlib.map
Normal file
83
contrib/libzlib-ng/zlib.map
Normal file
@ -0,0 +1,83 @@
|
||||
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;
|
13
contrib/libzlib-ng/zlib.pc.cmakein
Normal file
13
contrib/libzlib-ng/zlib.pc.cmakein
Normal file
@ -0,0 +1,13 @@
|
||||
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}
|
13
contrib/libzlib-ng/zlib.pc.in
Normal file
13
contrib/libzlib-ng/zlib.pc.in
Normal file
@ -0,0 +1,13 @@
|
||||
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}
|
124
contrib/libzlib-ng/zutil.c
Normal file
124
contrib/libzlib-ng/zutil.c
Normal file
@ -0,0 +1,124 @@
|
||||
/* 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 */
|
185
contrib/libzlib-ng/zutil.h
Normal file
185
contrib/libzlib-ng/zutil.h
Normal file
@ -0,0 +1,185 @@
|
||||
#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_ */
|
@ -116,6 +116,13 @@ else()
|
||||
set(PLATFORM_LIBS "")
|
||||
endif()
|
||||
|
||||
if (USE_STATIC_LIBRARIES)
|
||||
set (Z_LIB zlibstatic)
|
||||
else()
|
||||
set (Z_HINTS "/usr/local/opt/zlib/lib")
|
||||
find_library (Z_LIB z HINTS ${Z_HINTS})
|
||||
endif ()
|
||||
|
||||
target_link_libraries(dbms
|
||||
common
|
||||
zkutil
|
||||
@ -124,6 +131,7 @@ target_link_libraries(dbms
|
||||
lz4 zstd
|
||||
string_utils
|
||||
double-conversion
|
||||
${Z_LIB}
|
||||
${LINK_LIBRARIES_ONLY_ON_X86_64}
|
||||
re2 re2_st
|
||||
${OPENSSL_CRYPTO_LIBRARY}
|
||||
|
@ -3,12 +3,13 @@
|
||||
#include <experimental/optional>
|
||||
|
||||
#include <Poco/Net/HTTPServerResponse.h>
|
||||
#include <Poco/DeflatingStream.h>
|
||||
|
||||
#include <DB/Common/Exception.h>
|
||||
|
||||
#include <DB/IO/WriteBuffer.h>
|
||||
#include <DB/IO/BufferWithOwnMemory.h>
|
||||
#include <DB/IO/WriteBufferFromOStream.h>
|
||||
#include <DB/IO/ZlibDeflatingWriteBuffer.h>
|
||||
#include <DB/IO/HTTPCommon.h>
|
||||
#include <DB/Common/NetException.h>
|
||||
|
||||
@ -18,36 +19,37 @@ namespace DB
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int CANNOT_WRITE_TO_OSTREAM;
|
||||
extern const int LOGICAL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/** Отличается от WriteBufferFromOStream тем, что инициализируется не std::ostream, а Poco::Net::HTTPServerResponse.
|
||||
* При первом сбросе данных, получает из него std::ostream (с помощью метода send).
|
||||
* Это нужно в HTTP серверах, чтобы после передачи в какой-нибудь метод WriteBuffer-а,
|
||||
* но до вывода первых данных клиенту, можно было изменить какие-нибудь HTTP заголовки (например, код ответа).
|
||||
* (После вызова Poco::Net::HTTPServerResponse::send() изменить заголовки уже нельзя.)
|
||||
* То есть, суть в том, чтобы вызывать метод Poco::Net::HTTPServerResponse::send() не сразу.
|
||||
*
|
||||
* Дополнительно, позволяет сжимать тело HTTP-ответа, выставив соответствующий заголовок Content-Encoding.
|
||||
*/
|
||||
/// The difference from WriteBufferFromOStream is that this buffer gets the underlying std::ostream
|
||||
/// (using response.send()) only after data is flushed for the first time. This is needed in HTTP
|
||||
/// servers to change some HTTP headers (e.g. response code) before any data is sent to the client
|
||||
/// (headers can't be changed after response.send() is called).
|
||||
///
|
||||
/// In short, it allows delaying the call to response.send().
|
||||
///
|
||||
/// Additionally, supports HTTP response compression (in this case corresponding Content-Encoding
|
||||
/// header will be set).
|
||||
class WriteBufferFromHTTPServerResponse : public BufferWithOwnMemory<WriteBuffer>
|
||||
{
|
||||
private:
|
||||
Poco::Net::HTTPServerResponse & response;
|
||||
|
||||
bool add_cors_header;
|
||||
bool compress;
|
||||
Poco::DeflatingStreamBuf::StreamType compression_method;
|
||||
ZlibCompressionMethod compression_method;
|
||||
int compression_level = Z_DEFAULT_COMPRESSION;
|
||||
|
||||
std::ostream * response_ostr = nullptr; /// Сюда записывается тело HTTP ответа, возможно, сжатое.
|
||||
std::experimental::optional<Poco::DeflatingOutputStream> deflating_stream;
|
||||
std::ostream * ostr = nullptr; /// Куда записывать несжатое тело HTTP ответа. Указывает туда же, куда response_ostr или на deflating_stream.
|
||||
std::unique_ptr<WriteBufferFromOStream> out_raw;
|
||||
std::experimental::optional<ZlibDeflatingWriteBuffer> deflating_buf;
|
||||
|
||||
WriteBuffer * out = nullptr; /// Uncompressed HTTP body is written to this buffer. Points to out_raw or possibly to deflating_buf.
|
||||
|
||||
void sendHeaders()
|
||||
{
|
||||
if (!ostr)
|
||||
if (!out)
|
||||
{
|
||||
if (add_cors_header)
|
||||
{
|
||||
@ -56,24 +58,25 @@ private:
|
||||
|
||||
setResponseDefaultHeaders(response);
|
||||
|
||||
if (compress && offset()) /// Пустой ответ сжимать не нужно.
|
||||
if (compress && offset()) /// Empty response need not be compressed.
|
||||
{
|
||||
if (compression_method == Poco::DeflatingStreamBuf::STREAM_GZIP)
|
||||
if (compression_method == ZlibCompressionMethod::Gzip)
|
||||
response.set("Content-Encoding", "gzip");
|
||||
else if (compression_method == Poco::DeflatingStreamBuf::STREAM_ZLIB)
|
||||
else if (compression_method == ZlibCompressionMethod::Zlib)
|
||||
response.set("Content-Encoding", "deflate");
|
||||
else
|
||||
throw Exception("Logical error: unknown compression method passed to WriteBufferFromHTTPServerResponse",
|
||||
ErrorCodes::LOGICAL_ERROR);
|
||||
|
||||
response_ostr = &response.send();
|
||||
deflating_stream.emplace(*response_ostr, compression_method, compression_level);
|
||||
ostr = &deflating_stream.value();
|
||||
out_raw = std::make_unique<WriteBufferFromOStream>(response.send());
|
||||
/// Use memory allocated for the outer buffer in the buffer pointed to by out. This avoids extra allocation and copy.
|
||||
deflating_buf.emplace(*out_raw, compression_method, compression_level, working_buffer.size(), working_buffer.begin());
|
||||
out = &deflating_buf.value();
|
||||
}
|
||||
else
|
||||
{
|
||||
response_ostr = &response.send();
|
||||
ostr = response_ostr;
|
||||
out_raw = std::make_unique<WriteBufferFromOStream>(response.send(), working_buffer.size(), working_buffer.begin());
|
||||
out = out_raw.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -85,53 +88,43 @@ private:
|
||||
|
||||
sendHeaders();
|
||||
|
||||
ostr->write(working_buffer.begin(), offset());
|
||||
ostr->flush();
|
||||
|
||||
if (!ostr->good())
|
||||
throw NetException("Cannot write to ostream", ErrorCodes::CANNOT_WRITE_TO_OSTREAM);
|
||||
out->position() = position();
|
||||
out->next();
|
||||
}
|
||||
|
||||
public:
|
||||
WriteBufferFromHTTPServerResponse(
|
||||
Poco::Net::HTTPServerResponse & response_,
|
||||
bool compress_ = false, /// Если true - выставить заголовок Content-Encoding и сжимать результат.
|
||||
Poco::DeflatingStreamBuf::StreamType compression_method_ = Poco::DeflatingStreamBuf::STREAM_GZIP, /// Как сжимать результат (gzip, deflate).
|
||||
bool compress_ = false, /// If true - set Content-Encoding header and compress the result.
|
||||
ZlibCompressionMethod compression_method_ = ZlibCompressionMethod::Gzip,
|
||||
size_t size = DBMS_DEFAULT_BUFFER_SIZE)
|
||||
: BufferWithOwnMemory<WriteBuffer>(size), response(response_),
|
||||
compress(compress_), compression_method(compression_method_) {}
|
||||
|
||||
/** Если данные ещё не были отправлены - отправить хотя бы HTTP заголовки.
|
||||
* Используйте эту функцию после того, как данные, возможно, были отправлены,
|
||||
* и не было ошибок (вы не планируете поменять код ответа).
|
||||
*/
|
||||
/// Send at least HTTP headers if no data has been sent yet.
|
||||
/// Use after the data has possibly been sent and no error happened (and thus you do not plan
|
||||
/// to change response HTTP code.
|
||||
void finalize()
|
||||
{
|
||||
sendHeaders();
|
||||
}
|
||||
|
||||
/** Включить или отключить сжатие.
|
||||
* Работает только перед тем, как были отправлены HTTP заголовки.
|
||||
* Иначе - не имеет эффекта.
|
||||
*/
|
||||
/// Turn compression on or off.
|
||||
/// The setting has any effect only if HTTP headers haven't been sent yet.
|
||||
void setCompression(bool enable_compression)
|
||||
{
|
||||
compress = enable_compression;
|
||||
}
|
||||
|
||||
/** Установить уровень сжатия, если данные будут сжиматься.
|
||||
* Работает только перед тем, как были отправлены HTTP заголовки.
|
||||
* Иначе - не имеет эффекта.
|
||||
*/
|
||||
/// Set compression level if the compression is turned on.
|
||||
/// The setting has any effect only if HTTP headers haven't been sent yet.
|
||||
void setCompressionLevel(int level)
|
||||
{
|
||||
compression_level = level;
|
||||
}
|
||||
|
||||
/** Включить или отключить CORS.
|
||||
* Работает только перед тем, как были отправлены HTTP заголовки.
|
||||
* Иначе - не имеет эффекта.
|
||||
*/
|
||||
/// Turn CORS on or off.
|
||||
/// The setting has any effect only if HTTP headers haven't been sent yet.
|
||||
void addHeaderCORS(bool enable_cors)
|
||||
{
|
||||
add_cors_header = enable_cors;
|
||||
@ -145,9 +138,6 @@ public:
|
||||
try
|
||||
{
|
||||
next();
|
||||
|
||||
if (deflating_stream)
|
||||
deflating_stream->close();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
@ -34,8 +34,12 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
WriteBufferFromOStream(std::ostream & ostr_, size_t size = DBMS_DEFAULT_BUFFER_SIZE)
|
||||
: BufferWithOwnMemory<WriteBuffer>(size), ostr(ostr_) {}
|
||||
WriteBufferFromOStream(
|
||||
std::ostream & ostr_,
|
||||
size_t size = DBMS_DEFAULT_BUFFER_SIZE,
|
||||
char * existing_memory = nullptr,
|
||||
size_t alignment = 0)
|
||||
: BufferWithOwnMemory<WriteBuffer>(size, existing_memory, alignment), ostr(ostr_) {}
|
||||
|
||||
~WriteBufferFromOStream() override
|
||||
{
|
||||
|
16
dbms/include/DB/IO/ZlibCompressionMethod.h
Normal file
16
dbms/include/DB/IO/ZlibCompressionMethod.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
enum class ZlibCompressionMethod
|
||||
{
|
||||
/// DEFLATE compression with gzip header and CRC32 checksum.
|
||||
/// This option corresponds to files produced by gzip(1) or HTTP Content-Encoding: gzip.
|
||||
Gzip,
|
||||
/// DEFLATE compression with zlib header and Adler32 checksum.
|
||||
/// This option corresponds to HTTP Content-Encoding: deflate.
|
||||
Zlib,
|
||||
};
|
||||
|
||||
}
|
45
dbms/include/DB/IO/ZlibDeflatingWriteBuffer.h
Normal file
45
dbms/include/DB/IO/ZlibDeflatingWriteBuffer.h
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <DB/IO/WriteBuffer.h>
|
||||
#include <DB/IO/BufferWithOwnMemory.h>
|
||||
#include <DB/IO/ZlibCompressionMethod.h>
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int ZLIB_DEFLATE_FAILED;
|
||||
}
|
||||
|
||||
/// Performs compression using zlib library and writes compressed data to out_ WriteBuffer.
|
||||
class ZlibDeflatingWriteBuffer : public BufferWithOwnMemory<WriteBuffer>
|
||||
{
|
||||
public:
|
||||
ZlibDeflatingWriteBuffer(
|
||||
WriteBuffer & out_,
|
||||
ZlibCompressionMethod compression_method,
|
||||
int compression_level,
|
||||
size_t buf_size = DBMS_DEFAULT_BUFFER_SIZE,
|
||||
char * existing_memory = nullptr,
|
||||
size_t alignment = 0);
|
||||
|
||||
/// Flush all pending data and write zlib footer to the underlying buffer.
|
||||
/// After the first call to this function, subsequent calls will have no effect and
|
||||
/// an attempt to write to this buffer will result in exception.
|
||||
void finish();
|
||||
|
||||
~ZlibDeflatingWriteBuffer() override;
|
||||
|
||||
private:
|
||||
void nextImpl() override;
|
||||
|
||||
WriteBuffer & out;
|
||||
z_stream zstr;
|
||||
bool finished = false;
|
||||
};
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user