mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 16:51:29 +00:00
Zlib ng
This commit is contained in:
parent
d7c110041a
commit
e086f53b97
11
.gitignore
vendored
11
.gitignore
vendored
@ -23,16 +23,7 @@ CMakeFiles
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
Build/
|
||||
build/
|
||||
Build32/
|
||||
build32/
|
||||
Build64/
|
||||
build64/
|
||||
Build_32/
|
||||
build_32/
|
||||
Build_64/
|
||||
build_64/
|
||||
[Bb]uild*/
|
||||
x64/
|
||||
x86/
|
||||
log/
|
||||
|
||||
@ -290,14 +290,14 @@ ADD_DEFINITIONS(-DGLM_FORCE_CTOR_INIT)
|
||||
ADD_DEFINITIONS(-DGLM_ENABLE_EXPERIMENTAL)
|
||||
|
||||
#Find everything we need
|
||||
FIND_PACKAGE(ZLIB REQUIRED)
|
||||
FIND_PACKAGE(ZLIB)
|
||||
FIND_PACKAGE(MySQL REQUIRED)
|
||||
IF(EQEMU_BUILD_PERL)
|
||||
FIND_PACKAGE(PerlLibs REQUIRED)
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${PERL_INCLUDE_PATH}")
|
||||
ENDIF(EQEMU_BUILD_PERL)
|
||||
|
||||
SET(SERVER_LIBS common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY} libuv fmt recast_navigation)
|
||||
SET(SERVER_LIBS common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} libuv fmt recast_navigation)
|
||||
|
||||
FIND_PACKAGE(Sodium REQUIRED)
|
||||
IF(SODIUM_FOUND)
|
||||
@ -309,6 +309,21 @@ IF(SODIUM_FOUND)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
IF(ZLIB_FOUND)
|
||||
OPTION(EQEMU_BUILD_ZLIB "Build internal version of zlib." OFF)
|
||||
|
||||
IF(EQEMU_BUILD_ZLIB)
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng")
|
||||
SET(SERVER_LIBS ${SERVER_LIBS} "zlibstatic")
|
||||
ELSE()
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_INCLUDE_DIRS}")
|
||||
SET(SERVER_LIBS ${SERVER_LIBS} ${ZLIB_LIBRARY})
|
||||
ENDIF()
|
||||
ELSE()
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng")
|
||||
SET(SERVER_LIBS ${SERVER_LIBS} "zlibstatic")
|
||||
ENDIF()
|
||||
|
||||
IF(WIN32)
|
||||
SET(SERVER_LIBS ${SERVER_LIBS} "ws2_32" "psapi" "iphlpapi" "userenv")
|
||||
ENDIF()
|
||||
@ -338,7 +353,6 @@ IF(EQEMU_BUILD_LUA)
|
||||
ENDIF(EQEMU_SANITIZE_LUA_LIBS)
|
||||
ENDIF(EQEMU_BUILD_LUA)
|
||||
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_INCLUDE_DIRS}")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${MySQL_INCLUDE_DIR}")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/common/glm")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/cereal")
|
||||
@ -351,6 +365,12 @@ INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/recast/recast/inclu
|
||||
IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC)
|
||||
ADD_SUBDIRECTORY(common)
|
||||
ADD_SUBDIRECTORY(libs)
|
||||
|
||||
IF(EQEMU_BUILD_ZLIB)
|
||||
SET(ZLIB_COMPAT ON CACHE BOOL "Compile with zlib compatible API")
|
||||
SET(ZLIB_ENABLE_TESTS OFF CACHE BOOL "Build test binaries")
|
||||
ADD_SUBDIRECTORY(libs/zlibng)
|
||||
ENDIF()
|
||||
ENDIF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC)
|
||||
IF(EQEMU_BUILD_SERVER)
|
||||
ADD_SUBDIRECTORY(shared_memory)
|
||||
|
||||
4
libs/zlibng/.gitattributes
vendored
Normal file
4
libs/zlibng/.gitattributes
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
* text=auto
|
||||
*.c text
|
||||
*.h text
|
||||
Makefile text
|
||||
76
libs/zlibng/.gitignore
vendored
Normal file
76
libs/zlibng/.gitignore
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
*.diff
|
||||
*.patch
|
||||
*.orig
|
||||
*.rej
|
||||
|
||||
*~
|
||||
*.a
|
||||
*.lo
|
||||
*.o
|
||||
*.dylib
|
||||
|
||||
*.gcda
|
||||
*.gcno
|
||||
*.gcov
|
||||
|
||||
/example
|
||||
/example64
|
||||
/examplesh
|
||||
/libz.so*
|
||||
/libz-ng.so*
|
||||
/minigzip
|
||||
/minigzip64
|
||||
/minigzipsh
|
||||
/zlib.pc
|
||||
/zlib-ng.pc
|
||||
/CVE-2003-0107
|
||||
|
||||
.DS_Store
|
||||
*_fuzzer
|
||||
*.obj
|
||||
*.exe
|
||||
*.pdb
|
||||
*.exp
|
||||
*.lib
|
||||
*.dll
|
||||
*.res
|
||||
foo.gz
|
||||
*.manifest
|
||||
*.opensdf
|
||||
*.sln
|
||||
*.sdf
|
||||
*.vcxproj
|
||||
*.vcxproj.filters
|
||||
.vs
|
||||
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
Testing
|
||||
*.cmake
|
||||
*.stackdump
|
||||
zconf.h
|
||||
zconf.h.cmakein
|
||||
zconf.h.included
|
||||
zconf-ng.h
|
||||
zconf-ng.h.cmakein
|
||||
ztest*
|
||||
|
||||
configure.log
|
||||
a.out
|
||||
|
||||
/Makefile
|
||||
/arch/arm/Makefile
|
||||
/arch/generic/Makefile
|
||||
/arch/x86/Makefile
|
||||
.kdev4
|
||||
*.kdev4
|
||||
|
||||
/Debug
|
||||
/example.dir
|
||||
/minigzip.dir
|
||||
/zlib.dir
|
||||
/zlibstatic.dir
|
||||
/win32/Debug
|
||||
|
||||
/.idea
|
||||
/cmake-build-debug
|
||||
283
libs/zlibng/.travis.yml
Normal file
283
libs/zlibng/.travis.yml
Normal file
@ -0,0 +1,283 @@
|
||||
language: c
|
||||
cache: ccache
|
||||
dist: xenial
|
||||
|
||||
env:
|
||||
global:
|
||||
- BUILDDIR=.
|
||||
- MAKER="make -j2"
|
||||
- TESTER="make test"
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: windows
|
||||
compiler: clang
|
||||
env:
|
||||
- GENERATOR="cmake . "
|
||||
- MAKER="cmake --build . --config Release"
|
||||
- TESTER="ctest --verbose -C Release"
|
||||
- os: windows
|
||||
compiler: clang
|
||||
env:
|
||||
- GENERATOR="cmake ..\\zlib-ng -DZLIB_COMPAT=ON"
|
||||
- MAKER="cmake --build . --config Release"
|
||||
- TESTER="ctest --verbose -C Release"
|
||||
- BUILDDIR=..\\build
|
||||
- os: windows
|
||||
compiler: gcc
|
||||
env:
|
||||
- GENERATOR="cmake ."
|
||||
- MAKER="cmake --build . --config Release"
|
||||
- TESTER="ctest --verbose -C Release"
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: GENERATOR="./configure --warn"
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: GENERATOR="cmake . -DZLIB_COMPAT=OFF -DWITH_GZFILEOP=ON -DWITH_NEW_STRATEGIES=YES -DWITH_OPTIM=ON"
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env:
|
||||
- GENERATOR="../zlib-ng/configure --warn --zlib-compat"
|
||||
- BUILDDIR=../build
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: GENERATOR="./configure --warn --zlib-compat --without-optimizations --without-new-strategies"
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: GENERATOR="cmake ."
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env:
|
||||
- GENERATOR="cmake ../zlib-ng"
|
||||
- BUILDDIR=../build
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: GENERATOR="./configure --warn --zlib-compat"
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env:
|
||||
- GENERATOR="cmake ../zlib-ng"
|
||||
- BUILDDIR=../build
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env:
|
||||
- GENERATOR="scan-build -v --status-bugs cmake ../zlib-ng"
|
||||
- MAKER="scan-build -v --status-bugs make"
|
||||
- BUILDDIR=../build
|
||||
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
env: GENERATOR="./configure --warn --zlib-compat"
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
env:
|
||||
- GENERATOR="../zlib-ng/configure --warn --zlib-compat"
|
||||
- BUILDDIR=../build
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
env: GENERATOR="cmake ."
|
||||
|
||||
- os: osx
|
||||
compiler: clang
|
||||
env: GENERATOR="./configure --warn --zlib-compat"
|
||||
- os: osx
|
||||
compiler: clang
|
||||
env:
|
||||
- GENERATOR="cmake ../zlib-ng"
|
||||
- BUILDDIR=../build
|
||||
|
||||
# compiling for linux-ppc64le variants
|
||||
- os: linux-ppc64le
|
||||
compiler: gcc
|
||||
env: GENERATOR="cmake ."
|
||||
- os: linux-ppc64le
|
||||
compiler: gcc
|
||||
env:
|
||||
- GENERATOR="cmake ../zlib-ng"
|
||||
- BUILDDIR=../build
|
||||
|
||||
- os: linux-ppc64le
|
||||
compiler: clang
|
||||
env: GENERATOR="./configure --warn --zlib-compat"
|
||||
- os: linux-ppc64le
|
||||
compiler: clang
|
||||
env:
|
||||
- GENERATOR="cmake ../zlib-ng"
|
||||
- BUILDDIR=../build
|
||||
|
||||
# Cross compiling for arm variants
|
||||
- os: linux
|
||||
compiler: aarch64-linux-gnu-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-aarch64-linux-gnu
|
||||
- libc-dev-arm64-cross
|
||||
# For all aarch64 implementations NEON is mandatory, while crypto/crc are not.
|
||||
env:
|
||||
- GENERATOR="./configure --warn --zlib-compat"
|
||||
- CHOST=aarch64-linux-gnu
|
||||
- os: linux
|
||||
compiler: aarch64-linux-gnu-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-aarch64-linux-gnu
|
||||
- libc-dev-arm64-cross
|
||||
# For all aarch64 implementations NEON is mandatory, while crypto/crc are not.
|
||||
env:
|
||||
- GENERATOR="cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake . -DZLIB_COMPAT=ON"
|
||||
- MAKER="cmake --build . --config Release"
|
||||
- TESTER="ctest --verbose -C Release"
|
||||
- os: linux
|
||||
compiler: aarch64-linux-gnu-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-aarch64-linux-gnu
|
||||
- libc-dev-arm64-cross
|
||||
env:
|
||||
- GENERATOR="./configure --warn --zlib-compat"
|
||||
- CHOST=aarch64-linux-gnu
|
||||
- os: linux
|
||||
compiler: aarch64-linux-gnu-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-aarch64-linux-gnu
|
||||
- libc-dev-arm64-cross
|
||||
env:
|
||||
- GENERATOR="cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake ."
|
||||
- MAKER="cmake --build . --config Release"
|
||||
- TESTER="ctest --verbose -C Release"
|
||||
# Hard-float subsets
|
||||
- os: linux
|
||||
compiler: arm-linux-gnueabihf-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-arm-linux-gnueabihf
|
||||
- libc-dev-armhf-cross
|
||||
env:
|
||||
- GENERATOR="./configure --warn"
|
||||
- CHOST=arm-linux-gnueabihf
|
||||
- os: linux
|
||||
compiler: arm-linux-gnueabihf-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-arm-linux-gnueabihf
|
||||
- libc-dev-armhf-cross
|
||||
env:
|
||||
- GENERATOR="cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake . -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf"
|
||||
- MAKER="cmake --build . --config Release"
|
||||
- TESTER="ctest --verbose -C Release"
|
||||
- os: linux
|
||||
compiler: arm-linux-gnueabihf-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-arm-linux-gnueabihf
|
||||
- libc-dev-armhf-cross
|
||||
env:
|
||||
- GENERATOR="./configure --warn --zlib-compat --without-neon"
|
||||
- CHOST=arm-linux-gnueabihf
|
||||
- os: linux
|
||||
compiler: arm-linux-gnueabihf-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-arm-linux-gnueabihf
|
||||
- libc-dev-armhf-cross
|
||||
env:
|
||||
- GENERATOR="cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake . -DZLIB_COMPAT=ON -DWITH_NEON=OFF -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf"
|
||||
- MAKER="cmake --build . --config Release"
|
||||
- TESTER="ctest --verbose -C Release"
|
||||
- os: linux
|
||||
compiler: arm-linux-gnueabihf-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-arm-linux-gnueabihf
|
||||
- libc-dev-armhf-cross
|
||||
env:
|
||||
- GENERATOR="./configure --warn --zlib-compat"
|
||||
- CHOST=arm-linux-gnueabihf
|
||||
- os: linux
|
||||
compiler: arm-linux-gnueabihf-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-arm-linux-gnueabihf
|
||||
- libc-dev-armhf-cross
|
||||
env:
|
||||
- GENERATOR="cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake . -DZLIB_COMPAT=ON -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf"
|
||||
- MAKER="cmake --build . --config Release"
|
||||
- TESTER="ctest --verbose -C Release"
|
||||
# Soft-float subset
|
||||
- os: linux
|
||||
compiler: arm-linux-gnueabi-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-arm-linux-gnueabi
|
||||
- libc-dev-armel-cross
|
||||
env:
|
||||
- GENERATOR="./configure"
|
||||
- CHOST=arm-linux-gnueabi
|
||||
- os: linux
|
||||
compiler: arm-linux-gnueabi-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-arm-linux-gnueabi
|
||||
- libc-dev-armel-cross
|
||||
env:
|
||||
- GENERATOR="cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake . -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabi"
|
||||
- MAKER="cmake --build . --config Release"
|
||||
- TESTER="ctest --verbose -C Release"
|
||||
- os: linux
|
||||
compiler: arm-linux-gnueabi-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-arm-linux-gnueabi
|
||||
- libc-dev-armel-cross
|
||||
env:
|
||||
- GENERATOR="./configure --zlib-compat"
|
||||
- CHOST=arm-linux-gnueabi
|
||||
- os: linux
|
||||
compiler: arm-linux-gnueabi-gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qemu
|
||||
- gcc-arm-linux-gnueabi
|
||||
- libc-dev-armel-cross
|
||||
env:
|
||||
- GENERATOR="cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake . -DZLIB_COMPAT=ON -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabi"
|
||||
- MAKER="cmake --build . --config Release"
|
||||
- TESTER="ctest --verbose -C Release"
|
||||
|
||||
script:
|
||||
- mkdir -p $BUILDDIR
|
||||
- cd $BUILDDIR
|
||||
- $GENERATOR
|
||||
- $MAKER
|
||||
- $TESTER
|
||||
865
libs/zlibng/CMakeLists.txt
Normal file
865
libs/zlibng/CMakeLists.txt
Normal file
@ -0,0 +1,865 @@
|
||||
cmake_minimum_required(VERSION 3.5.1)
|
||||
if(CMAKE_VERSION VERSION_LESS 3.12)
|
||||
cmake_policy(VERSION ${CMAKE_VERSION})
|
||||
else()
|
||||
cmake_policy(VERSION 3.5.1...3.13.2)
|
||||
endif()
|
||||
|
||||
set(CMAKE_MACOSX_RPATH 1)
|
||||
|
||||
# If not specified on the command line, enable C99 as the default
|
||||
# Configuration items that affect the global compiler envirionment standards
|
||||
# should be issued before the "project" command.
|
||||
if(NOT CMAKE_C_STANDARD)
|
||||
set (CMAKE_C_STANDARD 99) # The C standard whose features are requested to build this target
|
||||
endif()
|
||||
if(NOT CMAKE_C_STANDARD_REQUIRED)
|
||||
set (CMAKE_C_STANDARD_REQUIRED ON) # Boolean describing whether the value of C_STANDARD is a requirement
|
||||
endif()
|
||||
if(NOT CMAKE_C_EXTENSIONS)
|
||||
set (CMAKE_C_EXTENSIONS OFF) # Boolean specifying whether compiler specific extensions are requested
|
||||
endif()
|
||||
set(VALID_C_STANDARDS "99" "11")
|
||||
if(NOT CMAKE_C_STANDARD IN_LIST VALID_C_STANDARDS )
|
||||
MESSAGE(FATAL_ERROR "CMAKE_C_STANDARD:STRING=${CMAKE_C_STANDARD} not in know standards list\n ${VALID_C_STANDARDS}")
|
||||
endif()
|
||||
|
||||
# Parse the full version number from zlib.h and include in ZLIB_FULL_VERSION
|
||||
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib${SUFFIX}.h _zlib_h_contents)
|
||||
string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([0-9]+.[0-9]+.[0-9]+).*\".*"
|
||||
"\\1" ZLIB_HEADER_VERSION ${_zlib_h_contents})
|
||||
string(REGEX REPLACE ".*#define[ \t]+ZLIBNG_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*"
|
||||
"\\1" ZLIBNG_HEADER_VERSION ${_zlib_h_contents})
|
||||
message(STATUS "ZLIB_HEADER_VERSION: ${ZLIB_HEADER_VERSION}")
|
||||
message(STATUS "ZLIBNG_HEADER_VERSION: ${ZLIBNG_HEADER_VERSION}")
|
||||
|
||||
project(zlib
|
||||
VERSION ${ZLIB_HEADER_VERSION}
|
||||
LANGUAGES C)
|
||||
|
||||
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(CMakeDependentOption)
|
||||
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()
|
||||
|
||||
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)
|
||||
check_include_file(sys/sdt.h HAVE_SYS_SDT_H)
|
||||
|
||||
if(CMAKE_OSX_ARCHITECTURES)
|
||||
# If multiple architectures are requested (universal build), pick only the first
|
||||
list(GET CMAKE_OSX_ARCHITECTURES 0 ARCH)
|
||||
else()
|
||||
set(ARCH ${CMAKE_SYSTEM_PROCESSOR})
|
||||
endif()
|
||||
message(STATUS "Architecture: ${ARCH}")
|
||||
if(CMAKE_TOOLCHAIN_FILE)
|
||||
message(STATUS "Using cmake toolchain: ${CMAKE_TOOLCHAIN_FILE}")
|
||||
endif()
|
||||
|
||||
#
|
||||
# Options parsing
|
||||
#
|
||||
option(WITH_GZFILEOP "Compile with support for gzFile related functions" OFF)
|
||||
option(ZLIB_COMPAT "Compile with zlib compatible API" OFF)
|
||||
option(ZLIB_ENABLE_TESTS "Build test binaries" ON)
|
||||
option(WITH_SANITIZERS "Build with address sanitizer and all supported sanitizers other than memory sanitizer" OFF)
|
||||
option(WITH_MSAN "Build with memory sanitizer" OFF)
|
||||
option(WITH_FUZZERS "Build test/fuzz" OFF)
|
||||
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("${ARCH}" MATCHES "arm" OR "${ARCH}" MATCHES "aarch64")
|
||||
option(WITH_ACLE "Build with ACLE CRC" ON)
|
||||
option(WITH_NEON "Build with NEON intrinsics" ON)
|
||||
elseif("${ARCH}" MATCHES "s390x")
|
||||
option(WITH_DFLTCC_DEFLATE "Use DEFLATE CONVERSION CALL instruction for compression on IBM Z" OFF)
|
||||
option(WITH_DFLTCC_INFLATE "Use DEFLATE CONVERSION CALL instruction for decompression on IBM Z" OFF)
|
||||
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_SANITIZERS WITH_SANITIZERS "Build with address sanitizer and all supported sanitizers other than memory sanitizer")
|
||||
add_feature_info(WITH_MSAN WITH_MSAN "Build with memory sanitizer")
|
||||
add_feature_info(WITH_FUZZERS WITH_FUZZERS "Build test/fuzz")
|
||||
add_feature_info(WITH_NEW_STRATEGIES WITH_NEW_STRATEGIES "Use new strategies")
|
||||
if("${ARCH}" MATCHES "arm" OR "${ARCH}" MATCHES "aarch64")
|
||||
add_feature_info(WITH_ACLE WITH_ACLE "Build with ACLE CRC")
|
||||
add_feature_info(WITH_NEON WITH_NEON "Build with NEON intrinsics")
|
||||
endif()
|
||||
|
||||
if (ZLIB_COMPAT)
|
||||
add_definitions(-DZLIB_COMPAT)
|
||||
set(WITH_GZFILEOP ON)
|
||||
set(LIBNAME1 libz)
|
||||
set(LIBNAME2 zlib)
|
||||
set(SUFFIX "")
|
||||
else()
|
||||
set(LIBNAME1 libz-ng)
|
||||
set(LIBNAME2 zlib-ng)
|
||||
set(SUFFIX "-ng")
|
||||
endif()
|
||||
|
||||
if(WITH_GZFILEOP)
|
||||
add_definitions(-DWITH_GZFILEOP)
|
||||
endif()
|
||||
|
||||
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("${ARCH}" MATCHES "arm")
|
||||
add_definitions("-D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1")
|
||||
set(NEONFLAG "/arch:VFPv4")
|
||||
endif()
|
||||
if(WITH_NATIVE_INSTRUCTIONS)
|
||||
message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not supported on this configuration")
|
||||
endif()
|
||||
else()
|
||||
# catch all GNU C compilers as well as Clang and AppleClang
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID 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(__GNUC__ AND "${ARCH}" MATCHES "arm")
|
||||
execute_process(COMMAND ${CMAKE_C_COMPILER} "-dumpmachine"
|
||||
OUTPUT_VARIABLE GCC_MACHINE)
|
||||
if ("${GCC_MACHINE}" MATCHES "eabihf")
|
||||
set(FLOATABI "-mfloat-abi=hard")
|
||||
else()
|
||||
set(FLOATABI "-mfloat-abi=softfp")
|
||||
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()
|
||||
if("${ARCH}" MATCHES "arm")
|
||||
set(ACLEFLAG "-march=armv8-a+crc")
|
||||
set(NEONFLAG "${FLOATABI} -mfpu=neon")
|
||||
elseif("${ARCH}" MATCHES "aarch64")
|
||||
set(ACLEFLAG "-march=armv8-a+crc")
|
||||
set(NEONFLAG "-march=armv8-a+crc+simd")
|
||||
endif()
|
||||
else()
|
||||
set(SSE2FLAG ${NATIVEFLAG})
|
||||
set(SSE4FLAG ${NATIVEFLAG})
|
||||
set(PCLMULFLAG ${NATIVEFLAG})
|
||||
if("${ARCH}" MATCHES "arm")
|
||||
set(ACLEFLAG "${NATIVEFLAG}")
|
||||
set(NEONFLAG "${FLOATABI} -mfpu=neon")
|
||||
elseif("${ARCH}" MATCHES "aarch64")
|
||||
set(ACLEFLAG "${NATIVEFLAG}")
|
||||
set(NEONFLAG "${NATIVEFLAG}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#
|
||||
# Check to see if we have large file support
|
||||
#
|
||||
set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1 -D__USE_LARGEFILE64)
|
||||
# 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 -D__USE_LARGEFILE64)
|
||||
else()
|
||||
check_type_size(_off64_t _OFF64_T)
|
||||
if(HAVE__OFF64_T)
|
||||
add_definitions(-D_LARGEFILE64_SOURCE=1 -D__USE_LARGEFILE64)
|
||||
else()
|
||||
check_type_size(__off64_t __OFF64_T)
|
||||
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)
|
||||
|
||||
if(WITH_SANITIZERS AND WITH_MSAN)
|
||||
message(FATAL_ERROR "Memory sanitizer is incompatible with address sanitizer")
|
||||
endif()
|
||||
|
||||
if(WITH_MSAN)
|
||||
set(CMAKE_REQUIRED_FLAGS "-fsanitize=memory")
|
||||
check_c_source_compiles("int main() { return 0; }" HAS_MSAN FAIL_REGEX "not supported")
|
||||
if(${HAS_MSAN})
|
||||
set(SANITIZERS_FLAGS "-fsanitize=memory")
|
||||
message(STATUS "Adding memory sanitizer flag: ${SANITIZERS_FLAGS}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZERS_FLAGS}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_SANITIZERS)
|
||||
set(_sanitize_flags
|
||||
bool
|
||||
address
|
||||
array-bounds
|
||||
float-divide-by-zero
|
||||
function
|
||||
integer-divide-by-zero
|
||||
return
|
||||
shift
|
||||
signed-integer-overflow
|
||||
undefined
|
||||
unsigned-integer-overflow
|
||||
vla-bound
|
||||
vptr
|
||||
)
|
||||
set(SANITIZERS_FLAGS "")
|
||||
foreach(_flag ${_sanitize_flags})
|
||||
set(CMAKE_REQUIRED_FLAGS "-fsanitize=${_flag}")
|
||||
check_c_source_compiles("int main() { return 0; }"
|
||||
HAS_SANITIZER_${_flag} FAIL_REGEX "not supported")
|
||||
if(${HAS_SANITIZER_${_flag}})
|
||||
if("${SANITIZERS_FLAGS}" STREQUAL "")
|
||||
set(SANITIZERS_FLAGS "-fsanitize=${_flag}")
|
||||
else()
|
||||
set(SANITIZERS_FLAGS "${SANITIZERS_FLAGS},${_flag}")
|
||||
endif()
|
||||
endif()
|
||||
set(CMAKE_REQUIRED_FLAGS)
|
||||
endforeach()
|
||||
message(STATUS "Adding sanitizers flags: ${SANITIZERS_FLAGS}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZERS_FLAGS}")
|
||||
endif()
|
||||
|
||||
#
|
||||
# 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()
|
||||
|
||||
#
|
||||
# check for ptrdiff_t support
|
||||
#
|
||||
check_c_source_compiles(
|
||||
"#include <stddef.h>
|
||||
int main() { ptrdiff_t *a; return 0; }"
|
||||
HAVE_PTRDIFF_T
|
||||
)
|
||||
if(NOT HAVE_PTRDIFF_T)
|
||||
set(NEED_PTRDIFF_T 1)
|
||||
|
||||
check_type_size("void *" SIZEOF_DATA_PTR)
|
||||
message(STATUS "sizeof(void *) is ${SIZEOF_DATA_PTR} bytes")
|
||||
|
||||
if(${SIZEOF_DATA_PTR} MATCHES "4")
|
||||
set(PTRDIFF_TYPE "uint32_t")
|
||||
elseif(${SIZEOF_DATA_PTR} MATCHES "8")
|
||||
set(PTRDIFF_TYPE "uint64_t")
|
||||
else()
|
||||
message(FATAL_ERROR "sizeof(void *) is neither 32 nor 64 bit")
|
||||
endif()
|
||||
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()
|
||||
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DZLIB_DEBUG")
|
||||
|
||||
if(MSVC)
|
||||
set(CMAKE_DEBUG_POSTFIX "d")
|
||||
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
|
||||
add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
|
||||
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
|
||||
)
|
||||
set(CMAKE_REQUIRED_FLAGS)
|
||||
|
||||
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
|
||||
)
|
||||
check_c_source_compile_or_run(
|
||||
"int main(void)
|
||||
{
|
||||
unsigned crc = 0;
|
||||
char c = 'c';
|
||||
crc = __builtin_ia32_crc32qi(crc, c);
|
||||
(void)crc;
|
||||
return 0;
|
||||
}"
|
||||
HAVE_SSE42CRC_INTRIN
|
||||
)
|
||||
set(CMAKE_REQUIRED_FLAGS)
|
||||
|
||||
if(WITH_NATIVE_INSTRUCTIONS)
|
||||
set(CMAKE_REQUIRED_FLAGS "${NATIVEFLAG}")
|
||||
else()
|
||||
set(CMAKE_REQUIRED_FLAGS "${PCLMULFLAG}")
|
||||
endif()
|
||||
if(NOT (APPLE AND ${ARCH} MATCHES "i386"))
|
||||
# The pclmul code currently crashes on Mac in 32bit mode. Avoid for now.
|
||||
check_c_source_compile_or_run(
|
||||
"#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;
|
||||
}"
|
||||
HAVE_PCLMULQDQ_INTRIN
|
||||
)
|
||||
else()
|
||||
set(HAVE_PCLMULQDQ_INTRIN NO)
|
||||
endif()
|
||||
set(CMAKE_REQUIRED_FLAGS)
|
||||
endif()
|
||||
|
||||
# Check whether -mfpu=neon is available
|
||||
set(CMAKE_REQUIRED_FLAGS "-mfpu=neon")
|
||||
check_c_source_compiles(
|
||||
"int main()
|
||||
{
|
||||
return 0;
|
||||
}"
|
||||
MFPU_NEON_AVAILABLE FAIL_REGEX "not supported")
|
||||
set(CMAKE_REQUIRED_FLAGS)
|
||||
|
||||
# FORCE_SSE2 option will only be shown if HAVE_SSE2_INTRIN is true
|
||||
if("${ARCH}" MATCHES "i[3-6]86")
|
||||
cmake_dependent_option(FORCE_SSE2 "Always assume CPU is SSE2 capable" OFF "HAVE_SSE2_INTRIN" OFF)
|
||||
endif()
|
||||
|
||||
#
|
||||
# Enable deflate_medium at level 4-6
|
||||
#
|
||||
if(NOT WITH_NEW_STRATEGIES)
|
||||
add_definitions(-DNO_MEDIUM_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()
|
||||
|
||||
set(ZLIB_ARCH_SRCS)
|
||||
set(ARCHDIR "arch/generic")
|
||||
if("${ARCH}" MATCHES "x86_64" OR "${ARCH}" MATCHES "AMD64" OR "${ARCH}" MATCHES "i[3-6]86")
|
||||
set(ARCHDIR "arch/x86")
|
||||
add_definitions(-DUNALIGNED_OK)
|
||||
add_feature_info(SSE2 1 "Support the SSE2 instruction set, using \"${SSE2FLAG}\"")
|
||||
elseif("${ARCH}" MATCHES "arm" OR "${ARCH}" MATCHES "aarch64")
|
||||
set(ARCHDIR "arch/arm")
|
||||
add_definitions(-DUNALIGNED_OK)
|
||||
elseif("${ARCH}" MATCHES "s390x")
|
||||
set(ARCHDIR "arch/s390")
|
||||
else()
|
||||
message(STATUS "No optimized architecture: using ${ARCHDIR}")
|
||||
endif()
|
||||
if("${ARCH}" MATCHES "arm" OR "${ARCH}" MATCHES "aarch64")
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/armfeature.c ${ARCHDIR}/fill_window_arm.c)
|
||||
endif()
|
||||
if(WITH_OPTIM)
|
||||
if("${ARCH}" MATCHES "arm")
|
||||
if(WITH_ACLE)
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/crc32_acle.c ${ARCHDIR}/insert_string_acle.c)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ACLEFLAG}")
|
||||
add_definitions("-DARM_ACLE_CRC_HASH")
|
||||
add_feature_info(ACLE_CRC 1 "Support CRC hash generation using the ACLE instruction set, using \"${ACLEFLAG}\"")
|
||||
endif()
|
||||
if(WITH_NEON)
|
||||
if(MFPU_NEON_AVAILABLE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${NEONFLAG}")
|
||||
endif()
|
||||
add_definitions("-DARM_NEON_ADLER32")
|
||||
if(MSVC)
|
||||
add_definitions("-D__ARM_NEON__=1")
|
||||
endif(MSVC)
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/adler32_neon.c)
|
||||
add_feature_info(NEON_FILLWINDOW 1 "Support NEON instructions in fill_window_arm, using \"${NEONFLAG}\"")
|
||||
endif()
|
||||
elseif("${ARCH}" MATCHES "aarch64")
|
||||
if(WITH_ACLE)
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/crc32_acle.c ${ARCHDIR}/insert_string_acle.c)
|
||||
add_definitions("-DARM_ACLE_CRC_HASH")
|
||||
add_feature_info(ACLE_CRC 1 "Support CRC hash generation using the ACLE instruction set, using \"${ACLEFLAG}\"")
|
||||
endif()
|
||||
# We need to check WITH_NEON first
|
||||
if(WITH_NEON)
|
||||
add_definitions("-DARM_NEON_ADLER32")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${NEONFLAG}")
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/adler32_neon.c)
|
||||
add_feature_info(NEON_FILLWINDOW 1 "Support NEON instructions in fill_window_arm, using \"${NEONFLAG}\"")
|
||||
elseif(WITH_ACLE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ACLEFLAG}")
|
||||
endif()
|
||||
elseif("${ARCHDIR}" MATCHES "arch/x86")
|
||||
add_definitions("-DX86_CPUID")
|
||||
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(HAVE_SSE42CRC_INTRIN)
|
||||
add_definitions(-DX86_SSE4_2_CRC_INTRIN)
|
||||
endif()
|
||||
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 compression")
|
||||
endif()
|
||||
endif()
|
||||
if(HAVE_SSE2_INTRIN)
|
||||
add_definitions(-DX86_SSE2)
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/fill_window_sse.c)
|
||||
if(NOT ${ARCH} MATCHES "x86_64")
|
||||
add_intrinsics_option("${SSE2FLAG}")
|
||||
add_feature_info(FORCE_SSE2 FORCE_SSE2 "Assume CPU is SSE2 capable")
|
||||
if(FORCE_SSE2)
|
||||
add_definitions(-DX86_NOCHECK_SSE2)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
if(HAVE_PCLMULQDQ_INTRIN)
|
||||
add_definitions(-DX86_PCLMULQDQ_CRC)
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/crc_folding.c)
|
||||
add_intrinsics_option("${PCLMULFLAG}")
|
||||
if(HAVE_SSE42_INTRIN)
|
||||
add_feature_info(PCLMUL_CRC 1 "Support CRC hash generation using PCLMULQDQ, using \"${PCLMULFLAG}\"")
|
||||
else()
|
||||
add_feature_info(PCLMUL_CRC 1 "Support CRC hash generation using PCLMULQDQ, using \"${PCLMULFLAG} ${SSE4FLAG}\"")
|
||||
endif()
|
||||
endif()
|
||||
elseif("${ARCH}" MATCHES "s390x")
|
||||
if(WITH_DFLTCC_DEFLATE OR WITH_DFLTCC_INFLATE)
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/dfltcc_common.c)
|
||||
endif()
|
||||
if(WITH_DFLTCC_DEFLATE)
|
||||
add_definitions(-DS390_DFLTCC_DEFLATE)
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/dfltcc_deflate.c)
|
||||
endif()
|
||||
if(WITH_DFLTCC_INFLATE)
|
||||
add_definitions(-DS390_DFLTCC_INFLATE)
|
||||
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/dfltcc_inflate.c)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
message(STATUS "Architecture-specific source files: ${ZLIB_ARCH_SRCS}")
|
||||
|
||||
#============================================================================
|
||||
# zconf.h
|
||||
#============================================================================
|
||||
|
||||
macro(generate_cmakein input output)
|
||||
file(REMOVE ${output})
|
||||
file(STRINGS ${input} _lines)
|
||||
foreach(_line IN LISTS _lines)
|
||||
file(APPEND ${output} "${_line}\n")
|
||||
|
||||
if (_line STREQUAL "#define ZCONF_H" OR _line STREQUAL "#define ZCONFNG_H")
|
||||
file(APPEND ${output} "#cmakedefine Z_HAVE_UNISTD_H\n")
|
||||
if(NOT HAVE_PTRDIFF_T)
|
||||
file(APPEND ${output} "#cmakedefine NEED_PTRDIFF_T\n")
|
||||
file(APPEND ${output} "#cmakedefine PTRDIFF_TYPE ${PTRDIFF_TYPE}\n")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro(generate_cmakein)
|
||||
|
||||
generate_cmakein( ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.in ${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.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${SUFFIX}.h)
|
||||
message(STATUS "Renaming")
|
||||
message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h")
|
||||
message(STATUS "to 'zconf${SUFFIX}.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${SUFFIX}.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.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${SUFFIX}.h.cmakein)
|
||||
message(STATUS "Renaming")
|
||||
message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.cmakein")
|
||||
message(STATUS "to 'zconf${SUFFIX}.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${SUFFIX}.h.cmakein ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.cmakeincluded)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/${LIBNAME2}.pc)
|
||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein
|
||||
${ZLIB_PC} @ONLY)
|
||||
configure_file(${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h.cmakein
|
||||
${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h @ONLY)
|
||||
|
||||
|
||||
#============================================================================
|
||||
# zlib
|
||||
#============================================================================
|
||||
|
||||
set(ZLIB_PUBLIC_HDRS
|
||||
${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h
|
||||
zlib${SUFFIX}.h
|
||||
)
|
||||
set(ZLIB_PRIVATE_HDRS
|
||||
crc32.h
|
||||
deflate.h
|
||||
functable.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
|
||||
functable.c
|
||||
inflate.c
|
||||
infback.c
|
||||
inftrees.c
|
||||
inffast.c
|
||||
trees.c
|
||||
uncompr.c
|
||||
zutil.c
|
||||
)
|
||||
|
||||
set(ZLIB_GZFILE_SRCS
|
||||
gzclose.c
|
||||
gzlib.c
|
||||
gzread.c
|
||||
gzwrite.c
|
||||
)
|
||||
|
||||
if(NOT MINGW AND NOT MSYS)
|
||||
set(ZLIB_DLL_SRCS
|
||||
win32/zlib${SUFFIX}1.rc # If present will override custom build rule below.
|
||||
)
|
||||
endif()
|
||||
|
||||
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/zlib${SUFFIX}1.rc)
|
||||
set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj)
|
||||
endif()
|
||||
|
||||
add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ARCH_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
|
||||
target_include_directories(zlib PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ARCH_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
|
||||
target_include_directories(zlibstatic PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
if(WITH_GZFILEOP)
|
||||
target_sources(zlib PRIVATE ${ZLIB_GZFILE_SRCS})
|
||||
target_sources(zlibstatic PRIVATE ${ZLIB_GZFILE_SRCS})
|
||||
endif()
|
||||
|
||||
set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)
|
||||
set_target_properties(zlib PROPERTIES SOVERSION 1)
|
||||
|
||||
if (ZLIB_COMPAT)
|
||||
set(ZLIB_FULL_VERSION ${ZLIB_HEADER_VERSION})
|
||||
else()
|
||||
set(ZLIB_FULL_VERSION ${ZLIBNG_HEADER_VERSION})
|
||||
endif()
|
||||
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${SUFFIX})
|
||||
if(NOT APPLE)
|
||||
set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/${LIBNAME2}.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${SUFFIX}.h DESTINATION "${INSTALL_INC_DIR}" RENAME zlib${SUFFIX}.h)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h DESTINATION "${INSTALL_INC_DIR}" RENAME zconf${SUFFIX}.h)
|
||||
endif()
|
||||
if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
|
||||
install(FILES zlib.3 DESTINATION "${INSTALL_MAN_DIR}/man3" RENAME zlib${SUFFIX}.3)
|
||||
endif()
|
||||
if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
|
||||
install(FILES ${ZLIB_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}")
|
||||
endif()
|
||||
|
||||
#============================================================================
|
||||
# Example binaries
|
||||
#============================================================================
|
||||
|
||||
option(ZLIB_ENABLE_TESTS "Build test binaries" ON)
|
||||
if (ZLIB_ENABLE_TESTS)
|
||||
enable_testing()
|
||||
macro(configure_test_executable target)
|
||||
target_link_libraries(${target} zlib)
|
||||
if(NOT WITH_GZFILEOP)
|
||||
target_compile_definitions(${target} PUBLIC -DWITH_GZFILEOP)
|
||||
target_sources(${target} PRIVATE ${ZLIB_GZFILE_SRCS})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
add_executable(example test/example.c)
|
||||
configure_test_executable(example)
|
||||
add_test(NAME example COMMAND example${CMAKE_EXECUTABLE_SUFFIX})
|
||||
|
||||
add_executable(minigzip test/minigzip.c)
|
||||
configure_test_executable(minigzip)
|
||||
|
||||
if(HAVE_OFF64_T)
|
||||
add_executable(example64 test/example.c)
|
||||
configure_test_executable(example64)
|
||||
set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
|
||||
add_test(NAME example64 COMMAND example64${CMAKE_EXECUTABLE_SUFFIX})
|
||||
|
||||
add_executable(minigzip64 test/minigzip.c)
|
||||
configure_test_executable(minigzip64)
|
||||
set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
|
||||
endif()
|
||||
|
||||
if(WITH_FUZZERS)
|
||||
set(FUZZERS checksum compress example_small example_large example_flush example_dict minigzip)
|
||||
file(GLOB ALL_SRC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*")
|
||||
foreach(FUZZER ${FUZZERS})
|
||||
add_executable(${FUZZER}_fuzzer test/fuzz/${FUZZER}_fuzzer.c test/fuzz/standalone_fuzz_target_runner.c)
|
||||
configure_test_executable(${FUZZER}_fuzzer)
|
||||
add_test(${FUZZER}_fuzzer ${FUZZER}_fuzzer${CMAKE_EXECUTABLE_SUFFIX} ${ALL_SRC_FILES})
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
set(CVES CVE-2002-0059 CVE-2004-0797 CVE-2005-1849 CVE-2005-2096)
|
||||
foreach(CVE ${CVES})
|
||||
set(CVE_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:minigzip> -d)
|
||||
add_test(NAME ${CVE}
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
"-DCOMMAND=${CVE_COMMAND}"
|
||||
-DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/${CVE}/test.gz
|
||||
"-DSUCCESS_EXIT=0;1"
|
||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-redirect.cmake)
|
||||
endforeach()
|
||||
|
||||
if(NOT WIN32 AND ZLIB_COMPAT)
|
||||
add_executable(CVE-2003-0107 test/CVE-2003-0107.c)
|
||||
target_link_libraries(CVE-2003-0107 zlib)
|
||||
add_test(NAME CVE-2003-0107 COMMAND CVE-2003-0107)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
FEATURE_SUMMARY(WHAT ALL INCLUDE_QUIET_PACKAGES)
|
||||
|
||||
1521
libs/zlibng/ChangeLog.zlib
Normal file
1521
libs/zlibng/ChangeLog.zlib
Normal file
File diff suppressed because it is too large
Load Diff
374
libs/zlibng/FAQ.zlib
Normal file
374
libs/zlibng/FAQ.zlib
Normal file
@ -0,0 +1,374 @@
|
||||
##
|
||||
# THIS IS AN UNMAINTAINED COPY OF THE ORIGINAL FILE DISTRIBUTED WITH ZLIB 1.2.11
|
||||
##
|
||||
|
||||
|
||||
|
||||
|
||||
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
libs/zlibng/INDEX
Normal file
55
libs/zlibng/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.11
|
||||
FAQ.zlib Frequently Asked Questions about zlib, as distributed in zlib 1.2.11
|
||||
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.11
|
||||
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
|
||||
64
libs/zlibng/INSTALL
Normal file
64
libs/zlibng/INSTALL
Normal file
@ -0,0 +1,64 @@
|
||||
Overview
|
||||
========
|
||||
|
||||
There are several methods for compiling and installing zlib-ng, depending
|
||||
on your favorite operating system and development toolkits.
|
||||
This document will attempt to give a general overview of some of them.
|
||||
|
||||
PS: We do not recommend running 'make install' unless you know what you
|
||||
are doing, as this can override the system default zlib library, and
|
||||
any wrong configuration or incompatability of zlib-ng can make the
|
||||
whole system unusable.
|
||||
|
||||
On linux distros, an alternative way to use zlib-ng instead of zlib
|
||||
for specific programs exist, use LD_PRELOAD.
|
||||
If the program is dynamically linked with zlib, then zlib-ng can take
|
||||
its place without risking system-wide instability. Ex:
|
||||
LD_PRELOAD=/opt/zlib-ng/libz.so.1.2.11.zlib-ng /usr/bin/program
|
||||
|
||||
|
||||
Configure
|
||||
=========
|
||||
|
||||
Using the configure script is currently the main method of setting up the
|
||||
makefiles and preparing for compilation. Configure will attempt to detect
|
||||
the specifics of your system, and enable some of the relevant options for you.
|
||||
|
||||
Configure accepts several command-line options, some of the most important
|
||||
ones are detailed below.
|
||||
|
||||
--zlib-compat
|
||||
This enables options that will ensure that zlib-ng is compiled with all the
|
||||
functions that a standard zlib library contains, you will need to use this
|
||||
if you are going to be using zlib-ng as a drop-in replacement for zlib.
|
||||
|
||||
--without-optimizations
|
||||
This will disable zlib-ng specific optimizations (does not disable strategies).
|
||||
|
||||
--without-new-strategies
|
||||
This will disable specially optimized strategies, such as deflate_quick and
|
||||
deflate_medium.
|
||||
|
||||
Run configure like this:
|
||||
./configure --zlib-compat
|
||||
|
||||
Then you can compile using make:
|
||||
make
|
||||
make test
|
||||
|
||||
|
||||
Cmake
|
||||
=====
|
||||
|
||||
Cmake is an alternative to configure, basically letting you do the same thing,
|
||||
but with different tools and user interfaces.
|
||||
|
||||
Start by initializing cmake:
|
||||
cmake .
|
||||
|
||||
Then you can start the configuration tui to set the wanted options
|
||||
ccmake .
|
||||
|
||||
You can now compile using make:
|
||||
make
|
||||
make test
|
||||
19
libs/zlibng/LICENSE.md
Normal file
19
libs/zlibng/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.
|
||||
365
libs/zlibng/Makefile.in
Normal file
365
libs/zlibng/Makefile.in
Normal file
@ -0,0 +1,365 @@
|
||||
# Makefile for zlib
|
||||
# Copyright (C) 1995-2016 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 -DZLIB_DEBUG
|
||||
#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
|
||||
# -Wstrict-prototypes -Wmissing-prototypes
|
||||
|
||||
SFLAGS=-O
|
||||
LDFLAGS=-L.
|
||||
LIBNAME1=libz-ng
|
||||
LIBNAME2=zlib-ng
|
||||
SUFFIX=-ng
|
||||
TEST_LIBS=$(LIBNAME1).a
|
||||
LDSHARED=$(CC)
|
||||
LDSHAREDFLAGS=-shared
|
||||
|
||||
VER=1.9.9
|
||||
VER1=1
|
||||
|
||||
STATICLIB=$(LIBNAME1).a
|
||||
SHAREDLIB=$(LIBNAME1).so
|
||||
SHAREDLIBV=$(LIBNAME1).so.$(VER)
|
||||
SHAREDLIBM=$(LIBNAME1).so.$(VER1)
|
||||
IMPORTLIB=
|
||||
SHAREDTARGET=$(LIBNAME1).so.$(VER)
|
||||
PKGFILE=$(LIBNAME2).pc
|
||||
|
||||
LIBS=$(STATICLIB) $(SHAREDTARGET)
|
||||
|
||||
AR=ar
|
||||
ARFLAGS=rc
|
||||
DEFFILE=
|
||||
RC=
|
||||
RCFLAGS=
|
||||
RCOBJS=
|
||||
STRIP=
|
||||
RANLIB=ranlib
|
||||
LDCONFIG=ldconfig
|
||||
LDSHAREDLIBC=-lc
|
||||
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 functable.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 functable.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) fuzzers
|
||||
|
||||
shared: examplesh$(EXE) minigzipsh$(EXE)
|
||||
|
||||
all64: example64$(EXE) minigzip64$(EXE)
|
||||
|
||||
check: test
|
||||
|
||||
.SECONDARY:
|
||||
|
||||
$(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
|
||||
|
||||
# This variable is set by configure.
|
||||
WITH_FUZZERS=
|
||||
|
||||
# By default, use our own standalone_fuzz_target_runner.
|
||||
# This runner does no fuzzing, but simply executes the inputs
|
||||
# provided via parameters.
|
||||
# Run e.g. "make all LIB_FUZZING_ENGINE=/path/to/libFuzzer.a"
|
||||
# to link the fuzzer(s) against a real fuzzing engine.
|
||||
ifeq (,$(LIB_FUZZING_ENGINE))
|
||||
LIB_FUZZING_ENGINE = standalone_fuzz_target_runner.o
|
||||
else
|
||||
# OSS-Fuzz will define its own value for LIB_FUZZING_ENGINE.
|
||||
WITH_FUZZERS=1
|
||||
endif
|
||||
|
||||
ifeq (1,$(WITH_FUZZERS))
|
||||
fuzzers: checksum_fuzzer$(EXE) compress_fuzzer$(EXE) example_small_fuzzer$(EXE) example_large_fuzzer$(EXE) example_flush_fuzzer$(EXE) example_dict_fuzzer$(EXE) minigzip_fuzzer$(EXE)
|
||||
else
|
||||
fuzzers:
|
||||
endif
|
||||
|
||||
# The standalone fuzz target runner.
|
||||
standalone_fuzz_target_runner.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
checksum_fuzzer.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
compress_fuzzer.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
example_small_fuzzer.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
example_large_fuzzer.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
example_flush_fuzzer.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
example_dict_fuzzer.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
minigzip_fuzzer.o:
|
||||
$(CC) $(CFLAGS) -DWITH_GZFILEOP $(INCLUDES) -c -o $@ $<
|
||||
checksum_fuzzer$(EXE): checksum_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) checksum_fuzzer.o $(STATICLIB) -lpthread
|
||||
compress_fuzzer$(EXE): compress_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) compress_fuzzer.o $(STATICLIB) -lpthread
|
||||
example_small_fuzzer$(EXE): example_small_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) example_small_fuzzer.o $(STATICLIB) -lpthread
|
||||
example_large_fuzzer$(EXE): example_large_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) example_large_fuzzer.o $(STATICLIB) -lpthread
|
||||
example_flush_fuzzer$(EXE): example_flush_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) example_flush_fuzzer.o $(STATICLIB) -lpthread
|
||||
example_dict_fuzzer$(EXE): example_dict_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) example_dict_fuzzer.o $(STATICLIB) -lpthread
|
||||
minigzip_fuzzer$(EXE): minigzip_fuzzer.o standalone_fuzz_target_runner.o $(OBJG) $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) minigzip_fuzzer.o $(OBJG) $(STATICLIB) -lpthread
|
||||
|
||||
infcover.o: $(SRCDIR)/test/infcover.c $(SRCDIR)/zlib$(SUFFIX).h zconf$(SUFFIX).h
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/test/infcover.c
|
||||
|
||||
infcover$(EXE): infcover.o $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -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:
|
||||
$(CC) $(CFLAGS) -DWITH_GZFILEOP $(INCLUDES) -c -o $@ $(SRCDIR)/test/example.c
|
||||
|
||||
minigzip.o:
|
||||
$(CC) $(CFLAGS) -DWITH_GZFILEOP $(INCLUDES) -c -o $@ $(SRCDIR)/test/minigzip.c
|
||||
|
||||
example64.o:
|
||||
$(CC) $(CFLAGS) -DWITH_GZFILEOP -D_FILE_OFFSET_BITS=64 $(INCLUDES) -c -o $@ $(SRCDIR)/test/example.c
|
||||
|
||||
minigzip64.o:
|
||||
$(CC) $(CFLAGS) -DWITH_GZFILEOP -D_FILE_OFFSET_BITS=64 $(INCLUDES) -c -o $@ $(SRCDIR)/test/minigzip.c
|
||||
|
||||
zlibrc.o: win32/zlib$(SUFFIX)1.rc
|
||||
$(RC) $(RCFLAGS) -o $@ win32/zlib$(SUFFIX)1.rc
|
||||
|
||||
.SUFFIXES: .lo
|
||||
|
||||
%.o: $(SRCDIR)/%.c
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
|
||||
%.lo: $(SRCDIR)/%.c
|
||||
$(CC) $(SFLAGS) -DPIC $(INCLUDES) -c -o $@ $<
|
||||
|
||||
$(OBJG): %.o: $(SRCDIR)/%.c
|
||||
$(CC) $(CFLAGS) -DWITH_GZFILEOP $(INCLUDES) -c -o $@ $<
|
||||
|
||||
$(SHAREDTARGET): $(PIC_OBJS) $(DEFFILE) $(RCOBJS)
|
||||
ifneq ($(SHAREDTARGET),)
|
||||
$(LDSHARED) $(LDSHAREDFLAGS) $(LDFLAGS) -o $@ $(DEFFILE) $(PIC_OBJS) $(RCOBJS) $(LDSHAREDLIBC)
|
||||
ifneq ($(STRIP),)
|
||||
$(STRIP) $@
|
||||
endif
|
||||
ifneq ($(SHAREDLIB),$(SHAREDTARGET))
|
||||
rm -f $(SHAREDLIB) $(SHAREDLIBM)
|
||||
ln -s $@ $(SHAREDLIB)
|
||||
ln -s $@ $(SHAREDLIBM)
|
||||
endif
|
||||
endif
|
||||
|
||||
example$(EXE): example.o $(OBJG) $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -o $@ example.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC)
|
||||
ifneq ($(STRIP),)
|
||||
$(STRIP) $@
|
||||
endif
|
||||
|
||||
minigzip$(EXE): minigzip.o $(OBJG) $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -o $@ minigzip.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC)
|
||||
ifneq ($(STRIP),)
|
||||
$(STRIP) $@
|
||||
endif
|
||||
|
||||
examplesh$(EXE): example.o $(OBJG) $(SHAREDTARGET)
|
||||
$(CC) $(LDFLAGS) -o $@ example.o $(OBJG) $(SHAREDTARGET) $(LDSHAREDLIBC)
|
||||
ifneq ($(STRIP),)
|
||||
$(STRIP) $@
|
||||
endif
|
||||
|
||||
minigzipsh$(EXE): minigzip.o $(OBJG) $(SHAREDTARGET)
|
||||
$(CC) $(LDFLAGS) -o $@ minigzip.o $(OBJG) $(SHAREDTARGET) $(LDSHAREDLIBC)
|
||||
ifneq ($(STRIP),)
|
||||
$(STRIP) $@
|
||||
endif
|
||||
|
||||
example64$(EXE): example64.o $(OBJG) $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -o $@ example64.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC)
|
||||
ifneq ($(STRIP),)
|
||||
$(STRIP) $@
|
||||
endif
|
||||
|
||||
minigzip64$(EXE): minigzip64.o $(OBJG) $(STATICLIB)
|
||||
$(CC) $(LDFLAGS) -o $@ minigzip64.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC)
|
||||
ifneq ($(STRIP),)
|
||||
$(STRIP) $@
|
||||
endif
|
||||
|
||||
install-shared: $(SHAREDTARGET)
|
||||
ifneq ($(SHAREDTARGET),)
|
||||
-@if [ ! -d $(DESTDIR)$(sharedlibdir) ]; then mkdir -p $(DESTDIR)$(sharedlibdir); fi
|
||||
rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDTARGET)
|
||||
cp $(SHAREDTARGET) $(DESTDIR)$(sharedlibdir)
|
||||
chmod 755 $(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
|
||||
rm -f $(DESTDIR)$(libdir)/$(STATICLIB)
|
||||
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
|
||||
rm -f $(DESTDIR)$(man3dir)/zlib$(SUFFIX).3
|
||||
cp $(SRCDIR)/zlib.3 $(DESTDIR)$(man3dir)/zlib$(SUFFIX).3
|
||||
chmod 644 $(DESTDIR)$(man3dir)/zlib$(SUFFIX).3
|
||||
rm -f $(DESTDIR)$(pkgconfigdir)/$(PKGFILE)
|
||||
cp $(PKGFILE) $(DESTDIR)$(pkgconfigdir)
|
||||
chmod 644 $(DESTDIR)$(pkgconfigdir)/$(PKGFILE)
|
||||
|
||||
install: install-libs
|
||||
-@if [ ! -d $(DESTDIR)$(includedir) ]; then mkdir -p $(DESTDIR)$(includedir); fi
|
||||
rm -f $(DESTDIR)$(includedir)/zlib$(SUFFIX).h $(DESTDIR)$(includedir)/zconf$(SUFFIX).h
|
||||
cp $(SRCDIR)/zlib$(SUFFIX).h $(DESTDIR)$(includedir)/zlib$(SUFFIX).h
|
||||
cp zconf$(SUFFIX).h $(DESTDIR)$(includedir)/zconf$(SUFFIX).h
|
||||
chmod 644 $(DESTDIR)$(includedir)/zlib$(SUFFIX).h $(DESTDIR)$(includedir)/zconf$(SUFFIX).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$(SUFFIX).h zconf$(SUFFIX).h
|
||||
cd $(DESTDIR)$(man3dir) && rm -f zlib$(SUFFIX).3
|
||||
cd $(DESTDIR)$(pkgconfigdir) && rm -f $(PKGFILE)
|
||||
|
||||
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) \
|
||||
checksum_fuzzer$(EXE) compress_fuzzer$(EXE) example_small_fuzzer$(EXE) example_large_fuzzer$(EXE) \
|
||||
example_flush_fuzzer$(EXE) example_dict_fuzzer$(EXE) minigzip_fuzzer$(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 a.exe
|
||||
rm -f *.pc
|
||||
|
||||
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 $(PKGFILE) 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\t$(MAKE) -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 ; \
|
||||
grep -v '^#cmakedefine' $(SRCDIR)/zconf.h.in > zconf.h.cmakein &&\
|
||||
touch -r $(SRCDIR)/zconf.h.in zconf.h.cmakein ; 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]
|
||||
81
libs/zlibng/README.md
Normal file
81
libs/zlibng/README.md
Normal file
@ -0,0 +1,81 @@
|
||||
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 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 various reasons.
|
||||
|
||||
A lot of improvements have gone into zlib-ng since its start, and
|
||||
numerous people have contributed both small and big improvements,
|
||||
or valuable testing.
|
||||
|
||||
Please read LICENSE.md, it is very simple and very liberal.
|
||||
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
Zlib-ng is a young project, and we aim to be open to contributions,
|
||||
and we would be delighted to receive pull requests on github.
|
||||
Just remember that any code you submit must be your own and it must
|
||||
be zlib licensed.
|
||||
Help with testing and reviewing of pull requests etc is also very
|
||||
much appreciated.
|
||||
|
||||
If you are interested in contributing, please consider joining our
|
||||
IRC channel #zlib-ng on the Freenode IRC network.
|
||||
|
||||
|
||||
Acknowledgments
|
||||
----------------
|
||||
|
||||
Thanks to Servebolt.com for sponsoring my maintainership of zlib-ng.
|
||||
|
||||
Thanks go out to all the people and companies who have taken the time
|
||||
to contribute code reviews, testing and/or patches. Zlib-ng would not
|
||||
have been nearly as good without you.
|
||||
|
||||
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).
|
||||
|
||||
|
||||
Build Status
|
||||
------------
|
||||
|
||||
Travis CI: [](https://travis-ci.org/zlib-ng/zlib-ng/)
|
||||
Buildkite: [](https://buildkite.com/circlestorm-productions/zlib-ng)
|
||||
118
libs/zlibng/README.zlib
Normal file
118
libs/zlibng/README.zlib
Normal file
@ -0,0 +1,118 @@
|
||||
ZLIB DATA COMPRESSION LIBRARY
|
||||
|
||||
zlib 1.2.11 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.11 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-2017 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. We make all
|
||||
contributions to and distributions of this project solely in our personal
|
||||
capacity, and are not conveying any rights to any intellectual property of
|
||||
any third parties.
|
||||
|
||||
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.
|
||||
132
libs/zlibng/adler32.c
Normal file
132
libs/zlibng/adler32.c
Normal file
@ -0,0 +1,132 @@
|
||||
/* adler32.c -- compute the Adler-32 checksum of a data stream
|
||||
* Copyright (C) 1995-2011, 2016 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#include "zbuild.h"
|
||||
#include "zutil.h"
|
||||
#include "functable.h"
|
||||
#include "adler32_p.h"
|
||||
|
||||
uint32_t adler32_c(uint32_t adler, const unsigned char *buf, size_t len);
|
||||
static uint32_t adler32_combine_(uint32_t adler1, uint32_t adler2, z_off64_t len2);
|
||||
|
||||
#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);
|
||||
|
||||
/* ========================================================================= */
|
||||
uint32_t adler32_c(uint32_t adler, const unsigned char *buf, size_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)
|
||||
return adler32_len_1(adler, buf, sum2);
|
||||
|
||||
/* initial Adler-32 value (deferred check for len == 1 speed) */
|
||||
if (buf == NULL)
|
||||
return 1L;
|
||||
|
||||
/* in case short lengths are provided, keep it somewhat fast */
|
||||
if (len < 16)
|
||||
return adler32_len_16(adler, buf, len, sum2);
|
||||
|
||||
/* do length NMAX blocks -- requires just one modulo operation */
|
||||
while (len >= NMAX) {
|
||||
len -= NMAX;
|
||||
#ifdef UNROLL_MORE
|
||||
n = NMAX / 16; /* NMAX is divisible by 16 */
|
||||
#else
|
||||
n = NMAX / 8; /* NMAX is divisible by 8 */
|
||||
#endif
|
||||
do {
|
||||
#ifdef UNROLL_MORE
|
||||
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 */
|
||||
#ifdef UNROLL_MORE
|
||||
while (len >= 16) {
|
||||
len -= 16;
|
||||
DO16(buf);
|
||||
buf += 16;
|
||||
#else
|
||||
while (len >= 8) {
|
||||
len -= 8;
|
||||
DO8(buf, 0);
|
||||
buf += 8;
|
||||
#endif
|
||||
}
|
||||
while (len) {
|
||||
--len;
|
||||
adler += *buf++;
|
||||
sum2 += adler;
|
||||
}
|
||||
MOD(adler);
|
||||
MOD(sum2);
|
||||
}
|
||||
|
||||
/* return recombined sums */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
uint32_t ZEXPORT PREFIX(adler32_z)(uint32_t adler, const unsigned char *buf, size_t len) {
|
||||
return functable.adler32(adler, buf, len);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uint32_t ZEXPORT PREFIX(adler32)(uint32_t adler, const unsigned char *buf, uint32_t len) {
|
||||
return functable.adler32(adler, buf, len);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
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 PREFIX(adler32_combine)(uint32_t adler1, uint32_t adler2, z_off_t len2) {
|
||||
return adler32_combine_(adler1, adler2, len2);
|
||||
}
|
||||
|
||||
uint32_t ZEXPORT PREFIX(adler32_combine64)(uint32_t adler1, uint32_t adler2, z_off64_t len2) {
|
||||
return adler32_combine_(adler1, adler2, len2);
|
||||
}
|
||||
77
libs/zlibng/adler32_p.h
Normal file
77
libs/zlibng/adler32_p.h
Normal file
@ -0,0 +1,77 @@
|
||||
/* adler32_p.h -- Private inline functions and macros shared with
|
||||
* different computation of the Adler-32 checksum
|
||||
* of a data stream.
|
||||
* Copyright (C) 1995-2011, 2016 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifndef ADLER32_P_H
|
||||
#define ADLER32_P_H
|
||||
|
||||
#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 */
|
||||
|
||||
/* 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
|
||||
|
||||
static inline uint32_t adler32_len_1(uint32_t adler, const unsigned char *buf, uint32_t sum2) {
|
||||
adler += buf[0];
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
sum2 += adler;
|
||||
if (sum2 >= BASE)
|
||||
sum2 -= BASE;
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
static inline uint32_t adler32_len_16(uint32_t adler, const unsigned char *buf, size_t len, uint32_t sum2) {
|
||||
while (len) {
|
||||
--len;
|
||||
adler += *buf++;
|
||||
sum2 += adler;
|
||||
}
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
MOD28(sum2); /* only added so many BASE's */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
#endif /* ADLER32_P_H */
|
||||
2
libs/zlibng/arch/.gitignore
vendored
Normal file
2
libs/zlibng/arch/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# ignore Makefiles; they're all automatically generated
|
||||
Makefile
|
||||
54
libs/zlibng/arch/arm/Makefile.in
Normal file
54
libs/zlibng/arch/arm/Makefile.in
Normal file
@ -0,0 +1,54 @@
|
||||
# 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=
|
||||
SUFFIX=
|
||||
|
||||
SRCDIR=.
|
||||
SRCTOP=../..
|
||||
TOPDIR=$(SRCTOP)
|
||||
|
||||
all: adler32_neon.o adler32_neon.lo armfeature.o armfeature.lo crc32_acle.o crc32_acle.lo fill_window_arm.o fill_window_arm.lo insert_string_acle.o insert_string_acle.lo
|
||||
|
||||
adler32_neon.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_neon.c
|
||||
|
||||
adler32_neon.lo:
|
||||
$(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_neon.c
|
||||
|
||||
armfeature.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/armfeature.c
|
||||
|
||||
armfeature.lo:
|
||||
$(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/armfeature.c
|
||||
|
||||
crc32_acle.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_acle.c
|
||||
|
||||
crc32_acle.lo:
|
||||
$(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_acle.c
|
||||
|
||||
fill_window_arm.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/fill_window_arm.c
|
||||
|
||||
fill_window_arm.lo:
|
||||
$(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/fill_window_arm.c
|
||||
|
||||
insert_string_acle.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_acle.c
|
||||
|
||||
insert_string_acle.lo:
|
||||
$(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_acle.c
|
||||
|
||||
mostlyclean: clean
|
||||
clean:
|
||||
rm -f *.o *.lo *~
|
||||
rm -rf objs
|
||||
rm -f *.gcda *.gcno *.gcov
|
||||
|
||||
distclean:
|
||||
rm -f Makefile
|
||||
134
libs/zlibng/arch/arm/adler32_neon.c
Normal file
134
libs/zlibng/arch/arm/adler32_neon.c
Normal file
@ -0,0 +1,134 @@
|
||||
/* Copyright (C) 1995-2011, 2016 Mark Adler
|
||||
* Copyright (C) 2017 ARM Holdings Inc.
|
||||
* Author: Adenilson Cavalcanti <adenilson.cavalcanti@arm.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include "adler32_neon.h"
|
||||
#if defined(__ARM_NEON__) || defined(__ARM_NEON)
|
||||
#include <arm_neon.h>
|
||||
#include "adler32_p.h"
|
||||
|
||||
static void NEON_accum32(uint32_t *s, const unsigned char *buf, size_t len) {
|
||||
static const uint8_t taps[32] = {
|
||||
32, 31, 30, 29, 28, 27, 26, 25,
|
||||
24, 23, 22, 21, 20, 19, 18, 17,
|
||||
16, 15, 14, 13, 12, 11, 10, 9,
|
||||
8, 7, 6, 5, 4, 3, 2, 1 };
|
||||
|
||||
uint32x2_t adacc2, s2acc2, as;
|
||||
uint8x16_t t0 = vld1q_u8(taps), t1 = vld1q_u8(taps + 16);
|
||||
|
||||
uint32x4_t adacc = vdupq_n_u32(0), s2acc = vdupq_n_u32(0);
|
||||
adacc = vsetq_lane_u32(s[0], adacc, 0);
|
||||
s2acc = vsetq_lane_u32(s[1], s2acc, 0);
|
||||
|
||||
while (len >= 2) {
|
||||
uint8x16_t d0 = vld1q_u8(buf), d1 = vld1q_u8(buf + 16);
|
||||
uint16x8_t adler, sum2;
|
||||
s2acc = vaddq_u32(s2acc, vshlq_n_u32(adacc, 5));
|
||||
adler = vpaddlq_u8( d0);
|
||||
adler = vpadalq_u8(adler, d1);
|
||||
sum2 = vmull_u8( vget_low_u8(t0), vget_low_u8(d0));
|
||||
sum2 = vmlal_u8(sum2, vget_high_u8(t0), vget_high_u8(d0));
|
||||
sum2 = vmlal_u8(sum2, vget_low_u8(t1), vget_low_u8(d1));
|
||||
sum2 = vmlal_u8(sum2, vget_high_u8(t1), vget_high_u8(d1));
|
||||
adacc = vpadalq_u16(adacc, adler);
|
||||
s2acc = vpadalq_u16(s2acc, sum2);
|
||||
len -= 2;
|
||||
buf += 32;
|
||||
}
|
||||
|
||||
while (len > 0) {
|
||||
uint8x16_t d0 = vld1q_u8(buf);
|
||||
uint16x8_t adler, sum2;
|
||||
s2acc = vaddq_u32(s2acc, vshlq_n_u32(adacc, 4));
|
||||
adler = vpaddlq_u8(d0);
|
||||
sum2 = vmull_u8( vget_low_u8(t1), vget_low_u8(d0));
|
||||
sum2 = vmlal_u8(sum2, vget_high_u8(t1), vget_high_u8(d0));
|
||||
adacc = vpadalq_u16(adacc, adler);
|
||||
s2acc = vpadalq_u16(s2acc, sum2);
|
||||
buf += 16;
|
||||
len--;
|
||||
}
|
||||
|
||||
adacc2 = vpadd_u32(vget_low_u32(adacc), vget_high_u32(adacc));
|
||||
s2acc2 = vpadd_u32(vget_low_u32(s2acc), vget_high_u32(s2acc));
|
||||
as = vpadd_u32(adacc2, s2acc2);
|
||||
s[0] = vget_lane_u32(as, 0);
|
||||
s[1] = vget_lane_u32(as, 1);
|
||||
}
|
||||
|
||||
static void NEON_handle_tail(uint32_t *pair, const unsigned char *buf, size_t len) {
|
||||
unsigned int i;
|
||||
for (i = 0; i < len; ++i) {
|
||||
pair[0] += buf[i];
|
||||
pair[1] += pair[0];
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t adler32_neon(uint32_t adler, const unsigned char *buf, size_t len) {
|
||||
/* split Adler-32 into component sums */
|
||||
uint32_t sum2 = (adler >> 16) & 0xffff;
|
||||
adler &= 0xffff;
|
||||
|
||||
/* in case user likes doing a byte at a time, keep it fast */
|
||||
if (len == 1)
|
||||
return adler32_len_1(adler, buf, sum2);
|
||||
|
||||
/* initial Adler-32 value (deferred check for len == 1 speed) */
|
||||
if (buf == NULL)
|
||||
return 1L;
|
||||
|
||||
/* in case short lengths are provided, keep it somewhat fast */
|
||||
if (len < 16)
|
||||
return adler32_len_16(adler, buf, len, sum2);
|
||||
|
||||
uint32_t pair[2];
|
||||
int n = NMAX;
|
||||
unsigned int done = 0;
|
||||
unsigned int i;
|
||||
|
||||
/* Split Adler-32 into component sums, it can be supplied by
|
||||
* the caller sites (e.g. in a PNG file).
|
||||
*/
|
||||
pair[0] = adler;
|
||||
pair[1] = sum2;
|
||||
|
||||
for (i = 0; i < len; i += n) {
|
||||
if ((i + n) > len)
|
||||
n = len - i;
|
||||
|
||||
if (n < 16)
|
||||
break;
|
||||
|
||||
NEON_accum32(pair, buf + i, n / 16);
|
||||
pair[0] %= BASE;
|
||||
pair[1] %= BASE;
|
||||
|
||||
done += (n / 16) * 16;
|
||||
}
|
||||
|
||||
/* Handle the tail elements. */
|
||||
if (done < len) {
|
||||
NEON_handle_tail(pair, (buf + done), len - done);
|
||||
pair[0] %= BASE;
|
||||
pair[1] %= BASE;
|
||||
}
|
||||
|
||||
/* D = B * 65536 + A, see: https://en.wikipedia.org/wiki/Adler-32. */
|
||||
return (pair[1] << 16) | pair[0];
|
||||
}
|
||||
#endif
|
||||
29
libs/zlibng/arch/arm/adler32_neon.h
Normal file
29
libs/zlibng/arch/arm/adler32_neon.h
Normal file
@ -0,0 +1,29 @@
|
||||
/* Copyright (C) 1995-2011, 2016 Mark Adler
|
||||
* Copyright (C) 2017 ARM Holdings Inc.
|
||||
* Author: Adenilson Cavalcanti <adenilson.cavalcanti@arm.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef __ADLER32_NEON__
|
||||
#define __ADLER32_NEON__
|
||||
|
||||
#if defined(__ARM_NEON__) || defined(__ARM_NEON)
|
||||
// Depending on the compiler flavor, size_t may be defined in one or the other header. See:
|
||||
// http://stackoverflow.com/questions/26410466/gcc-linaro-compiler-throws-error-unknown-type-name-size-t
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
uint32_t adler32_neon(uint32_t adler, const unsigned char *buf, size_t len);
|
||||
#endif
|
||||
#endif
|
||||
13
libs/zlibng/arch/arm/arm.h
Normal file
13
libs/zlibng/arch/arm/arm.h
Normal file
@ -0,0 +1,13 @@
|
||||
/* arm.h -- check for ARM features.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifndef ARM_H_
|
||||
#define ARM_H_
|
||||
|
||||
extern int arm_cpu_has_neon;
|
||||
extern int arm_cpu_has_crc32;
|
||||
|
||||
void ZLIB_INTERNAL arm_check_features(void);
|
||||
|
||||
#endif /* ARM_H_ */
|
||||
50
libs/zlibng/arch/arm/armfeature.c
Normal file
50
libs/zlibng/arch/arm/armfeature.c
Normal file
@ -0,0 +1,50 @@
|
||||
#include "zutil.h"
|
||||
|
||||
#if defined(__linux__)
|
||||
# include <sys/auxv.h>
|
||||
# include <asm/hwcap.h>
|
||||
#elif defined(_WIN32)
|
||||
# include <winapifamily.h>
|
||||
#endif
|
||||
|
||||
static int arm_has_crc32() {
|
||||
#if defined(__linux__) && defined(HWCAP2_CRC32)
|
||||
return (getauxval(AT_HWCAP2) & HWCAP2_CRC32) != 0 ? 1 : 0;
|
||||
#elif defined(ARM_NOCHECK_ACLE)
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* AArch64 has neon. */
|
||||
#if !defined(__aarch64__)
|
||||
static inline int arm_has_neon()
|
||||
{
|
||||
#if defined(__linux__) && defined(HWCAP_NEON)
|
||||
return (getauxval(AT_HWCAP) & HWCAP_NEON) != 0 ? 1 : 0;
|
||||
#elif defined(_M_ARM) && defined(WINAPI_FAMILY_PARTITION)
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
|
||||
return 1; /* Always supported */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(ARM_NOCHECK_NEON)
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
ZLIB_INTERNAL int arm_cpu_has_neon;
|
||||
ZLIB_INTERNAL int arm_cpu_has_crc32;
|
||||
|
||||
void ZLIB_INTERNAL arm_check_features(void) {
|
||||
#if defined(__aarch64__)
|
||||
arm_cpu_has_neon = 1; /* always available */
|
||||
#else
|
||||
arm_cpu_has_neon = arm_has_neon();
|
||||
#endif
|
||||
arm_cpu_has_crc32 = arm_has_crc32();
|
||||
}
|
||||
115
libs/zlibng/arch/arm/crc32_acle.c
Normal file
115
libs/zlibng/arch/arm/crc32_acle.c
Normal file
@ -0,0 +1,115 @@
|
||||
/* crc32_acle.c -- compute the CRC-32 of a data stream
|
||||
* Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler
|
||||
* Copyright (C) 2016 Yang Zhang
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __ARM_FEATURE_CRC32
|
||||
# include <arm_acle.h>
|
||||
# ifdef ZLIB_COMPAT
|
||||
# include <zconf.h>
|
||||
# else
|
||||
# include <zconf-ng.h>
|
||||
# endif
|
||||
# ifdef __linux__
|
||||
# include <stddef.h>
|
||||
# endif
|
||||
|
||||
uint32_t crc32_acle(uint32_t crc, const unsigned char *buf, uint64_t len) {
|
||||
register uint32_t c;
|
||||
register const uint16_t *buf2;
|
||||
register const uint32_t *buf4;
|
||||
|
||||
c = ~crc;
|
||||
if (len && ((ptrdiff_t)buf & 1)) {
|
||||
c = __crc32b(c, *buf++);
|
||||
len--;
|
||||
}
|
||||
|
||||
if ((len > sizeof(uint16_t)) && ((ptrdiff_t)buf & sizeof(uint16_t))) {
|
||||
buf2 = (const uint16_t *) buf;
|
||||
c = __crc32h(c, *buf2++);
|
||||
len -= sizeof(uint16_t);
|
||||
buf4 = (const uint32_t *) buf2;
|
||||
} else {
|
||||
buf4 = (const uint32_t *) buf;
|
||||
}
|
||||
|
||||
# if defined(__aarch64__)
|
||||
if ((len > sizeof(uint32_t)) && ((ptrdiff_t)buf & sizeof(uint32_t))) {
|
||||
c = __crc32w(c, *buf4++);
|
||||
len -= sizeof(uint32_t);
|
||||
}
|
||||
|
||||
const uint64_t *buf8 = (const uint64_t *) buf4;
|
||||
|
||||
# ifdef UNROLL_MORE
|
||||
while (len >= 4 * sizeof(uint64_t)) {
|
||||
c = __crc32d(c, *buf8++);
|
||||
c = __crc32d(c, *buf8++);
|
||||
c = __crc32d(c, *buf8++);
|
||||
c = __crc32d(c, *buf8++);
|
||||
len -= 4 * sizeof(uint64_t);
|
||||
}
|
||||
# endif
|
||||
|
||||
while (len >= sizeof(uint64_t)) {
|
||||
c = __crc32d(c, *buf8++);
|
||||
len -= sizeof(uint64_t);
|
||||
}
|
||||
|
||||
if (len >= sizeof(uint32_t)) {
|
||||
buf4 = (const uint32_t *) buf8;
|
||||
c = __crc32w(c, *buf4++);
|
||||
len -= sizeof(uint32_t);
|
||||
buf2 = (const uint16_t *) buf4;
|
||||
} else {
|
||||
buf2 = (const uint16_t *) buf8;
|
||||
}
|
||||
|
||||
if (len >= sizeof(uint16_t)) {
|
||||
c = __crc32h(c, *buf2++);
|
||||
len -= sizeof(uint16_t);
|
||||
}
|
||||
|
||||
buf = (const unsigned char *) buf2;
|
||||
# else /* __aarch64__ */
|
||||
|
||||
# ifdef UNROLL_MORE
|
||||
while (len >= 8 * sizeof(uint32_t)) {
|
||||
c = __crc32w(c, *buf4++);
|
||||
c = __crc32w(c, *buf4++);
|
||||
c = __crc32w(c, *buf4++);
|
||||
c = __crc32w(c, *buf4++);
|
||||
c = __crc32w(c, *buf4++);
|
||||
c = __crc32w(c, *buf4++);
|
||||
c = __crc32w(c, *buf4++);
|
||||
c = __crc32w(c, *buf4++);
|
||||
len -= 8 * sizeof(uint32_t);
|
||||
}
|
||||
# endif
|
||||
|
||||
while (len >= sizeof(uint32_t)) {
|
||||
c = __crc32w(c, *buf4++);
|
||||
len -= sizeof(uint32_t);
|
||||
}
|
||||
|
||||
if (len >= sizeof(uint16_t)) {
|
||||
buf2 = (const uint16_t *) buf4;
|
||||
c = __crc32h(c, *buf2++);
|
||||
len -= sizeof(uint16_t);
|
||||
buf = (const unsigned char *) buf2;
|
||||
} else {
|
||||
buf = (const unsigned char *) buf4;
|
||||
}
|
||||
# endif /* __aarch64__ */
|
||||
|
||||
if (len) {
|
||||
c = __crc32b(c, *buf);
|
||||
}
|
||||
|
||||
c = ~c;
|
||||
return c;
|
||||
}
|
||||
#endif /* __ARM_FEATURE_CRC32 */
|
||||
12
libs/zlibng/arch/arm/ctzl.h
Normal file
12
libs/zlibng/arch/arm/ctzl.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef ARM_CTZL_H
|
||||
#define ARM_CTZL_H
|
||||
|
||||
#include <armintr.h>
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
static __forceinline unsigned long __builtin_ctzl(unsigned long value) {
|
||||
return _arm_clz(_arm_rbit(value));
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
169
libs/zlibng/arch/arm/fill_window_arm.c
Normal file
169
libs/zlibng/arch/arm/fill_window_arm.c
Normal file
@ -0,0 +1,169 @@
|
||||
/* fill_window_arm.c -- Optimized hash table shifting for ARM with support for NEON instructions
|
||||
* Copyright (C) 2017 Mika T. Lindqvist
|
||||
*
|
||||
* Authors:
|
||||
* Mika T. Lindqvist <postmaster@raasu.org>
|
||||
* Jun He <jun.he@arm.com>
|
||||
*
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#include "zbuild.h"
|
||||
#include "deflate.h"
|
||||
#include "deflate_p.h"
|
||||
#include "functable.h"
|
||||
|
||||
extern ZLIB_INTERNAL int read_buf(PREFIX3(stream) *strm, unsigned char *buf, unsigned size);
|
||||
|
||||
#if defined(__ARM_NEON__) || defined(__ARM_NEON)
|
||||
#include <arm_neon.h>
|
||||
|
||||
/* SIMD version of hash_chain rebase */
|
||||
static inline void slide_hash_chain(Pos *table, unsigned int entries, uint16_t window_size) {
|
||||
register uint16x8_t v, *p;
|
||||
register size_t n;
|
||||
|
||||
size_t size = entries*sizeof(table[0]);
|
||||
Assert((size % sizeof(uint16x8_t) * 8 == 0), "hash table size err");
|
||||
|
||||
Assert(sizeof(Pos) == 2, "Wrong Pos size");
|
||||
v = vdupq_n_u16(window_size);
|
||||
|
||||
p = (uint16x8_t *)table;
|
||||
n = size / (sizeof(uint16x8_t) * 8);
|
||||
do {
|
||||
p[0] = vqsubq_u16(p[0], v);
|
||||
p[1] = vqsubq_u16(p[1], v);
|
||||
p[2] = vqsubq_u16(p[2], v);
|
||||
p[3] = vqsubq_u16(p[3], v);
|
||||
p[4] = vqsubq_u16(p[4], v);
|
||||
p[5] = vqsubq_u16(p[5], v);
|
||||
p[6] = vqsubq_u16(p[6], v);
|
||||
p[7] = vqsubq_u16(p[7], v);
|
||||
p += 8;
|
||||
} while (--n);
|
||||
}
|
||||
#else
|
||||
/* generic version for hash rebase */
|
||||
static inline void slide_hash_chain(Pos *table, unsigned int entries, uint16_t window_size) {
|
||||
unsigned int i;
|
||||
for (i = 0; i < entries; i++) {
|
||||
table[i] = (table[i] >= window_size) ? (table[i] - window_size) : NIL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void fill_window_arm(deflate_state *s) {
|
||||
register unsigned n;
|
||||
unsigned long 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 = s->window_size - s->lookahead - s->strstart;
|
||||
|
||||
/* 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, wsize);
|
||||
s->match_start -= wsize;
|
||||
s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
|
||||
s->block_start -= 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.)
|
||||
*/
|
||||
|
||||
slide_hash_chain(s->head, s->hash_size, wsize);
|
||||
slide_hash_chain(s->prev, wsize, wsize);
|
||||
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;
|
||||
unsigned int insert_cnt = s->insert;
|
||||
unsigned int slen;
|
||||
|
||||
s->ins_h = s->window[str];
|
||||
|
||||
if (unlikely(s->lookahead < MIN_MATCH))
|
||||
insert_cnt += s->lookahead - MIN_MATCH;
|
||||
slen = insert_cnt;
|
||||
if (str >= (MIN_MATCH - 2))
|
||||
{
|
||||
str += 2 - MIN_MATCH;
|
||||
insert_cnt += MIN_MATCH - 2;
|
||||
}
|
||||
if (insert_cnt > 0)
|
||||
{
|
||||
functable.insert_string(s, str, insert_cnt);
|
||||
s->insert -= slen;
|
||||
}
|
||||
}
|
||||
/* 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, init);
|
||||
s->high_water = curr + init;
|
||||
} else if (s->high_water < 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 = curr + WIN_INIT;
|
||||
if (init > s->window_size)
|
||||
init = s->window_size;
|
||||
init -= s->high_water;
|
||||
memset(s->window + s->high_water, 0, init);
|
||||
s->high_water += init;
|
||||
}
|
||||
}
|
||||
|
||||
Assert((unsigned long)s->strstart <= s->window_size - MIN_LOOKAHEAD, "not enough room for search");
|
||||
}
|
||||
53
libs/zlibng/arch/arm/insert_string_acle.c
Normal file
53
libs/zlibng/arch/arm/insert_string_acle.c
Normal file
@ -0,0 +1,53 @@
|
||||
/* insert_string_acle.c -- insert_string variant using ACLE'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
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(__ARM_FEATURE_CRC32) && defined(ARM_ACLE_CRC_HASH)
|
||||
#include <arm_acle.h>
|
||||
#include "zbuild.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).
|
||||
*/
|
||||
Pos insert_string_acle(deflate_state *const s, const Pos str, unsigned int count) {
|
||||
Pos p, lp, ret;
|
||||
|
||||
if (unlikely(count == 0)) {
|
||||
return s->prev[str & s->w_mask];
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
lp = str + count - 1; /* last position */
|
||||
|
||||
for (p = str; p <= lp; p++) {
|
||||
uint32_t val, h, hm;
|
||||
memcpy(&val, &s->window[p], sizeof(val));
|
||||
|
||||
if (s->level >= TRIGGER_LEVEL)
|
||||
val &= 0xFFFFFF;
|
||||
|
||||
h = __crc32w(0, val);
|
||||
hm = h & s->hash_mask;
|
||||
|
||||
Pos head = s->head[hm];
|
||||
if (head != p) {
|
||||
s->prev[p & s->w_mask] = head;
|
||||
s->head[hm] = p;
|
||||
if (p == lp)
|
||||
ret = head;
|
||||
} else if (p == lp) {
|
||||
ret = p;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
21
libs/zlibng/arch/generic/Makefile.in
Normal file
21
libs/zlibng/arch/generic/Makefile.in
Normal file
@ -0,0 +1,21 @@
|
||||
# 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=../..
|
||||
TOPDIR=$(SRCTOP)
|
||||
|
||||
all:
|
||||
|
||||
|
||||
mostlyclean: clean
|
||||
clean:
|
||||
rm -f *.o *.lo *~ \
|
||||
rm -rf objs
|
||||
rm -f *.gcda *.gcno *.gcov
|
||||
40
libs/zlibng/arch/s390/Makefile.in
Normal file
40
libs/zlibng/arch/s390/Makefile.in
Normal file
@ -0,0 +1,40 @@
|
||||
# Makefile for zlib-ng
|
||||
# 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=
|
||||
SUFFIX=
|
||||
|
||||
SRCDIR=.
|
||||
SRCTOP=../..
|
||||
TOPDIR=$(SRCTOP)
|
||||
|
||||
dfltcc_common.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/dfltcc_common.c
|
||||
|
||||
dfltcc_common.lo:
|
||||
$(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/dfltcc_common.c
|
||||
|
||||
dfltcc_deflate.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/dfltcc_deflate.c
|
||||
|
||||
dfltcc_deflate.lo:
|
||||
$(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/dfltcc_deflate.c
|
||||
|
||||
dfltcc_inflate.o:
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/dfltcc_inflate.c
|
||||
|
||||
dfltcc_inflate.lo:
|
||||
$(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/dfltcc_inflate.c
|
||||
|
||||
mostlyclean: clean
|
||||
clean:
|
||||
rm -f *.o *.lo *~
|
||||
rm -rf objs
|
||||
rm -f *.gcda *.gcno *.gcov
|
||||
|
||||
distclean:
|
||||
rm -f Makefile
|
||||
69
libs/zlibng/arch/s390/README.md
Normal file
69
libs/zlibng/arch/s390/README.md
Normal file
@ -0,0 +1,69 @@
|
||||
This directory contains IBM Z DEFLATE CONVERSION CALL support for
|
||||
zlib-ng. In order to enable it, the following build commands should be
|
||||
used:
|
||||
|
||||
$ ./configure --with-dfltcc-deflate --with-dfltcc-inflate
|
||||
$ make
|
||||
|
||||
or
|
||||
|
||||
$ cmake -DWITH_DFLTCC_DEFLATE=1 -DWITH_DFLTCC_INFLATE=1 .
|
||||
$ make
|
||||
|
||||
When built like this, zlib-ng would compress in hardware on level 1,
|
||||
and in software on all other levels. Decompression will always happen
|
||||
in hardware. In order to enable DFLTCC compression for levels 1-6 (i.e.
|
||||
to make it used by default) one could add -DDFLTCC_LEVEL_MASK=0x7e to
|
||||
CFLAGS when building zlib-ng.
|
||||
|
||||
Two DFLTCC compression calls produce the same results only when they
|
||||
both are made on machines of the same generation, and when the
|
||||
respective buffers have the same offset relative to the start of the
|
||||
page. Therefore care should be taken when using hardware compression
|
||||
when reproducible results are desired.
|
||||
|
||||
DFLTCC does not support every single zlib-ng feature, in particular:
|
||||
|
||||
* inflate(Z_BLOCK) and inflate(Z_TREES)
|
||||
* inflateMark()
|
||||
* inflatePrime()
|
||||
* deflateParams() after the first deflate() call
|
||||
|
||||
When used, these functions will either switch to software, or, in case
|
||||
this is not possible, gracefully fail.
|
||||
|
||||
All SystemZ-specific code lives in a separate file and is integrated
|
||||
with the rest of zlib-ng using hook macros, which are explained below.
|
||||
|
||||
DFLTCC takes as arguments a parameter block, an input buffer, an output
|
||||
buffer and a window. ZALLOC_STATE, ZFREE_STATE, ZCOPY_STATE,
|
||||
ZALLOC_WINDOW and TRY_FREE_WINDOW macros encapsulate allocation details
|
||||
for the parameter block (which is allocated alongside zlib-ng state)
|
||||
and the window (which must be page-aligned).
|
||||
|
||||
While for inflate software and hardware window formats match, this is
|
||||
not the case for deflate. Therefore, deflateSetDictionary and
|
||||
deflateGetDictionary need special handling, which is triggered using
|
||||
the DEFLATE_SET_DICTIONARY_HOOK and DEFLATE_GET_DICTIONARY_HOOK macros.
|
||||
|
||||
deflateResetKeep() and inflateResetKeep() update the DFLTCC parameter
|
||||
block using DEFLATE_RESET_KEEP_HOOK and INFLATE_RESET_KEEP_HOOK macros.
|
||||
|
||||
DEFLATE_PARAMS_HOOK, INFLATE_PRIME_HOOK and INFLATE_MARK_HOOK macros
|
||||
make the unsupported deflateParams(), inflatePrime() and inflateMark()
|
||||
calls fail gracefully.
|
||||
|
||||
The algorithm implemented in hardware has different compression ratio
|
||||
than the one implemented in software. DEFLATE_BOUND_ADJUST_COMPLEN and
|
||||
DEFLATE_NEED_CONSERVATIVE_BOUND macros make deflateBound() return the
|
||||
correct results for the hardware implementation.
|
||||
|
||||
Actual compression and decompression are handled by DEFLATE_HOOK and
|
||||
INFLATE_TYPEDO_HOOK macros. Since inflation with DFLTCC manages the
|
||||
window on its own, calling updatewindow() is suppressed using
|
||||
INFLATE_NEED_UPDATEWINDOW() macro.
|
||||
|
||||
In addition to compression, DFLTCC computes CRC-32 and Adler-32
|
||||
checksums, therefore, whenever it's used, software checksumming is
|
||||
suppressed using DEFLATE_NEED_CHECKSUM and INFLATE_NEED_CHECKSUM
|
||||
macros.
|
||||
86
libs/zlibng/arch/s390/dfltcc_common.c
Normal file
86
libs/zlibng/arch/s390/dfltcc_common.c
Normal file
@ -0,0 +1,86 @@
|
||||
/* dfltcc_deflate.c - IBM Z DEFLATE CONVERSION CALL general support. */
|
||||
|
||||
#include "zbuild.h"
|
||||
#include "dfltcc_common.h"
|
||||
#include "dfltcc_detail.h"
|
||||
|
||||
/*
|
||||
Memory management.
|
||||
|
||||
DFLTCC requires parameter blocks and window to be aligned. zlib-ng allows
|
||||
users to specify their own allocation functions, so using e.g.
|
||||
`posix_memalign' is not an option. Thus, we overallocate and take the
|
||||
aligned portion of the buffer.
|
||||
*/
|
||||
static inline int is_dfltcc_enabled(void)
|
||||
{
|
||||
uint64_t facilities[(DFLTCC_FACILITY / 64) + 1];
|
||||
register uint8_t r0 __asm__("r0");
|
||||
|
||||
memset(facilities, 0, sizeof(facilities));
|
||||
r0 = sizeof(facilities) / sizeof(facilities[0]) - 1;
|
||||
__asm__ volatile("stfle %[facilities]\n" : [facilities] "=Q" (facilities), [r0] "+r" (r0) :: "cc");
|
||||
return is_bit_set((const char *)facilities, DFLTCC_FACILITY);
|
||||
}
|
||||
|
||||
void ZLIB_INTERNAL dfltcc_reset(PREFIX3(streamp) strm, uInt size)
|
||||
{
|
||||
struct dfltcc_state *dfltcc_state = (struct dfltcc_state *)((char *)strm->state + size);
|
||||
struct dfltcc_qaf_param *param = (struct dfltcc_qaf_param *)&dfltcc_state->param;
|
||||
|
||||
/* Initialize available functions */
|
||||
if (is_dfltcc_enabled()) {
|
||||
dfltcc(DFLTCC_QAF, param, NULL, NULL, NULL, NULL, NULL);
|
||||
memmove(&dfltcc_state->af, param, sizeof(dfltcc_state->af));
|
||||
} else
|
||||
memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af));
|
||||
|
||||
/* Initialize parameter block */
|
||||
memset(&dfltcc_state->param, 0, sizeof(dfltcc_state->param));
|
||||
dfltcc_state->param.nt = 1;
|
||||
|
||||
/* Initialize tuning parameters */
|
||||
dfltcc_state->level_mask = DFLTCC_LEVEL_MASK;
|
||||
dfltcc_state->block_size = DFLTCC_BLOCK_SIZE;
|
||||
dfltcc_state->block_threshold = DFLTCC_FIRST_FHT_BLOCK_SIZE;
|
||||
dfltcc_state->dht_threshold = DFLTCC_DHT_MIN_SAMPLE_SIZE;
|
||||
dfltcc_state->param.ribm = DFLTCC_RIBM;
|
||||
}
|
||||
|
||||
void ZLIB_INTERNAL *dfltcc_alloc_state(PREFIX3(streamp) strm, uInt items, uInt size)
|
||||
{
|
||||
Assert((items * size) % 8 == 0,
|
||||
"The size of zlib-ng state must be a multiple of 8");
|
||||
return ZALLOC(strm, items * size + sizeof(struct dfltcc_state), sizeof(unsigned char));
|
||||
}
|
||||
|
||||
void ZLIB_INTERNAL dfltcc_copy_state(void *dst, const void *src, uInt size)
|
||||
{
|
||||
memcpy(dst, src, size + sizeof(struct dfltcc_state));
|
||||
}
|
||||
|
||||
static const int PAGE_ALIGN = 0x1000;
|
||||
|
||||
#define ALIGN_UP(p, size) (__typeof__(p))(((uintptr_t)(p) + ((size) - 1)) & ~((size) - 1))
|
||||
|
||||
void ZLIB_INTERNAL *dfltcc_alloc_window(PREFIX3(streamp) strm, uInt items, uInt size)
|
||||
{
|
||||
void *p;
|
||||
void *w;
|
||||
|
||||
/* To simplify freeing, we store the pointer to the allocated buffer right
|
||||
* before the window.
|
||||
*/
|
||||
p = ZALLOC(strm, sizeof(void *) + items * size + PAGE_ALIGN, sizeof(unsigned char));
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
w = ALIGN_UP((char *)p + sizeof(void *), PAGE_ALIGN);
|
||||
*(void **)((char *)w - sizeof(void *)) = p;
|
||||
return w;
|
||||
}
|
||||
|
||||
void ZLIB_INTERNAL dfltcc_free_window(PREFIX3(streamp) strm, void *w)
|
||||
{
|
||||
if (w)
|
||||
ZFREE(strm, *(void **)((unsigned char *)w - sizeof(void *)));
|
||||
}
|
||||
29
libs/zlibng/arch/s390/dfltcc_common.h
Normal file
29
libs/zlibng/arch/s390/dfltcc_common.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef DFLTCC_COMMON_H
|
||||
#define DFLTCC_COMMON_H
|
||||
|
||||
#ifdef ZLIB_COMPAT
|
||||
#include "zlib.h"
|
||||
#else
|
||||
#include "zlib-ng.h"
|
||||
#endif
|
||||
#include "zutil.h"
|
||||
|
||||
void ZLIB_INTERNAL *dfltcc_alloc_state(PREFIX3(streamp) strm, uInt items, uInt size);
|
||||
void ZLIB_INTERNAL dfltcc_copy_state(void *dst, const void *src, uInt size);
|
||||
void ZLIB_INTERNAL dfltcc_reset(PREFIX3(streamp) strm, uInt size);
|
||||
void ZLIB_INTERNAL *dfltcc_alloc_window(PREFIX3(streamp) strm, uInt items, uInt size);
|
||||
void ZLIB_INTERNAL dfltcc_free_window(PREFIX3(streamp) strm, void *w);
|
||||
|
||||
#define ZALLOC_STATE dfltcc_alloc_state
|
||||
|
||||
#define ZFREE_STATE ZFREE
|
||||
|
||||
#define ZCOPY_STATE dfltcc_copy_state
|
||||
|
||||
#define ZALLOC_WINDOW dfltcc_alloc_window
|
||||
|
||||
#define ZFREE_WINDOW dfltcc_free_window
|
||||
|
||||
#define TRY_FREE_WINDOW dfltcc_free_window
|
||||
|
||||
#endif
|
||||
365
libs/zlibng/arch/s390/dfltcc_deflate.c
Normal file
365
libs/zlibng/arch/s390/dfltcc_deflate.c
Normal file
@ -0,0 +1,365 @@
|
||||
/* dfltcc_deflate.c - IBM Z DEFLATE CONVERSION CALL compression support. */
|
||||
|
||||
/*
|
||||
Use the following commands to build zlib-ng with DFLTCC compression support:
|
||||
|
||||
$ ./configure --with-dfltcc-deflate
|
||||
or
|
||||
|
||||
$ cmake -DWITH_DFLTCC_DEFLATE=1 .
|
||||
|
||||
and then
|
||||
|
||||
$ make
|
||||
*/
|
||||
|
||||
#include "zbuild.h"
|
||||
#include "zutil.h"
|
||||
#include "deflate.h"
|
||||
#include "dfltcc_deflate.h"
|
||||
#include "dfltcc_detail.h"
|
||||
|
||||
static inline int dfltcc_are_params_ok(int level, uInt window_bits, int strategy, uint16_t level_mask)
|
||||
{
|
||||
return (level_mask & ((uint16_t)1 << level)) != 0 &&
|
||||
(window_bits == HB_BITS) &&
|
||||
(strategy == Z_FIXED || strategy == Z_DEFAULT_STRATEGY);
|
||||
}
|
||||
|
||||
|
||||
int ZLIB_INTERNAL dfltcc_can_deflate(PREFIX3(streamp) strm)
|
||||
{
|
||||
deflate_state *state = (deflate_state *)strm->state;
|
||||
struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
|
||||
|
||||
/* Unsupported compression settings */
|
||||
if (!dfltcc_are_params_ok(state->level, state->w_bits, state->strategy, dfltcc_state->level_mask))
|
||||
return 0;
|
||||
|
||||
/* Unsupported hardware */
|
||||
if (!is_bit_set(dfltcc_state->af.fns, DFLTCC_GDHT) ||
|
||||
!is_bit_set(dfltcc_state->af.fns, DFLTCC_CMPR) ||
|
||||
!is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline void dfltcc_gdht(PREFIX3(streamp) strm)
|
||||
{
|
||||
deflate_state *state = (deflate_state *)strm->state;
|
||||
struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
|
||||
size_t avail_in = strm->avail_in;
|
||||
|
||||
dfltcc(DFLTCC_GDHT, param, NULL, NULL, &strm->next_in, &avail_in, NULL);
|
||||
}
|
||||
|
||||
static inline dfltcc_cc dfltcc_cmpr(PREFIX3(streamp) strm)
|
||||
{
|
||||
deflate_state *state = (deflate_state *)strm->state;
|
||||
struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
|
||||
size_t avail_in = strm->avail_in;
|
||||
size_t avail_out = strm->avail_out;
|
||||
dfltcc_cc cc;
|
||||
|
||||
cc = dfltcc(DFLTCC_CMPR | HBT_CIRCULAR,
|
||||
param, &strm->next_out, &avail_out,
|
||||
&strm->next_in, &avail_in, state->window);
|
||||
strm->total_in += (strm->avail_in - avail_in);
|
||||
strm->total_out += (strm->avail_out - avail_out);
|
||||
strm->avail_in = avail_in;
|
||||
strm->avail_out = avail_out;
|
||||
return cc;
|
||||
}
|
||||
|
||||
static inline void send_eobs(PREFIX3(streamp) strm, const struct dfltcc_param_v0 *param)
|
||||
{
|
||||
deflate_state *state = (deflate_state *)strm->state;
|
||||
|
||||
send_bits(state, bi_reverse(param->eobs >> (15 - param->eobl), param->eobl), param->eobl);
|
||||
flush_pending(strm);
|
||||
if (state->pending != 0) {
|
||||
/* The remaining data is located in pending_out[0:pending]. If someone
|
||||
* calls put_byte() - this might happen in deflate() - the byte will be
|
||||
* placed into pending_buf[pending], which is incorrect. Move the
|
||||
* remaining data to the beginning of pending_buf so that put_byte() is
|
||||
* usable again.
|
||||
*/
|
||||
memmove(state->pending_buf, state->pending_out, state->pending);
|
||||
state->pending_out = state->pending_buf;
|
||||
}
|
||||
#ifdef ZLIB_DEBUG
|
||||
state->compressed_len += param->eobl;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ZLIB_INTERNAL dfltcc_deflate(PREFIX3(streamp) strm, int flush, block_state *result)
|
||||
{
|
||||
deflate_state *state = (deflate_state *)strm->state;
|
||||
struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
|
||||
struct dfltcc_param_v0 *param = &dfltcc_state->param;
|
||||
uInt masked_avail_in;
|
||||
dfltcc_cc cc;
|
||||
int need_empty_block;
|
||||
int soft_bcc;
|
||||
int no_flush;
|
||||
|
||||
if (!dfltcc_can_deflate(strm))
|
||||
return 0;
|
||||
|
||||
again:
|
||||
masked_avail_in = 0;
|
||||
soft_bcc = 0;
|
||||
no_flush = flush == Z_NO_FLUSH;
|
||||
|
||||
/* Trailing empty block. Switch to software, except when Continuation Flag
|
||||
* is set, which means that DFLTCC has buffered some output in the
|
||||
* parameter block and needs to be called again in order to flush it.
|
||||
*/
|
||||
if (flush == Z_FINISH && strm->avail_in == 0 && !param->cf) {
|
||||
if (param->bcf) {
|
||||
/* A block is still open, and the hardware does not support closing
|
||||
* blocks without adding data. Thus, close it manually.
|
||||
*/
|
||||
send_eobs(strm, param);
|
||||
param->bcf = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strm->avail_in == 0 && !param->cf) {
|
||||
*result = need_more;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* There is an open non-BFINAL block, we are not going to close it just
|
||||
* yet, we have compressed more than DFLTCC_BLOCK_SIZE bytes and we see
|
||||
* more than DFLTCC_DHT_MIN_SAMPLE_SIZE bytes. Open a new block with a new
|
||||
* DHT in order to adapt to a possibly changed input data distribution.
|
||||
*/
|
||||
if (param->bcf && no_flush &&
|
||||
strm->total_in > dfltcc_state->block_threshold &&
|
||||
strm->avail_in >= dfltcc_state->dht_threshold) {
|
||||
if (param->cf) {
|
||||
/* We need to flush the DFLTCC buffer before writing the
|
||||
* End-of-block Symbol. Mask the input data and proceed as usual.
|
||||
*/
|
||||
masked_avail_in += strm->avail_in;
|
||||
strm->avail_in = 0;
|
||||
no_flush = 0;
|
||||
} else {
|
||||
/* DFLTCC buffer is empty, so we can manually write the
|
||||
* End-of-block Symbol right away.
|
||||
*/
|
||||
send_eobs(strm, param);
|
||||
param->bcf = 0;
|
||||
dfltcc_state->block_threshold = strm->total_in + dfltcc_state->block_size;
|
||||
if (strm->avail_out == 0) {
|
||||
*result = need_more;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* The caller gave us too much data. Pass only one block worth of
|
||||
* uncompressed data to DFLTCC and mask the rest, so that on the next
|
||||
* iteration we start a new block.
|
||||
*/
|
||||
if (no_flush && strm->avail_in > dfltcc_state->block_size) {
|
||||
masked_avail_in += (strm->avail_in - dfltcc_state->block_size);
|
||||
strm->avail_in = dfltcc_state->block_size;
|
||||
}
|
||||
|
||||
/* When we have an open non-BFINAL deflate block and caller indicates that
|
||||
* the stream is ending, we need to close an open deflate block and open a
|
||||
* BFINAL one.
|
||||
*/
|
||||
need_empty_block = flush == Z_FINISH && param->bcf && !param->bhf;
|
||||
|
||||
/* Translate stream to parameter block */
|
||||
param->cvt = state->wrap == 2 ? CVT_CRC32 : CVT_ADLER32;
|
||||
if (!no_flush)
|
||||
/* We need to close a block. Always do this in software - when there is
|
||||
* no input data, the hardware will not nohor BCC. */
|
||||
soft_bcc = 1;
|
||||
if (flush == Z_FINISH && !param->bcf)
|
||||
/* We are about to open a BFINAL block, set Block Header Final bit
|
||||
* until the stream ends.
|
||||
*/
|
||||
param->bhf = 1;
|
||||
/* DFLTCC-CMPR will write to next_out, so make sure that buffers with
|
||||
* higher precedence are empty.
|
||||
*/
|
||||
Assert(state->pending == 0, "There must be no pending bytes");
|
||||
Assert(state->bi_valid < 8, "There must be less than 8 pending bits");
|
||||
param->sbb = (unsigned int)state->bi_valid;
|
||||
if (param->sbb > 0)
|
||||
*strm->next_out = (unsigned char)state->bi_buf;
|
||||
if (param->hl)
|
||||
param->nt = 0; /* Honor history */
|
||||
param->cv = state->wrap == 2 ? ZSWAP32(strm->adler) : strm->adler;
|
||||
|
||||
/* When opening a block, choose a Huffman-Table Type */
|
||||
if (!param->bcf) {
|
||||
if (state->strategy == Z_FIXED || (strm->total_in == 0 && dfltcc_state->block_threshold > 0))
|
||||
param->htt = HTT_FIXED;
|
||||
else {
|
||||
param->htt = HTT_DYNAMIC;
|
||||
dfltcc_gdht(strm);
|
||||
}
|
||||
}
|
||||
|
||||
/* Deflate */
|
||||
do {
|
||||
cc = dfltcc_cmpr(strm);
|
||||
if (strm->avail_in < 4096 && masked_avail_in > 0)
|
||||
/* We are about to call DFLTCC with a small input buffer, which is
|
||||
* inefficient. Since there is masked data, there will be at least
|
||||
* one more DFLTCC call, so skip the current one and make the next
|
||||
* one handle more data.
|
||||
*/
|
||||
break;
|
||||
} while (cc == DFLTCC_CC_AGAIN);
|
||||
|
||||
/* Translate parameter block to stream */
|
||||
strm->msg = oesc_msg(dfltcc_state->msg, param->oesc);
|
||||
state->bi_valid = param->sbb;
|
||||
if (state->bi_valid == 0)
|
||||
state->bi_buf = 0; /* Avoid accessing next_out */
|
||||
else
|
||||
state->bi_buf = *strm->next_out & ((1 << state->bi_valid) - 1);
|
||||
strm->adler = state->wrap == 2 ? ZSWAP32(param->cv) : param->cv;
|
||||
|
||||
/* Unmask the input data */
|
||||
strm->avail_in += masked_avail_in;
|
||||
masked_avail_in = 0;
|
||||
|
||||
/* If we encounter an error, it means there is a bug in DFLTCC call */
|
||||
Assert(cc != DFLTCC_CC_OP2_CORRUPT || param->oesc == 0, "BUG");
|
||||
|
||||
/* Update Block-Continuation Flag. It will be used to check whether to call
|
||||
* GDHT the next time.
|
||||
*/
|
||||
if (cc == DFLTCC_CC_OK) {
|
||||
if (soft_bcc) {
|
||||
send_eobs(strm, param);
|
||||
param->bcf = 0;
|
||||
dfltcc_state->block_threshold = strm->total_in + dfltcc_state->block_size;
|
||||
} else
|
||||
param->bcf = 1;
|
||||
if (flush == Z_FINISH) {
|
||||
if (need_empty_block)
|
||||
/* Make the current deflate() call also close the stream */
|
||||
return 0;
|
||||
else {
|
||||
bi_windup(state);
|
||||
*result = finish_done;
|
||||
}
|
||||
} else {
|
||||
if (flush == Z_FULL_FLUSH)
|
||||
param->hl = 0; /* Clear history */
|
||||
*result = flush == Z_NO_FLUSH ? need_more : block_done;
|
||||
}
|
||||
} else {
|
||||
param->bcf = 1;
|
||||
*result = need_more;
|
||||
}
|
||||
if (strm->avail_in != 0 && strm->avail_out != 0)
|
||||
goto again; /* deflate() must use all input or all output */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Switching between hardware and software compression.
|
||||
|
||||
DFLTCC does not support all zlib settings, e.g. generation of non-compressed
|
||||
blocks or alternative window sizes. When such settings are applied on the
|
||||
fly with deflateParams, we need to convert between hardware and software
|
||||
window formats.
|
||||
*/
|
||||
int ZLIB_INTERNAL dfltcc_deflate_params(PREFIX3(streamp) strm, int level, int strategy)
|
||||
{
|
||||
deflate_state *state = (deflate_state *)strm->state;
|
||||
struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
|
||||
struct dfltcc_param_v0 *param = &dfltcc_state->param;
|
||||
int could_deflate = dfltcc_can_deflate(strm);
|
||||
int can_deflate = dfltcc_are_params_ok(level, state->w_bits, strategy, dfltcc_state->level_mask);
|
||||
|
||||
if (can_deflate == could_deflate)
|
||||
/* We continue to work in the same mode - no changes needed */
|
||||
return Z_OK;
|
||||
|
||||
if (strm->total_in == 0 && param->nt == 1 && param->hl == 0)
|
||||
/* DFLTCC was not used yet - no changes needed */
|
||||
return Z_OK;
|
||||
|
||||
/* Switching between hardware and software is not implemented */
|
||||
return Z_STREAM_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
Preloading history.
|
||||
*/
|
||||
static void append_history(struct dfltcc_param_v0 *param, unsigned char *history, const unsigned char *buf, uInt count)
|
||||
{
|
||||
size_t offset;
|
||||
size_t n;
|
||||
|
||||
/* Do not use more than 32K */
|
||||
if (count > HB_SIZE) {
|
||||
buf += count - HB_SIZE;
|
||||
count = HB_SIZE;
|
||||
}
|
||||
offset = (param->ho + param->hl) % HB_SIZE;
|
||||
if (offset + count <= HB_SIZE)
|
||||
/* Circular history buffer does not wrap - copy one chunk */
|
||||
memcpy(history + offset, buf, count);
|
||||
else {
|
||||
/* Circular history buffer wraps - copy two chunks */
|
||||
n = HB_SIZE - offset;
|
||||
memcpy(history + offset, buf, n);
|
||||
memcpy(history, buf + n, count - n);
|
||||
}
|
||||
n = param->hl + count;
|
||||
if (n <= HB_SIZE)
|
||||
/* All history fits into buffer - no need to discard anything */
|
||||
param->hl = n;
|
||||
else {
|
||||
/* History does not fit into buffer - discard extra bytes */
|
||||
param->ho = (param->ho + (n - HB_SIZE)) % HB_SIZE;
|
||||
param->hl = HB_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
int ZLIB_INTERNAL dfltcc_deflate_set_dictionary(PREFIX3(streamp) strm,
|
||||
const unsigned char *dictionary, uInt dict_length)
|
||||
{
|
||||
deflate_state *state = (deflate_state *)strm->state;
|
||||
struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
|
||||
struct dfltcc_param_v0 *param = &dfltcc_state->param;
|
||||
|
||||
append_history(param, state->window, dictionary, dict_length);
|
||||
state->strstart = 1; /* Add FDICT to zlib header */
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
int ZLIB_INTERNAL dfltcc_deflate_get_dictionary(PREFIX3(streamp) strm, unsigned char *dictionary, uInt *dict_length)
|
||||
{
|
||||
deflate_state *state = (deflate_state *)strm->state;
|
||||
struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
|
||||
struct dfltcc_param_v0 *param = &dfltcc_state->param;
|
||||
|
||||
if (dictionary) {
|
||||
if (param->ho + param->hl <= HB_SIZE)
|
||||
/* Circular history buffer does not wrap - copy one chunk */
|
||||
memcpy(dictionary, state->window + param->ho, param->hl);
|
||||
else {
|
||||
/* Circular history buffer wraps - copy two chunks */
|
||||
memcpy(dictionary, state->window + param->ho, HB_SIZE - param->ho);
|
||||
memcpy(dictionary + HB_SIZE - param->ho, state->window, param->ho + param->hl - HB_SIZE);
|
||||
}
|
||||
}
|
||||
if (dict_length)
|
||||
*dict_length = param->hl;
|
||||
return Z_OK;
|
||||
}
|
||||
50
libs/zlibng/arch/s390/dfltcc_deflate.h
Normal file
50
libs/zlibng/arch/s390/dfltcc_deflate.h
Normal file
@ -0,0 +1,50 @@
|
||||
#ifndef DFLTCC_DEFLATE_H
|
||||
#define DFLTCC_DEFLATE_H
|
||||
|
||||
#include "dfltcc_common.h"
|
||||
|
||||
int ZLIB_INTERNAL dfltcc_can_deflate(PREFIX3(streamp) strm);
|
||||
int ZLIB_INTERNAL dfltcc_deflate(PREFIX3(streamp) strm, int flush, block_state *result);
|
||||
int ZLIB_INTERNAL dfltcc_deflate_params(PREFIX3(streamp) strm, int level, int strategy);
|
||||
int ZLIB_INTERNAL dfltcc_deflate_set_dictionary(PREFIX3(streamp) strm,
|
||||
const unsigned char *dictionary, uInt dict_length);
|
||||
int ZLIB_INTERNAL dfltcc_deflate_get_dictionary(PREFIX3(streamp) strm, unsigned char *dictionary, uInt* dict_length);
|
||||
|
||||
#define DEFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) \
|
||||
do { \
|
||||
if (dfltcc_can_deflate((strm))) \
|
||||
return dfltcc_deflate_set_dictionary((strm), (dict), (dict_len)); \
|
||||
} while (0)
|
||||
|
||||
#define DEFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) \
|
||||
do { \
|
||||
if (dfltcc_can_deflate((strm))) \
|
||||
return dfltcc_deflate_get_dictionary((strm), (dict), (dict_len)); \
|
||||
} while (0)
|
||||
|
||||
#define DEFLATE_RESET_KEEP_HOOK(strm) \
|
||||
dfltcc_reset((strm), sizeof(deflate_state))
|
||||
|
||||
#define DEFLATE_PARAMS_HOOK(strm, level, strategy) \
|
||||
do { \
|
||||
int err; \
|
||||
\
|
||||
err = dfltcc_deflate_params((strm), (level), (strategy)); \
|
||||
if (err == Z_STREAM_ERROR) \
|
||||
return err; \
|
||||
} while (0)
|
||||
|
||||
#define DEFLATE_BOUND_ADJUST_COMPLEN(strm, complen, source_len) \
|
||||
do { \
|
||||
if (dfltcc_can_deflate((strm))) \
|
||||
(complen) = (3 + 5 + 5 + 4 + 19 * 3 + (286 + 30) * 7 + \
|
||||
(source_len) * 16 + 15 + 7) >> 3; \
|
||||
} while (0)
|
||||
|
||||
#define DEFLATE_NEED_CONSERVATIVE_BOUND(strm) (dfltcc_can_deflate((strm)))
|
||||
|
||||
#define DEFLATE_HOOK dfltcc_deflate
|
||||
|
||||
#define DEFLATE_NEED_CHECKSUM(strm) (!dfltcc_can_deflate((strm)))
|
||||
|
||||
#endif
|
||||
201
libs/zlibng/arch/s390/dfltcc_detail.h
Normal file
201
libs/zlibng/arch/s390/dfltcc_detail.h
Normal file
@ -0,0 +1,201 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef HAVE_SYS_SDT_H
|
||||
#include <sys/sdt.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
Tuning parameters.
|
||||
*/
|
||||
#ifndef DFLTCC_LEVEL_MASK
|
||||
#define DFLTCC_LEVEL_MASK 0x2
|
||||
#endif
|
||||
#ifndef DFLTCC_BLOCK_SIZE
|
||||
#define DFLTCC_BLOCK_SIZE 1048576
|
||||
#endif
|
||||
#ifndef DFLTCC_FIRST_FHT_BLOCK_SIZE
|
||||
#define DFLTCC_FIRST_FHT_BLOCK_SIZE 4096
|
||||
#endif
|
||||
#ifndef DFLTCC_DHT_MIN_SAMPLE_SIZE
|
||||
#define DFLTCC_DHT_MIN_SAMPLE_SIZE 4096
|
||||
#endif
|
||||
#ifndef DFLTCC_RIBM
|
||||
#define DFLTCC_RIBM 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
C wrapper for the DEFLATE CONVERSION CALL instruction.
|
||||
*/
|
||||
typedef enum {
|
||||
DFLTCC_CC_OK = 0,
|
||||
DFLTCC_CC_OP1_TOO_SHORT = 1,
|
||||
DFLTCC_CC_OP2_TOO_SHORT = 2,
|
||||
DFLTCC_CC_OP2_CORRUPT = 2,
|
||||
DFLTCC_CC_AGAIN = 3,
|
||||
} dfltcc_cc;
|
||||
|
||||
#define DFLTCC_QAF 0
|
||||
#define DFLTCC_GDHT 1
|
||||
#define DFLTCC_CMPR 2
|
||||
#define DFLTCC_XPND 4
|
||||
#define HBT_CIRCULAR (1 << 7)
|
||||
#define HB_BITS 15
|
||||
#define HB_SIZE (1 << HB_BITS)
|
||||
#define DFLTCC_FACILITY 151
|
||||
|
||||
static inline dfltcc_cc dfltcc(int fn, void *param,
|
||||
unsigned char **op1, size_t *len1, const unsigned char **op2, size_t *len2, void *hist)
|
||||
{
|
||||
unsigned char *t2 = op1 ? *op1 : NULL;
|
||||
size_t t3 = len1 ? *len1 : 0;
|
||||
const unsigned char *t4 = op2 ? *op2 : NULL;
|
||||
size_t t5 = len2 ? *len2 : 0;
|
||||
register int r0 __asm__("r0") = fn;
|
||||
register void *r1 __asm__("r1") = param;
|
||||
register unsigned char *r2 __asm__("r2") = t2;
|
||||
register size_t r3 __asm__("r3") = t3;
|
||||
register const unsigned char *r4 __asm__("r4") = t4;
|
||||
register size_t r5 __asm__("r5") = t5;
|
||||
int cc;
|
||||
|
||||
__asm__ volatile(
|
||||
#ifdef HAVE_SYS_SDT_H
|
||||
STAP_PROBE_ASM(zlib, dfltcc_entry, STAP_PROBE_ASM_TEMPLATE(5))
|
||||
#endif
|
||||
".insn rrf,0xb9390000,%[r2],%[r4],%[hist],0\n"
|
||||
#ifdef HAVE_SYS_SDT_H
|
||||
STAP_PROBE_ASM(zlib, dfltcc_exit, STAP_PROBE_ASM_TEMPLATE(5))
|
||||
#endif
|
||||
"ipm %[cc]\n"
|
||||
: [r2] "+r" (r2)
|
||||
, [r3] "+r" (r3)
|
||||
, [r4] "+r" (r4)
|
||||
, [r5] "+r" (r5)
|
||||
, [cc] "=r" (cc)
|
||||
: [r0] "r" (r0)
|
||||
, [r1] "r" (r1)
|
||||
, [hist] "r" (hist)
|
||||
#ifdef HAVE_SYS_SDT_H
|
||||
, STAP_PROBE_ASM_OPERANDS(5, r2, r3, r4, r5, hist)
|
||||
#endif
|
||||
: "cc", "memory");
|
||||
t2 = r2; t3 = r3; t4 = r4; t5 = r5;
|
||||
|
||||
if (op1)
|
||||
*op1 = t2;
|
||||
if (len1)
|
||||
*len1 = t3;
|
||||
if (op2)
|
||||
*op2 = t4;
|
||||
if (len2)
|
||||
*len2 = t5;
|
||||
return (cc >> 28) & 3;
|
||||
}
|
||||
|
||||
/*
|
||||
Parameter Block for Query Available Functions.
|
||||
*/
|
||||
#define static_assert(c, msg) __attribute__((unused)) static char static_assert_failed_ ## msg[c ? 1 : -1]
|
||||
|
||||
struct dfltcc_qaf_param {
|
||||
char fns[16];
|
||||
char reserved1[8];
|
||||
char fmts[2];
|
||||
char reserved2[6];
|
||||
};
|
||||
|
||||
static_assert(sizeof(struct dfltcc_qaf_param) == 32, sizeof_struct_dfltcc_qaf_param_is_32);
|
||||
|
||||
static inline int is_bit_set(const char *bits, int n)
|
||||
{
|
||||
return bits[n / 8] & (1 << (7 - (n % 8)));
|
||||
}
|
||||
|
||||
static inline void clear_bit(char *bits, int n)
|
||||
{
|
||||
bits[n / 8] &= ~(1 << (7 - (n % 8)));
|
||||
}
|
||||
|
||||
#define DFLTCC_FMT0 0
|
||||
|
||||
/*
|
||||
Parameter Block for Generate Dynamic-Huffman Table, Compress and Expand.
|
||||
*/
|
||||
#define CVT_CRC32 0
|
||||
#define CVT_ADLER32 1
|
||||
#define HTT_FIXED 0
|
||||
#define HTT_DYNAMIC 1
|
||||
|
||||
struct dfltcc_param_v0 {
|
||||
uint16_t pbvn; /* Parameter-Block-Version Number */
|
||||
uint8_t mvn; /* Model-Version Number */
|
||||
uint8_t ribm; /* Reserved for IBM use */
|
||||
uint32_t reserved32 : 31;
|
||||
uint32_t cf : 1; /* Continuation Flag */
|
||||
uint8_t reserved64[8];
|
||||
uint32_t nt : 1; /* New Task */
|
||||
uint32_t reserved129 : 1;
|
||||
uint32_t cvt : 1; /* Check Value Type */
|
||||
uint32_t reserved131 : 1;
|
||||
uint32_t htt : 1; /* Huffman-Table Type */
|
||||
uint32_t bcf : 1; /* Block-Continuation Flag */
|
||||
uint32_t bcc : 1; /* Block Closing Control */
|
||||
uint32_t bhf : 1; /* Block Header Final */
|
||||
uint32_t reserved136 : 1;
|
||||
uint32_t reserved137 : 1;
|
||||
uint32_t dhtgc : 1; /* DHT Generation Control */
|
||||
uint32_t reserved139 : 5;
|
||||
uint32_t reserved144 : 5;
|
||||
uint32_t sbb : 3; /* Sub-Byte Boundary */
|
||||
uint8_t oesc; /* Operation-Ending-Supplemental Code */
|
||||
uint32_t reserved160 : 12;
|
||||
uint32_t ifs : 4; /* Incomplete-Function Status */
|
||||
uint16_t ifl; /* Incomplete-Function Length */
|
||||
uint8_t reserved192[8];
|
||||
uint8_t reserved256[8];
|
||||
uint8_t reserved320[4];
|
||||
uint16_t hl; /* History Length */
|
||||
uint32_t reserved368 : 1;
|
||||
uint16_t ho : 15; /* History Offset */
|
||||
uint32_t cv; /* Check Value */
|
||||
uint32_t eobs : 15; /* End-of-block Symbol */
|
||||
uint32_t reserved431: 1;
|
||||
uint8_t eobl : 4; /* End-of-block Length */
|
||||
uint32_t reserved436 : 12;
|
||||
uint32_t reserved448 : 4;
|
||||
uint16_t cdhtl : 12; /* Compressed-Dynamic-Huffman Table
|
||||
Length */
|
||||
uint8_t reserved464[6];
|
||||
uint8_t cdht[288];
|
||||
uint8_t reserved[32];
|
||||
uint8_t csb[1152];
|
||||
};
|
||||
|
||||
static_assert(sizeof(struct dfltcc_param_v0) == 1536, sizeof_struct_dfltcc_param_v0_is_1536);
|
||||
|
||||
static inline const char *oesc_msg(char *buf, int oesc)
|
||||
{
|
||||
if (oesc == 0x00)
|
||||
return NULL; /* Successful completion */
|
||||
else {
|
||||
sprintf(buf, "Operation-Ending-Supplemental Code is 0x%.2X", oesc);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Extension of inflate_state and deflate_state. Must be doubleword-aligned.
|
||||
*/
|
||||
struct dfltcc_state {
|
||||
struct dfltcc_param_v0 param; /* Parameter block. */
|
||||
struct dfltcc_qaf_param af; /* Available functions. */
|
||||
uint16_t level_mask; /* Levels on which to use DFLTCC */
|
||||
uint32_t block_size; /* New block each X bytes */
|
||||
size_t block_threshold; /* New block after total_in > X */
|
||||
uint32_t dht_threshold; /* New block only if avail_in >= X */
|
||||
char msg[64]; /* Buffer for strm->msg */
|
||||
};
|
||||
|
||||
#define GET_DFLTCC_STATE(state) ((struct dfltcc_state *)((state) + 1))
|
||||
142
libs/zlibng/arch/s390/dfltcc_inflate.c
Normal file
142
libs/zlibng/arch/s390/dfltcc_inflate.c
Normal file
@ -0,0 +1,142 @@
|
||||
/* dfltcc_inflate.c - IBM Z DEFLATE CONVERSION CALL decompression support. */
|
||||
|
||||
/*
|
||||
Use the following commands to build zlib-ng with DFLTCC decompression support:
|
||||
|
||||
$ ./configure --with-dfltcc-inflate
|
||||
or
|
||||
|
||||
$ cmake -DWITH_DFLTCC_INFLATE=1 .
|
||||
|
||||
and then
|
||||
|
||||
$ make
|
||||
*/
|
||||
|
||||
#include "zbuild.h"
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
#include "inflate.h"
|
||||
#include "dfltcc_inflate.h"
|
||||
#include "dfltcc_detail.h"
|
||||
|
||||
int ZLIB_INTERNAL dfltcc_can_inflate(PREFIX3(streamp) strm)
|
||||
{
|
||||
struct inflate_state *state = (struct inflate_state *)strm->state;
|
||||
struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
|
||||
|
||||
/* Unsupported compression settings */
|
||||
if (state->wbits != HB_BITS)
|
||||
return 0;
|
||||
|
||||
/* Unsupported hardware */
|
||||
return is_bit_set(dfltcc_state->af.fns, DFLTCC_XPND) && is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0);
|
||||
}
|
||||
|
||||
static inline dfltcc_cc dfltcc_xpnd(PREFIX3(streamp) strm)
|
||||
{
|
||||
struct inflate_state *state = (struct inflate_state *)strm->state;
|
||||
struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
|
||||
size_t avail_in = strm->avail_in;
|
||||
size_t avail_out = strm->avail_out;
|
||||
dfltcc_cc cc;
|
||||
|
||||
cc = dfltcc(DFLTCC_XPND | HBT_CIRCULAR,
|
||||
param, &strm->next_out, &avail_out,
|
||||
&strm->next_in, &avail_in, state->window);
|
||||
strm->avail_in = avail_in;
|
||||
strm->avail_out = avail_out;
|
||||
return cc;
|
||||
}
|
||||
|
||||
dfltcc_inflate_action ZLIB_INTERNAL dfltcc_inflate(PREFIX3(streamp) strm, int flush, int *ret)
|
||||
{
|
||||
struct inflate_state *state = (struct inflate_state *)strm->state;
|
||||
struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
|
||||
struct dfltcc_param_v0 *param = &dfltcc_state->param;
|
||||
dfltcc_cc cc;
|
||||
|
||||
if (flush == Z_BLOCK || flush == Z_TREES) {
|
||||
/* DFLTCC does not support stopping on block boundaries */
|
||||
if (dfltcc_inflate_disable(strm)) {
|
||||
*ret = Z_STREAM_ERROR;
|
||||
return DFLTCC_INFLATE_BREAK;
|
||||
} else
|
||||
return DFLTCC_INFLATE_SOFTWARE;
|
||||
}
|
||||
|
||||
if (state->last) {
|
||||
if (state->bits != 0) {
|
||||
strm->next_in++;
|
||||
strm->avail_in--;
|
||||
state->bits = 0;
|
||||
}
|
||||
state->mode = CHECK;
|
||||
return DFLTCC_INFLATE_CONTINUE;
|
||||
}
|
||||
|
||||
if (strm->avail_in == 0 && !param->cf)
|
||||
return DFLTCC_INFLATE_BREAK;
|
||||
|
||||
if (inflate_ensure_window(state)) {
|
||||
state->mode = MEM;
|
||||
return DFLTCC_INFLATE_CONTINUE;
|
||||
}
|
||||
|
||||
/* Translate stream to parameter block */
|
||||
param->cvt = state->flags ? CVT_CRC32 : CVT_ADLER32;
|
||||
param->sbb = state->bits;
|
||||
param->hl = state->whave; /* Software and hardware history formats match */
|
||||
param->ho = (state->wnext - state->whave) & ((1 << HB_BITS) - 1);
|
||||
if (param->hl)
|
||||
param->nt = 0; /* Honor history for the first block */
|
||||
param->cv = state->flags ? ZSWAP32(state->check) : state->check;
|
||||
|
||||
/* Inflate */
|
||||
do {
|
||||
cc = dfltcc_xpnd(strm);
|
||||
} while (cc == DFLTCC_CC_AGAIN);
|
||||
|
||||
/* Translate parameter block to stream */
|
||||
strm->msg = oesc_msg(dfltcc_state->msg, param->oesc);
|
||||
state->last = cc == DFLTCC_CC_OK;
|
||||
state->bits = param->sbb;
|
||||
state->whave = param->hl;
|
||||
state->wnext = (param->ho + param->hl) & ((1 << HB_BITS) - 1);
|
||||
state->check = state->flags ? ZSWAP32(param->cv) : param->cv;
|
||||
if (cc == DFLTCC_CC_OP2_CORRUPT && param->oesc != 0) {
|
||||
/* Report an error if stream is corrupted */
|
||||
state->mode = BAD;
|
||||
return DFLTCC_INFLATE_CONTINUE;
|
||||
}
|
||||
state->mode = TYPEDO;
|
||||
/* Break if operands are exhausted, otherwise continue looping */
|
||||
return (cc == DFLTCC_CC_OP1_TOO_SHORT || cc == DFLTCC_CC_OP2_TOO_SHORT) ?
|
||||
DFLTCC_INFLATE_BREAK : DFLTCC_INFLATE_CONTINUE;
|
||||
}
|
||||
|
||||
int ZLIB_INTERNAL dfltcc_was_inflate_used(PREFIX3(streamp) strm)
|
||||
{
|
||||
struct inflate_state *state = (struct inflate_state *)strm->state;
|
||||
struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
|
||||
|
||||
return !param->nt;
|
||||
}
|
||||
|
||||
int ZLIB_INTERNAL dfltcc_inflate_disable(PREFIX3(streamp) strm)
|
||||
{
|
||||
struct inflate_state *state = (struct inflate_state *)strm->state;
|
||||
struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
|
||||
|
||||
if (!dfltcc_can_inflate(strm))
|
||||
return 0;
|
||||
if (dfltcc_was_inflate_used(strm))
|
||||
/* DFLTCC has already decompressed some data. Since there is not
|
||||
* enough information to resume decompression in software, the call
|
||||
* must fail.
|
||||
*/
|
||||
return 1;
|
||||
/* DFLTCC was not used yet - decompress in software */
|
||||
memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af));
|
||||
return 0;
|
||||
}
|
||||
44
libs/zlibng/arch/s390/dfltcc_inflate.h
Normal file
44
libs/zlibng/arch/s390/dfltcc_inflate.h
Normal file
@ -0,0 +1,44 @@
|
||||
#ifndef DFLTCC_INFLATE_H
|
||||
#define DFLTCC_INFLATE_H
|
||||
|
||||
#include "dfltcc_common.h"
|
||||
|
||||
int ZLIB_INTERNAL dfltcc_can_inflate(PREFIX3(streamp) strm);
|
||||
typedef enum {
|
||||
DFLTCC_INFLATE_CONTINUE,
|
||||
DFLTCC_INFLATE_BREAK,
|
||||
DFLTCC_INFLATE_SOFTWARE,
|
||||
} dfltcc_inflate_action;
|
||||
dfltcc_inflate_action ZLIB_INTERNAL dfltcc_inflate(PREFIX3(streamp) strm, int flush, int *ret);
|
||||
int ZLIB_INTERNAL dfltcc_was_inflate_used(PREFIX3(streamp) strm);
|
||||
int ZLIB_INTERNAL dfltcc_inflate_disable(PREFIX3(streamp) strm);
|
||||
|
||||
#define INFLATE_RESET_KEEP_HOOK(strm) \
|
||||
dfltcc_reset((strm), sizeof(struct inflate_state))
|
||||
|
||||
#define INFLATE_PRIME_HOOK(strm, bits, value) \
|
||||
do { if (dfltcc_inflate_disable((strm))) return Z_STREAM_ERROR; } while (0)
|
||||
|
||||
#define INFLATE_TYPEDO_HOOK(strm, flush) \
|
||||
if (dfltcc_can_inflate((strm))) { \
|
||||
dfltcc_inflate_action action; \
|
||||
\
|
||||
RESTORE(); \
|
||||
action = dfltcc_inflate((strm), (flush), &ret); \
|
||||
LOAD(); \
|
||||
if (action == DFLTCC_INFLATE_CONTINUE) \
|
||||
break; \
|
||||
else if (action == DFLTCC_INFLATE_BREAK) \
|
||||
goto inf_leave; \
|
||||
}
|
||||
|
||||
#define INFLATE_NEED_CHECKSUM(strm) (!dfltcc_can_inflate((strm)))
|
||||
|
||||
#define INFLATE_NEED_UPDATEWINDOW(strm) (!dfltcc_can_inflate((strm)))
|
||||
|
||||
#define INFLATE_MARK_HOOK(strm) \
|
||||
do { \
|
||||
if (dfltcc_was_inflate_used((strm))) return -(1L << 16); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
79
libs/zlibng/compress.c
Normal file
79
libs/zlibng/compress.c
Normal file
@ -0,0 +1,79 @@
|
||||
/* compress.c -- compress a memory buffer
|
||||
* Copyright (C) 1995-2005, 2014, 2016 Jean-loup Gailly, Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include "zbuild.h"
|
||||
#if defined(ZLIB_COMPAT)
|
||||
# include "zlib.h"
|
||||
#else
|
||||
# include "zlib-ng.h"
|
||||
#endif
|
||||
|
||||
/* ===========================================================================
|
||||
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 PREFIX(compress2)(unsigned char *dest, z_size_t *destLen, const unsigned char *source,
|
||||
z_size_t sourceLen, int level) {
|
||||
PREFIX3(stream) stream;
|
||||
int err;
|
||||
const unsigned int max = (unsigned int)-1;
|
||||
z_size_t left;
|
||||
|
||||
left = *destLen;
|
||||
*destLen = 0;
|
||||
|
||||
stream.zalloc = NULL;
|
||||
stream.zfree = NULL;
|
||||
stream.opaque = NULL;
|
||||
|
||||
err = PREFIX(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 = PREFIX(deflate)(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH);
|
||||
} while (err == Z_OK);
|
||||
|
||||
*destLen = (z_size_t)stream.total_out;
|
||||
PREFIX(deflateEnd)(&stream);
|
||||
return err == Z_STREAM_END ? Z_OK : err;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
*/
|
||||
int ZEXPORT PREFIX(compress)(unsigned char *dest, z_size_t *destLen, const unsigned char *source, z_size_t sourceLen) {
|
||||
return PREFIX(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.
|
||||
*/
|
||||
z_size_t ZEXPORT PREFIX(compressBound)(z_size_t sourceLen) {
|
||||
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13;
|
||||
}
|
||||
1503
libs/zlibng/configure
vendored
Normal file
1503
libs/zlibng/configure
vendored
Normal file
File diff suppressed because it is too large
Load Diff
498
libs/zlibng/crc32.c
Normal file
498
libs/zlibng/crc32.c
Normal file
@ -0,0 +1,498 @@
|
||||
/* crc32.c -- compute the CRC-32 of a data stream
|
||||
* Copyright (C) 1995-2006, 2010, 2011, 2012, 2016, 2018 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$ */
|
||||
|
||||
# include "zbuild.h"
|
||||
# include "gzendian.h"
|
||||
# include <inttypes.h>
|
||||
|
||||
/*
|
||||
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. A main()
|
||||
routine is also produced, so that this one source file can be compiled to an
|
||||
executable.
|
||||
*/
|
||||
|
||||
#ifdef MAKECRCH
|
||||
# include <stdio.h>
|
||||
# ifndef DYNAMIC_CRC_TABLE
|
||||
# define DYNAMIC_CRC_TABLE
|
||||
# endif /* !DYNAMIC_CRC_TABLE */
|
||||
#endif /* MAKECRCH */
|
||||
|
||||
#include "deflate.h"
|
||||
#include "functable.h"
|
||||
|
||||
|
||||
/* Local functions for crc concatenation */
|
||||
#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
|
||||
static uint32_t gf2_matrix_times(const uint32_t *mat, uint32_t vec);
|
||||
static uint32_t crc32_combine_(uint32_t crc1, uint32_t crc2, z_off64_t len2);
|
||||
static void crc32_combine_gen_(uint32_t *op, z_off64_t len2);
|
||||
|
||||
/* ========================================================================= */
|
||||
static uint32_t gf2_matrix_times(const uint32_t *mat, uint32_t vec) {
|
||||
uint32_t sum = 0;
|
||||
while (vec) {
|
||||
if (vec & 1)
|
||||
sum ^= *mat;
|
||||
vec >>= 1;
|
||||
mat++;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
volatile int crc_table_empty = 1;
|
||||
static uint32_t crc_table[8][256];
|
||||
static uint32_t crc_comb[GF2_DIM][GF2_DIM];
|
||||
void make_crc_table(void);
|
||||
static void gf2_matrix_square(uint32_t *square, const uint32_t *mat);
|
||||
#ifdef MAKECRCH
|
||||
static void write_table(FILE *, const uint32_t *, int);
|
||||
#endif /* MAKECRCH */
|
||||
|
||||
/* ========================================================================= */
|
||||
static void gf2_matrix_square(uint32_t *square, const uint32_t *mat) {
|
||||
int n;
|
||||
|
||||
for (n = 0; n < GF2_DIM; n++)
|
||||
square[n] = gf2_matrix_times(mat, mat[n]);
|
||||
}
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* generate zero operators table for crc32_combine() */
|
||||
|
||||
/* generate the operator to apply a single zero bit to a CRC -- the
|
||||
first row adds the polynomial if the low bit is a 1, and the
|
||||
remaining rows shift the CRC right one bit */
|
||||
k = GF2_DIM - 3;
|
||||
crc_comb[k][0] = 0xedb88320UL; /* CRC-32 polynomial */
|
||||
uint32_t row = 1;
|
||||
for (n = 1; n < GF2_DIM; n++) {
|
||||
crc_comb[k][n] = row;
|
||||
row <<= 1;
|
||||
}
|
||||
|
||||
/* generate operators that apply 2, 4, and 8 zeros to a CRC, putting
|
||||
the last one, the operator for one zero byte, at the 0 position */
|
||||
gf2_matrix_square(crc_comb[k + 1], crc_comb[k]);
|
||||
gf2_matrix_square(crc_comb[k + 2], crc_comb[k + 1]);
|
||||
gf2_matrix_square(crc_comb[0], crc_comb[k + 2]);
|
||||
|
||||
/* generate operators for applying 2^n zero bytes to a CRC, filling out
|
||||
the remainder of the table -- the operators repeat after GF2_DIM
|
||||
values of n, so the table only needs GF2_DIM entries, regardless of
|
||||
the size of the length being processed */
|
||||
for (n = 1; n < k; n++)
|
||||
gf2_matrix_square(crc_comb[n], crc_comb[n - 1]);
|
||||
|
||||
/* mark tables as complete, in case someone else is waiting */
|
||||
crc_table_empty = 0;
|
||||
} else { /* not first */
|
||||
/* wait for the other guy to finish (not efficient, but rare) */
|
||||
while (crc_table_empty)
|
||||
{}
|
||||
}
|
||||
#ifdef MAKECRCH
|
||||
{
|
||||
FILE *out;
|
||||
|
||||
out = fopen("crc32.h", "w");
|
||||
if (out == NULL) return;
|
||||
|
||||
/* write out CRC table to crc32.h */
|
||||
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], 256);
|
||||
for (k = 1; k < 8; k++) {
|
||||
fprintf(out, " },\n {\n");
|
||||
write_table(out, crc_table[k], 256);
|
||||
}
|
||||
fprintf(out, " }\n};\n");
|
||||
|
||||
/* write out zero operator table to crc32.h */
|
||||
fprintf(out, "\nstatic const uint32_t ");
|
||||
fprintf(out, "crc_comb[%d][%d] =\n{\n {\n", GF2_DIM, GF2_DIM);
|
||||
write_table(out, crc_comb[0], GF2_DIM);
|
||||
for (k = 1; k < GF2_DIM; k++) {
|
||||
fprintf(out, " },\n {\n");
|
||||
write_table(out, crc_comb[k], GF2_DIM);
|
||||
}
|
||||
fprintf(out, " }\n};\n");
|
||||
fclose(out);
|
||||
}
|
||||
#endif /* MAKECRCH */
|
||||
}
|
||||
|
||||
#ifdef MAKECRCH
|
||||
static void write_table(FILE *out, const uint32_t *table, int k) {
|
||||
int n;
|
||||
|
||||
for (n = 0; n < k; n++)
|
||||
fprintf(out, "%s0x%08" PRIx32 "%s", n % 5 ? "" : " ",
|
||||
(uint32_t)(table[n]),
|
||||
n == k - 1 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
make_crc_table();
|
||||
return 0;
|
||||
}
|
||||
#endif /* MAKECRCH */
|
||||
|
||||
#else /* !DYNAMIC_CRC_TABLE */
|
||||
/* ========================================================================
|
||||
* Tables of CRC-32s of all single-byte values, made by make_crc_table(),
|
||||
* and tables of zero operator matrices for crc32_combine().
|
||||
*/
|
||||
#include "crc32.h"
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
|
||||
/* =========================================================================
|
||||
* This function can be used by asm versions of crc32()
|
||||
*/
|
||||
const uint32_t * ZEXPORT PREFIX(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;
|
||||
}
|
||||
|
||||
uint32_t ZEXPORT PREFIX(crc32_z)(uint32_t crc, const unsigned char *buf, size_t len) {
|
||||
if (buf == NULL) return 0;
|
||||
|
||||
return functable.crc32(crc, buf, len);
|
||||
}
|
||||
/* ========================================================================= */
|
||||
#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
|
||||
|
||||
/* ========================================================================= */
|
||||
ZLIB_INTERNAL uint32_t crc32_generic(uint32_t crc, const unsigned char *buf, uint64_t len)
|
||||
{
|
||||
crc = crc ^ 0xffffffff;
|
||||
|
||||
#ifdef UNROLL_MORE
|
||||
while (len >= 8) {
|
||||
DO8;
|
||||
len -= 8;
|
||||
}
|
||||
#else
|
||||
while (len >= 4) {
|
||||
DO4;
|
||||
len -= 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (len) do {
|
||||
DO1;
|
||||
} while (--len);
|
||||
return crc ^ 0xffffffff;
|
||||
}
|
||||
|
||||
uint32_t ZEXPORT PREFIX(crc32)(uint32_t crc, const unsigned char *buf, uint32_t len) {
|
||||
return PREFIX(crc32_z)(crc, buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit
|
||||
integer pointer type. This violates the strict aliasing rule, where a
|
||||
compiler can assume, for optimization purposes, that two pointers to
|
||||
fundamentally different types won't ever point to the same memory. This can
|
||||
manifest as a problem only if one of the pointers is written to. This code
|
||||
only reads from those pointers. So long as this code remains isolated in
|
||||
this compilation unit, there won't be a problem. For this reason, this code
|
||||
should not be copied and pasted into a compilation unit in which other code
|
||||
writes to the buffer that is passed to these routines.
|
||||
*/
|
||||
|
||||
/* ========================================================================= */
|
||||
#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
|
||||
|
||||
/* ========================================================================= */
|
||||
ZLIB_INTERNAL uint32_t crc32_little(uint32_t crc, const unsigned char *buf, uint64_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;
|
||||
|
||||
#ifdef UNROLL_MORE
|
||||
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
|
||||
|
||||
/* ========================================================================= */
|
||||
ZLIB_INTERNAL uint32_t crc32_big(uint32_t crc, const unsigned char *buf, uint64_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;
|
||||
|
||||
#ifdef UNROLL_MORE
|
||||
while (len >= 32) {
|
||||
DOBIG32;
|
||||
len -= 32;
|
||||
}
|
||||
#endif
|
||||
|
||||
while (len >= 4) {
|
||||
DOBIG4;
|
||||
len -= 4;
|
||||
}
|
||||
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 */
|
||||
|
||||
|
||||
/* ========================================================================= */
|
||||
static uint32_t crc32_combine_(uint32_t crc1, uint32_t crc2, z_off64_t len2) {
|
||||
int n;
|
||||
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
if (crc_table_empty)
|
||||
make_crc_table();
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
|
||||
if (len2 > 0)
|
||||
/* operator for 2^n zeros repeats every GF2_DIM n values */
|
||||
for (n = 0; len2; n = (n + 1) % GF2_DIM, len2 >>= 1)
|
||||
if (len2 & 1)
|
||||
crc1 = gf2_matrix_times(crc_comb[n], crc1);
|
||||
return crc1 ^ crc2;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uint32_t ZEXPORT PREFIX(crc32_combine)(uint32_t crc1, uint32_t crc2, z_off_t len2) {
|
||||
return crc32_combine_(crc1, crc2, len2);
|
||||
}
|
||||
|
||||
uint32_t ZEXPORT PREFIX(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"
|
||||
#include "arch/x86/crc_folding.h"
|
||||
|
||||
ZLIB_INTERNAL void crc_finalize(deflate_state *const s) {
|
||||
if (x86_cpu_has_pclmulqdq)
|
||||
s->strm->adler = crc_fold_512to32(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 = PREFIX(crc32)(0L, NULL, 0);
|
||||
}
|
||||
|
||||
ZLIB_INTERNAL void copy_with_crc(PREFIX3(stream) *strm, unsigned char *dst, unsigned 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 = PREFIX(crc32)(strm->adler, dst, size);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
static void crc32_combine_gen_(uint32_t *op, z_off64_t len2)
|
||||
{
|
||||
uint32_t row;
|
||||
int j;
|
||||
unsigned i;
|
||||
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
if (crc_table_empty)
|
||||
make_crc_table();
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
|
||||
/* if len2 is zero or negative, return the identity matrix */
|
||||
if (len2 <= 0) {
|
||||
row = 1;
|
||||
for (j = 0; j < GF2_DIM; j++) {
|
||||
op[j] = row;
|
||||
row <<= 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* at least one bit in len2 is set -- find it, and copy the operator
|
||||
corresponding to that position into op */
|
||||
i = 0;
|
||||
for (;;) {
|
||||
if (len2 & 1) {
|
||||
for (j = 0; j < GF2_DIM; j++)
|
||||
op[j] = crc_comb[i][j];
|
||||
break;
|
||||
}
|
||||
len2 >>= 1;
|
||||
i = (i + 1) % GF2_DIM;
|
||||
}
|
||||
|
||||
/* for each remaining bit set in len2 (if any), multiply op by the operator
|
||||
corresponding to that position */
|
||||
for (;;) {
|
||||
len2 >>= 1;
|
||||
i = (i + 1) % GF2_DIM;
|
||||
if (len2 == 0)
|
||||
break;
|
||||
if (len2 & 1)
|
||||
for (j = 0; j < GF2_DIM; j++)
|
||||
op[j] = gf2_matrix_times(crc_comb[i], op[j]);
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
void ZEXPORT PREFIX(crc32_combine_gen)(uint32_t *op, z_off_t len2)
|
||||
{
|
||||
crc32_combine_gen_(op, len2);
|
||||
}
|
||||
|
||||
void ZEXPORT PREFIX(crc32_combine_gen64)(uint32_t *op, z_off64_t len2)
|
||||
{
|
||||
crc32_combine_gen_(op, len2);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uint32_t ZEXPORT PREFIX(crc32_combine_op)(uint32_t crc1, uint32_t crc2, const uint32_t *op)
|
||||
{
|
||||
return gf2_matrix_times(op, crc1) ^ crc2;
|
||||
}
|
||||
735
libs/zlibng/crc32.h
Normal file
735
libs/zlibng/crc32.h
Normal file
@ -0,0 +1,735 @@
|
||||
#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
|
||||
}
|
||||
};
|
||||
|
||||
static const uint32_t crc_comb[32][32] =
|
||||
{
|
||||
{
|
||||
0x77073096UL, 0xee0e612cUL, 0x076dc419UL, 0x0edb8832UL, 0x1db71064UL,
|
||||
0x3b6e20c8UL, 0x76dc4190UL, 0xedb88320UL, 0x00000001UL, 0x00000002UL,
|
||||
0x00000004UL, 0x00000008UL, 0x00000010UL, 0x00000020UL, 0x00000040UL,
|
||||
0x00000080UL, 0x00000100UL, 0x00000200UL, 0x00000400UL, 0x00000800UL,
|
||||
0x00001000UL, 0x00002000UL, 0x00004000UL, 0x00008000UL, 0x00010000UL,
|
||||
0x00020000UL, 0x00040000UL, 0x00080000UL, 0x00100000UL, 0x00200000UL,
|
||||
0x00400000UL, 0x00800000UL
|
||||
},
|
||||
{
|
||||
0x191b3141UL, 0x32366282UL, 0x646cc504UL, 0xc8d98a08UL, 0x4ac21251UL,
|
||||
0x958424a2UL, 0xf0794f05UL, 0x3b83984bUL, 0x77073096UL, 0xee0e612cUL,
|
||||
0x076dc419UL, 0x0edb8832UL, 0x1db71064UL, 0x3b6e20c8UL, 0x76dc4190UL,
|
||||
0xedb88320UL, 0x00000001UL, 0x00000002UL, 0x00000004UL, 0x00000008UL,
|
||||
0x00000010UL, 0x00000020UL, 0x00000040UL, 0x00000080UL, 0x00000100UL,
|
||||
0x00000200UL, 0x00000400UL, 0x00000800UL, 0x00001000UL, 0x00002000UL,
|
||||
0x00004000UL, 0x00008000UL
|
||||
},
|
||||
{
|
||||
0xb8bc6765UL, 0xaa09c88bUL, 0x8f629757UL, 0xc5b428efUL, 0x5019579fUL,
|
||||
0xa032af3eUL, 0x9b14583dUL, 0xed59b63bUL, 0x01c26a37UL, 0x0384d46eUL,
|
||||
0x0709a8dcUL, 0x0e1351b8UL, 0x1c26a370UL, 0x384d46e0UL, 0x709a8dc0UL,
|
||||
0xe1351b80UL, 0x191b3141UL, 0x32366282UL, 0x646cc504UL, 0xc8d98a08UL,
|
||||
0x4ac21251UL, 0x958424a2UL, 0xf0794f05UL, 0x3b83984bUL, 0x77073096UL,
|
||||
0xee0e612cUL, 0x076dc419UL, 0x0edb8832UL, 0x1db71064UL, 0x3b6e20c8UL,
|
||||
0x76dc4190UL, 0xedb88320UL
|
||||
},
|
||||
{
|
||||
0xccaa009eUL, 0x4225077dUL, 0x844a0efaUL, 0xd3e51bb5UL, 0x7cbb312bUL,
|
||||
0xf9766256UL, 0x299dc2edUL, 0x533b85daUL, 0xa6770bb4UL, 0x979f1129UL,
|
||||
0xf44f2413UL, 0x33ef4e67UL, 0x67de9cceUL, 0xcfbd399cUL, 0x440b7579UL,
|
||||
0x8816eaf2UL, 0xcb5cd3a5UL, 0x4dc8a10bUL, 0x9b914216UL, 0xec53826dUL,
|
||||
0x03d6029bUL, 0x07ac0536UL, 0x0f580a6cUL, 0x1eb014d8UL, 0x3d6029b0UL,
|
||||
0x7ac05360UL, 0xf580a6c0UL, 0x30704bc1UL, 0x60e09782UL, 0xc1c12f04UL,
|
||||
0x58f35849UL, 0xb1e6b092UL
|
||||
},
|
||||
{
|
||||
0xae689191UL, 0x87a02563UL, 0xd4314c87UL, 0x73139f4fUL, 0xe6273e9eUL,
|
||||
0x173f7b7dUL, 0x2e7ef6faUL, 0x5cfdedf4UL, 0xb9fbdbe8UL, 0xa886b191UL,
|
||||
0x8a7c6563UL, 0xcf89cc87UL, 0x44629f4fUL, 0x88c53e9eUL, 0xcafb7b7dUL,
|
||||
0x4e87f0bbUL, 0x9d0fe176UL, 0xe16ec4adUL, 0x19ac8f1bUL, 0x33591e36UL,
|
||||
0x66b23c6cUL, 0xcd6478d8UL, 0x41b9f7f1UL, 0x8373efe2UL, 0xdd96d985UL,
|
||||
0x605cb54bUL, 0xc0b96a96UL, 0x5a03d36dUL, 0xb407a6daUL, 0xb37e4bf5UL,
|
||||
0xbd8d91abUL, 0xa06a2517UL
|
||||
},
|
||||
{
|
||||
0xf1da05aaUL, 0x38c50d15UL, 0x718a1a2aUL, 0xe3143454UL, 0x1d596ee9UL,
|
||||
0x3ab2ddd2UL, 0x7565bba4UL, 0xeacb7748UL, 0x0ee7e8d1UL, 0x1dcfd1a2UL,
|
||||
0x3b9fa344UL, 0x773f4688UL, 0xee7e8d10UL, 0x078c1c61UL, 0x0f1838c2UL,
|
||||
0x1e307184UL, 0x3c60e308UL, 0x78c1c610UL, 0xf1838c20UL, 0x38761e01UL,
|
||||
0x70ec3c02UL, 0xe1d87804UL, 0x18c1f649UL, 0x3183ec92UL, 0x6307d924UL,
|
||||
0xc60fb248UL, 0x576e62d1UL, 0xaedcc5a2UL, 0x86c88d05UL, 0xd6e01c4bUL,
|
||||
0x76b13ed7UL, 0xed627daeUL
|
||||
},
|
||||
{
|
||||
0x8f352d95UL, 0xc51b5d6bUL, 0x5147bc97UL, 0xa28f792eUL, 0x9e6ff41dUL,
|
||||
0xe7aeee7bUL, 0x142cdab7UL, 0x2859b56eUL, 0x50b36adcUL, 0xa166d5b8UL,
|
||||
0x99bcad31UL, 0xe8085c23UL, 0x0b61be07UL, 0x16c37c0eUL, 0x2d86f81cUL,
|
||||
0x5b0df038UL, 0xb61be070UL, 0xb746c6a1UL, 0xb5fc8b03UL, 0xb0881047UL,
|
||||
0xba6126cfUL, 0xafb34bdfUL, 0x841791ffUL, 0xd35e25bfUL, 0x7dcd4d3fUL,
|
||||
0xfb9a9a7eUL, 0x2c4432bdUL, 0x5888657aUL, 0xb110caf4UL, 0xb95093a9UL,
|
||||
0xa9d02113UL, 0x88d14467UL
|
||||
},
|
||||
{
|
||||
0x33fff533UL, 0x67ffea66UL, 0xcfffd4ccUL, 0x448eafd9UL, 0x891d5fb2UL,
|
||||
0xc94bb925UL, 0x49e6740bUL, 0x93cce816UL, 0xfce8d66dUL, 0x22a0aa9bUL,
|
||||
0x45415536UL, 0x8a82aa6cUL, 0xce745299UL, 0x4799a373UL, 0x8f3346e6UL,
|
||||
0xc5178b8dUL, 0x515e115bUL, 0xa2bc22b6UL, 0x9e09432dUL, 0xe763801bUL,
|
||||
0x15b60677UL, 0x2b6c0ceeUL, 0x56d819dcUL, 0xadb033b8UL, 0x80116131UL,
|
||||
0xdb53c423UL, 0x6dd68e07UL, 0xdbad1c0eUL, 0x6c2b3e5dUL, 0xd8567cbaUL,
|
||||
0x6bddff35UL, 0xd7bbfe6aUL
|
||||
},
|
||||
{
|
||||
0xce3371cbUL, 0x4717e5d7UL, 0x8e2fcbaeUL, 0xc72e911dUL, 0x552c247bUL,
|
||||
0xaa5848f6UL, 0x8fc197adUL, 0xc4f2291bUL, 0x52955477UL, 0xa52aa8eeUL,
|
||||
0x9124579dUL, 0xf939a97bUL, 0x290254b7UL, 0x5204a96eUL, 0xa40952dcUL,
|
||||
0x9363a3f9UL, 0xfdb641b3UL, 0x201d8527UL, 0x403b0a4eUL, 0x8076149cUL,
|
||||
0xdb9d2f79UL, 0x6c4b58b3UL, 0xd896b166UL, 0x6a5c648dUL, 0xd4b8c91aUL,
|
||||
0x72009475UL, 0xe40128eaUL, 0x13735795UL, 0x26e6af2aUL, 0x4dcd5e54UL,
|
||||
0x9b9abca8UL, 0xec447f11UL
|
||||
},
|
||||
{
|
||||
0x1072db28UL, 0x20e5b650UL, 0x41cb6ca0UL, 0x8396d940UL, 0xdc5cb4c1UL,
|
||||
0x63c86fc3UL, 0xc790df86UL, 0x5450b94dUL, 0xa8a1729aUL, 0x8a33e375UL,
|
||||
0xcf16c0abUL, 0x455c8717UL, 0x8ab90e2eUL, 0xce031a1dUL, 0x4777327bUL,
|
||||
0x8eee64f6UL, 0xc6adcfadUL, 0x562a991bUL, 0xac553236UL, 0x83db622dUL,
|
||||
0xdcc7c21bUL, 0x62fe8277UL, 0xc5fd04eeUL, 0x508b0f9dUL, 0xa1161f3aUL,
|
||||
0x995d3835UL, 0xe9cb762bUL, 0x08e7ea17UL, 0x11cfd42eUL, 0x239fa85cUL,
|
||||
0x473f50b8UL, 0x8e7ea170UL
|
||||
},
|
||||
{
|
||||
0xf891f16fUL, 0x2a52e49fUL, 0x54a5c93eUL, 0xa94b927cUL, 0x89e622b9UL,
|
||||
0xc8bd4333UL, 0x4a0b8027UL, 0x9417004eUL, 0xf35f06ddUL, 0x3dcf0bfbUL,
|
||||
0x7b9e17f6UL, 0xf73c2fecUL, 0x35095999UL, 0x6a12b332UL, 0xd4256664UL,
|
||||
0x733bca89UL, 0xe6779512UL, 0x179e2c65UL, 0x2f3c58caUL, 0x5e78b194UL,
|
||||
0xbcf16328UL, 0xa293c011UL, 0x9e568663UL, 0xe7dc0a87UL, 0x14c9134fUL,
|
||||
0x2992269eUL, 0x53244d3cUL, 0xa6489a78UL, 0x97e032b1UL, 0xf4b16323UL,
|
||||
0x3213c007UL, 0x6427800eUL
|
||||
},
|
||||
{
|
||||
0x88b6ba63UL, 0xca1c7287UL, 0x4f49e34fUL, 0x9e93c69eUL, 0xe6568b7dUL,
|
||||
0x17dc10bbUL, 0x2fb82176UL, 0x5f7042ecUL, 0xbee085d8UL, 0xa6b00df1UL,
|
||||
0x96111da3UL, 0xf7533d07UL, 0x35d77c4fUL, 0x6baef89eUL, 0xd75df13cUL,
|
||||
0x75cae439UL, 0xeb95c872UL, 0x0c5a96a5UL, 0x18b52d4aUL, 0x316a5a94UL,
|
||||
0x62d4b528UL, 0xc5a96a50UL, 0x5023d2e1UL, 0xa047a5c2UL, 0x9bfe4dc5UL,
|
||||
0xec8d9dcbUL, 0x026a3dd7UL, 0x04d47baeUL, 0x09a8f75cUL, 0x1351eeb8UL,
|
||||
0x26a3dd70UL, 0x4d47bae0UL
|
||||
},
|
||||
{
|
||||
0x5ad8a92cUL, 0xb5b15258UL, 0xb013a2f1UL, 0xbb5643a3UL, 0xaddd8107UL,
|
||||
0x80ca044fUL, 0xdae50edfUL, 0x6ebb1bffUL, 0xdd7637feUL, 0x619d69bdUL,
|
||||
0xc33ad37aUL, 0x5d04a0b5UL, 0xba09416aUL, 0xaf638495UL, 0x85b60f6bUL,
|
||||
0xd01d1897UL, 0x7b4b376fUL, 0xf6966edeUL, 0x365ddbfdUL, 0x6cbbb7faUL,
|
||||
0xd9776ff4UL, 0x699fd9a9UL, 0xd33fb352UL, 0x7d0e60e5UL, 0xfa1cc1caUL,
|
||||
0x2f4885d5UL, 0x5e910baaUL, 0xbd221754UL, 0xa13528e9UL, 0x991b5793UL,
|
||||
0xe947a967UL, 0x09fe548fUL
|
||||
},
|
||||
{
|
||||
0xb566f6e2UL, 0xb1bceb85UL, 0xb808d14bUL, 0xab60a4d7UL, 0x8db04fefUL,
|
||||
0xc011999fUL, 0x5b52357fUL, 0xb6a46afeUL, 0xb639d3bdUL, 0xb702a13bUL,
|
||||
0xb5744437UL, 0xb1998e2fUL, 0xb8421a1fUL, 0xabf5327fUL, 0x8c9b62bfUL,
|
||||
0xc247c33fUL, 0x5ffe803fUL, 0xbffd007eUL, 0xa48b06bdUL, 0x92670b3bUL,
|
||||
0xffbf1037UL, 0x240f262fUL, 0x481e4c5eUL, 0x903c98bcUL, 0xfb083739UL,
|
||||
0x2d616833UL, 0x5ac2d066UL, 0xb585a0ccUL, 0xb07a47d9UL, 0xbb8589f3UL,
|
||||
0xac7a15a7UL, 0x83852d0fUL
|
||||
},
|
||||
{
|
||||
0x9d9129bfUL, 0xe053553fUL, 0x1bd7ac3fUL, 0x37af587eUL, 0x6f5eb0fcUL,
|
||||
0xdebd61f8UL, 0x660bc5b1UL, 0xcc178b62UL, 0x435e1085UL, 0x86bc210aUL,
|
||||
0xd6094455UL, 0x77638eebUL, 0xeec71dd6UL, 0x06ff3dedUL, 0x0dfe7bdaUL,
|
||||
0x1bfcf7b4UL, 0x37f9ef68UL, 0x6ff3ded0UL, 0xdfe7bda0UL, 0x64be7d01UL,
|
||||
0xc97cfa02UL, 0x4988f245UL, 0x9311e48aUL, 0xfd52cf55UL, 0x21d498ebUL,
|
||||
0x43a931d6UL, 0x875263acUL, 0xd5d5c119UL, 0x70da8473UL, 0xe1b508e6UL,
|
||||
0x181b178dUL, 0x30362f1aUL
|
||||
},
|
||||
{
|
||||
0x2ee43a2cUL, 0x5dc87458UL, 0xbb90e8b0UL, 0xac50d721UL, 0x83d0a803UL,
|
||||
0xdcd05647UL, 0x62d1aacfUL, 0xc5a3559eUL, 0x5037ad7dUL, 0xa06f5afaUL,
|
||||
0x9bafb3b5UL, 0xec2e612bUL, 0x032dc417UL, 0x065b882eUL, 0x0cb7105cUL,
|
||||
0x196e20b8UL, 0x32dc4170UL, 0x65b882e0UL, 0xcb7105c0UL, 0x4d930dc1UL,
|
||||
0x9b261b82UL, 0xed3d3145UL, 0x010b64cbUL, 0x0216c996UL, 0x042d932cUL,
|
||||
0x085b2658UL, 0x10b64cb0UL, 0x216c9960UL, 0x42d932c0UL, 0x85b26580UL,
|
||||
0xd015cd41UL, 0x7b5a9cc3UL
|
||||
},
|
||||
{
|
||||
0x1b4511eeUL, 0x368a23dcUL, 0x6d1447b8UL, 0xda288f70UL, 0x6f2018a1UL,
|
||||
0xde403142UL, 0x67f164c5UL, 0xcfe2c98aUL, 0x44b49555UL, 0x89692aaaUL,
|
||||
0xc9a35315UL, 0x4837a06bUL, 0x906f40d6UL, 0xfbaf87edUL, 0x2c2e099bUL,
|
||||
0x585c1336UL, 0xb0b8266cUL, 0xba014a99UL, 0xaf739373UL, 0x859620a7UL,
|
||||
0xd05d470fUL, 0x7bcb885fUL, 0xf79710beUL, 0x345f273dUL, 0x68be4e7aUL,
|
||||
0xd17c9cf4UL, 0x79883fa9UL, 0xf3107f52UL, 0x3d51f8e5UL, 0x7aa3f1caUL,
|
||||
0xf547e394UL, 0x31fec169UL
|
||||
},
|
||||
{
|
||||
0xbce15202UL, 0xa2b3a245UL, 0x9e1642cbUL, 0xe75d83d7UL, 0x15ca01efUL,
|
||||
0x2b9403deUL, 0x572807bcUL, 0xae500f78UL, 0x87d118b1UL, 0xd4d33723UL,
|
||||
0x72d76807UL, 0xe5aed00eUL, 0x102ca65dUL, 0x20594cbaUL, 0x40b29974UL,
|
||||
0x816532e8UL, 0xd9bb6391UL, 0x6807c163UL, 0xd00f82c6UL, 0x7b6e03cdUL,
|
||||
0xf6dc079aUL, 0x36c90975UL, 0x6d9212eaUL, 0xdb2425d4UL, 0x6d394de9UL,
|
||||
0xda729bd2UL, 0x6f9431e5UL, 0xdf2863caUL, 0x6521c1d5UL, 0xca4383aaUL,
|
||||
0x4ff60115UL, 0x9fec022aUL
|
||||
},
|
||||
{
|
||||
0xff08e5efUL, 0x2560cd9fUL, 0x4ac19b3eUL, 0x9583367cUL, 0xf0776ab9UL,
|
||||
0x3b9fd333UL, 0x773fa666UL, 0xee7f4cccUL, 0x078f9fd9UL, 0x0f1f3fb2UL,
|
||||
0x1e3e7f64UL, 0x3c7cfec8UL, 0x78f9fd90UL, 0xf1f3fb20UL, 0x3896f001UL,
|
||||
0x712de002UL, 0xe25bc004UL, 0x1fc68649UL, 0x3f8d0c92UL, 0x7f1a1924UL,
|
||||
0xfe343248UL, 0x271962d1UL, 0x4e32c5a2UL, 0x9c658b44UL, 0xe3ba10c9UL,
|
||||
0x1c0527d3UL, 0x380a4fa6UL, 0x70149f4cUL, 0xe0293e98UL, 0x1b237b71UL,
|
||||
0x3646f6e2UL, 0x6c8dedc4UL
|
||||
},
|
||||
{
|
||||
0x6f76172eUL, 0xdeec2e5cUL, 0x66a95af9UL, 0xcd52b5f2UL, 0x41d46da5UL,
|
||||
0x83a8db4aUL, 0xdc20b0d5UL, 0x633067ebUL, 0xc660cfd6UL, 0x57b099edUL,
|
||||
0xaf6133daUL, 0x85b361f5UL, 0xd017c5abUL, 0x7b5e8d17UL, 0xf6bd1a2eUL,
|
||||
0x360b321dUL, 0x6c16643aUL, 0xd82cc874UL, 0x6b2896a9UL, 0xd6512d52UL,
|
||||
0x77d35ce5UL, 0xefa6b9caUL, 0x043c75d5UL, 0x0878ebaaUL, 0x10f1d754UL,
|
||||
0x21e3aea8UL, 0x43c75d50UL, 0x878ebaa0UL, 0xd46c7301UL, 0x73a9e043UL,
|
||||
0xe753c086UL, 0x15d6874dUL
|
||||
},
|
||||
{
|
||||
0x56f5cab9UL, 0xadeb9572UL, 0x80a62ca5UL, 0xda3d5f0bUL, 0x6f0bb857UL,
|
||||
0xde1770aeUL, 0x675fe71dUL, 0xcebfce3aUL, 0x460e9a35UL, 0x8c1d346aUL,
|
||||
0xc34b6e95UL, 0x5de7db6bUL, 0xbbcfb6d6UL, 0xacee6bedUL, 0x82add19bUL,
|
||||
0xde2aa577UL, 0x67244cafUL, 0xce48995eUL, 0x47e034fdUL, 0x8fc069faUL,
|
||||
0xc4f1d5b5UL, 0x5292ad2bUL, 0xa5255a56UL, 0x913bb2edUL, 0xf906639bUL,
|
||||
0x297dc177UL, 0x52fb82eeUL, 0xa5f705dcUL, 0x909f0df9UL, 0xfa4f1db3UL,
|
||||
0x2fef3d27UL, 0x5fde7a4eUL
|
||||
},
|
||||
{
|
||||
0x385993acUL, 0x70b32758UL, 0xe1664eb0UL, 0x19bd9b21UL, 0x337b3642UL,
|
||||
0x66f66c84UL, 0xcdecd908UL, 0x40a8b451UL, 0x815168a2UL, 0xd9d3d705UL,
|
||||
0x68d6a84bUL, 0xd1ad5096UL, 0x782ba76dUL, 0xf0574edaUL, 0x3bdf9bf5UL,
|
||||
0x77bf37eaUL, 0xef7e6fd4UL, 0x058dd9e9UL, 0x0b1bb3d2UL, 0x163767a4UL,
|
||||
0x2c6ecf48UL, 0x58dd9e90UL, 0xb1bb3d20UL, 0xb8077c01UL, 0xab7ffe43UL,
|
||||
0x8d8efac7UL, 0xc06cf3cfUL, 0x5ba8e1dfUL, 0xb751c3beUL, 0xb5d2813dUL,
|
||||
0xb0d4043bUL, 0xbad90e37UL
|
||||
},
|
||||
{
|
||||
0xb4247b20UL, 0xb339f001UL, 0xbd02e643UL, 0xa174cac7UL, 0x999893cfUL,
|
||||
0xe84021dfUL, 0x0bf145ffUL, 0x17e28bfeUL, 0x2fc517fcUL, 0x5f8a2ff8UL,
|
||||
0xbf145ff0UL, 0xa559b9a1UL, 0x91c27503UL, 0xf8f5ec47UL, 0x2a9adecfUL,
|
||||
0x5535bd9eUL, 0xaa6b7b3cUL, 0x8fa7f039UL, 0xc43ee633UL, 0x530cca27UL,
|
||||
0xa619944eUL, 0x97422eddUL, 0xf5f55bfbUL, 0x309bb1b7UL, 0x6137636eUL,
|
||||
0xc26ec6dcUL, 0x5fac8bf9UL, 0xbf5917f2UL, 0xa5c329a5UL, 0x90f7550bUL,
|
||||
0xfa9fac57UL, 0x2e4e5eefUL
|
||||
},
|
||||
{
|
||||
0x695186a7UL, 0xd2a30d4eUL, 0x7e371cddUL, 0xfc6e39baUL, 0x23ad7535UL,
|
||||
0x475aea6aUL, 0x8eb5d4d4UL, 0xc61aafe9UL, 0x57445993UL, 0xae88b326UL,
|
||||
0x8660600dUL, 0xd7b1c65bUL, 0x74128af7UL, 0xe82515eeUL, 0x0b3b2d9dUL,
|
||||
0x16765b3aUL, 0x2cecb674UL, 0x59d96ce8UL, 0xb3b2d9d0UL, 0xbc14b5e1UL,
|
||||
0xa3586d83UL, 0x9dc1dd47UL, 0xe0f2bccfUL, 0x1a947fdfUL, 0x3528ffbeUL,
|
||||
0x6a51ff7cUL, 0xd4a3fef8UL, 0x7236fbb1UL, 0xe46df762UL, 0x13aae885UL,
|
||||
0x2755d10aUL, 0x4eaba214UL
|
||||
},
|
||||
{
|
||||
0x66bc001eUL, 0xcd78003cUL, 0x41810639UL, 0x83020c72UL, 0xdd751ea5UL,
|
||||
0x619b3b0bUL, 0xc3367616UL, 0x5d1dea6dUL, 0xba3bd4daUL, 0xaf06aff5UL,
|
||||
0x857c59abUL, 0xd189b517UL, 0x78626c6fUL, 0xf0c4d8deUL, 0x3af8b7fdUL,
|
||||
0x75f16ffaUL, 0xebe2dff4UL, 0x0cb4b9a9UL, 0x19697352UL, 0x32d2e6a4UL,
|
||||
0x65a5cd48UL, 0xcb4b9a90UL, 0x4de63361UL, 0x9bcc66c2UL, 0xece9cbc5UL,
|
||||
0x02a291cbUL, 0x05452396UL, 0x0a8a472cUL, 0x15148e58UL, 0x2a291cb0UL,
|
||||
0x54523960UL, 0xa8a472c0UL
|
||||
},
|
||||
{
|
||||
0xb58b27b3UL, 0xb0674927UL, 0xbbbf940fUL, 0xac0e2e5fUL, 0x836d5affUL,
|
||||
0xddabb3bfUL, 0x6026613fUL, 0xc04cc27eUL, 0x5be882bdUL, 0xb7d1057aUL,
|
||||
0xb4d30cb5UL, 0xb2d71f2bUL, 0xbedf3817UL, 0xa6cf766fUL, 0x96efea9fUL,
|
||||
0xf6aed37fUL, 0x362ca0bfUL, 0x6c59417eUL, 0xd8b282fcUL, 0x6a1403b9UL,
|
||||
0xd4280772UL, 0x732108a5UL, 0xe642114aUL, 0x17f524d5UL, 0x2fea49aaUL,
|
||||
0x5fd49354UL, 0xbfa926a8UL, 0xa4234b11UL, 0x93379063UL, 0xfd1e2687UL,
|
||||
0x214d4b4fUL, 0x429a969eUL
|
||||
},
|
||||
{
|
||||
0xfe273162UL, 0x273f6485UL, 0x4e7ec90aUL, 0x9cfd9214UL, 0xe28a2269UL,
|
||||
0x1e654293UL, 0x3cca8526UL, 0x79950a4cUL, 0xf32a1498UL, 0x3d252f71UL,
|
||||
0x7a4a5ee2UL, 0xf494bdc4UL, 0x32587dc9UL, 0x64b0fb92UL, 0xc961f724UL,
|
||||
0x49b2e809UL, 0x9365d012UL, 0xfdbaa665UL, 0x20044a8bUL, 0x40089516UL,
|
||||
0x80112a2cUL, 0xdb535219UL, 0x6dd7a273UL, 0xdbaf44e6UL, 0x6c2f8f8dUL,
|
||||
0xd85f1f1aUL, 0x6bcf3875UL, 0xd79e70eaUL, 0x744de795UL, 0xe89bcf2aUL,
|
||||
0x0a469815UL, 0x148d302aUL
|
||||
},
|
||||
{
|
||||
0xd3c98813UL, 0x7ce21667UL, 0xf9c42cceUL, 0x28f95fddUL, 0x51f2bfbaUL,
|
||||
0xa3e57f74UL, 0x9cbbf8a9UL, 0xe206f713UL, 0x1f7ce867UL, 0x3ef9d0ceUL,
|
||||
0x7df3a19cUL, 0xfbe74338UL, 0x2cbf8031UL, 0x597f0062UL, 0xb2fe00c4UL,
|
||||
0xbe8d07c9UL, 0xa66b09d3UL, 0x97a715e7UL, 0xf43f2d8fUL, 0x330f5d5fUL,
|
||||
0x661ebabeUL, 0xcc3d757cUL, 0x430becb9UL, 0x8617d972UL, 0xd75eb4a5UL,
|
||||
0x75cc6f0bUL, 0xeb98de16UL, 0x0c40ba6dUL, 0x188174daUL, 0x3102e9b4UL,
|
||||
0x6205d368UL, 0xc40ba6d0UL
|
||||
},
|
||||
{
|
||||
0xf7d6deb4UL, 0x34dcbb29UL, 0x69b97652UL, 0xd372eca4UL, 0x7d94df09UL,
|
||||
0xfb29be12UL, 0x2d227a65UL, 0x5a44f4caUL, 0xb489e994UL, 0xb262d569UL,
|
||||
0xbfb4ac93UL, 0xa4185f67UL, 0x9341b88fUL, 0xfdf2775fUL, 0x2095e8ffUL,
|
||||
0x412bd1feUL, 0x8257a3fcUL, 0xdfde41b9UL, 0x64cd8533UL, 0xc99b0a66UL,
|
||||
0x4847128dUL, 0x908e251aUL, 0xfa6d4c75UL, 0x2fab9eabUL, 0x5f573d56UL,
|
||||
0xbeae7aacUL, 0xa62df319UL, 0x972ae073UL, 0xf524c6a7UL, 0x31388b0fUL,
|
||||
0x6271161eUL, 0xc4e22c3cUL
|
||||
},
|
||||
{
|
||||
0xedb88320UL, 0x00000001UL, 0x00000002UL, 0x00000004UL, 0x00000008UL,
|
||||
0x00000010UL, 0x00000020UL, 0x00000040UL, 0x00000080UL, 0x00000100UL,
|
||||
0x00000200UL, 0x00000400UL, 0x00000800UL, 0x00001000UL, 0x00002000UL,
|
||||
0x00004000UL, 0x00008000UL, 0x00010000UL, 0x00020000UL, 0x00040000UL,
|
||||
0x00080000UL, 0x00100000UL, 0x00200000UL, 0x00400000UL, 0x00800000UL,
|
||||
0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, 0x10000000UL,
|
||||
0x20000000UL, 0x40000000UL
|
||||
},
|
||||
{
|
||||
0x76dc4190UL, 0xedb88320UL, 0x00000001UL, 0x00000002UL, 0x00000004UL,
|
||||
0x00000008UL, 0x00000010UL, 0x00000020UL, 0x00000040UL, 0x00000080UL,
|
||||
0x00000100UL, 0x00000200UL, 0x00000400UL, 0x00000800UL, 0x00001000UL,
|
||||
0x00002000UL, 0x00004000UL, 0x00008000UL, 0x00010000UL, 0x00020000UL,
|
||||
0x00040000UL, 0x00080000UL, 0x00100000UL, 0x00200000UL, 0x00400000UL,
|
||||
0x00800000UL, 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL,
|
||||
0x10000000UL, 0x20000000UL
|
||||
},
|
||||
{
|
||||
0x1db71064UL, 0x3b6e20c8UL, 0x76dc4190UL, 0xedb88320UL, 0x00000001UL,
|
||||
0x00000002UL, 0x00000004UL, 0x00000008UL, 0x00000010UL, 0x00000020UL,
|
||||
0x00000040UL, 0x00000080UL, 0x00000100UL, 0x00000200UL, 0x00000400UL,
|
||||
0x00000800UL, 0x00001000UL, 0x00002000UL, 0x00004000UL, 0x00008000UL,
|
||||
0x00010000UL, 0x00020000UL, 0x00040000UL, 0x00080000UL, 0x00100000UL,
|
||||
0x00200000UL, 0x00400000UL, 0x00800000UL, 0x01000000UL, 0x02000000UL,
|
||||
0x04000000UL, 0x08000000UL
|
||||
}
|
||||
};
|
||||
#endif /* CRC32_H_ */
|
||||
1712
libs/zlibng/deflate.c
Normal file
1712
libs/zlibng/deflate.c
Normal file
File diff suppressed because it is too large
Load Diff
445
libs/zlibng/deflate.h
Normal file
445
libs/zlibng/deflate.h
Normal file
@ -0,0 +1,445 @@
|
||||
#ifndef DEFLATE_H_
|
||||
#define DEFLATE_H_
|
||||
/* deflate.h -- internal compression state
|
||||
* Copyright (C) 1995-2016 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"
|
||||
#include "gzendian.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 /* zlib header -> BUSY_STATE */
|
||||
#ifdef GZIP
|
||||
# define GZIP_STATE 57 /* gzip header -> BUSY_STATE | EXTRA_STATE */
|
||||
#endif
|
||||
#define EXTRA_STATE 69 /* gzip extra block -> NAME_STATE */
|
||||
#define NAME_STATE 73 /* gzip file name -> COMMENT_STATE */
|
||||
#define COMMENT_STATE 91 /* gzip comment -> HCRC_STATE */
|
||||
#define HCRC_STATE 103 /* gzip header CRC -> BUSY_STATE */
|
||||
#define BUSY_STATE 113 /* deflate -> FINISH_STATE */
|
||||
#define FINISH_STATE 666 /* stream complete */
|
||||
/* 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 {
|
||||
PREFIX3(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 */
|
||||
uint32_t pending; /* nb of bytes in the pending buffer */
|
||||
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
|
||||
PREFIX(gz_headerp) gzhead; /* gzip header information to write */
|
||||
uint32_t 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 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 */
|
||||
|
||||
#if !defined(__x86_64__) && !defined(_M_X64) && !defined(__i386) && !defined(_M_IX86)
|
||||
unsigned int hash_shift;
|
||||
#endif
|
||||
/* 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 *sym_buf; /* buffer for distances and literals/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 sym_next; /* running index in sym_buf */
|
||||
unsigned int sym_end; /* symbol table full when sym_next reaches this */
|
||||
|
||||
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 ZLIB_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.
|
||||
*/
|
||||
int block_open;
|
||||
/* Whether or not a block is currently open for the QUICK deflation scheme.
|
||||
* This is set to 1 if there is an active block, or 0 if the block was just
|
||||
* closed.
|
||||
*/
|
||||
|
||||
} 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++] = (unsigned char)(c);}
|
||||
|
||||
/* ===========================================================================
|
||||
* Output a short LSB first on the stream.
|
||||
* IN assertion: there is enough room in pendingBuf.
|
||||
*/
|
||||
static inline void put_short(deflate_state *s, uint16_t w) {
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
w = ZSWAP16(w);
|
||||
#endif
|
||||
memcpy(&(s->pending_buf[s->pending]), &w, sizeof(uint16_t));
|
||||
s->pending += 2;
|
||||
}
|
||||
|
||||
#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 */
|
||||
|
||||
|
||||
void ZLIB_INTERNAL fill_window_c(deflate_state *s);
|
||||
|
||||
/* 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);
|
||||
unsigned ZLIB_INTERNAL bi_reverse(unsigned code, int len);
|
||||
void ZLIB_INTERNAL flush_pending(PREFIX3(streamp) strm);
|
||||
|
||||
#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 ZLIB_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->sym_buf[s->sym_next++] = 0; \
|
||||
s->sym_buf[s->sym_next++] = 0; \
|
||||
s->sym_buf[s->sym_next++] = cc; \
|
||||
s->dyn_ltree[cc].Freq++; \
|
||||
flush = (s->sym_next == s->sym_end); \
|
||||
}
|
||||
# define _tr_tally_dist(s, distance, length, flush) \
|
||||
{ unsigned char len = (unsigned char)(length); \
|
||||
uint16_t dist = (uint16_t)(distance); \
|
||||
s->sym_buf[s->sym_next++] = dist; \
|
||||
s->sym_buf[s->sym_next++] = dist >> 8; \
|
||||
s->sym_buf[s->sym_next++] = len; \
|
||||
dist--; \
|
||||
s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
|
||||
s->dyn_dtree[d_code(dist)].Freq++; \
|
||||
flush = (s->sym_next == s->sym_end); \
|
||||
}
|
||||
#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, (unsigned)(distance), (unsigned)(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 NOT_TWEAK_COMPILER
|
||||
#define TRIGGER_LEVEL 6
|
||||
#else
|
||||
#define TRIGGER_LEVEL 5
|
||||
#endif
|
||||
|
||||
#if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86)
|
||||
#define UPDATE_HASH(s, h, i) \
|
||||
do {\
|
||||
if (s->level < TRIGGER_LEVEL) \
|
||||
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 ZLIB_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 /* ZLIB_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 ZLIB_DEBUG
|
||||
void send_bits(deflate_state *s, int value, int length);
|
||||
#else
|
||||
#define send_bits(s, value, length) \
|
||||
{ int len = length;\
|
||||
if (s->bi_valid > (int)Buf_size - len) {\
|
||||
int val = (int)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_ */
|
||||
120
libs/zlibng/deflate_fast.c
Normal file
120
libs/zlibng/deflate_fast.c
Normal file
@ -0,0 +1,120 @@
|
||||
/* 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 "zbuild.h"
|
||||
#include "deflate.h"
|
||||
#include "deflate_p.h"
|
||||
#include "match_p.h"
|
||||
#include "functable.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.
|
||||
*/
|
||||
ZLIB_INTERNAL 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) {
|
||||
functable.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 = functable.insert_string(s, s->strstart, 1);
|
||||
}
|
||||
|
||||
/* 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 {
|
||||
functable.insert_string(s, s->strstart, 1);
|
||||
s->strstart++;
|
||||
/* strstart never exceeds WSIZE-MAX_MATCH, so there are
|
||||
* always MIN_MATCH bytes ahead.
|
||||
*/
|
||||
} while (--s->match_length != 0);
|
||||
#else
|
||||
{
|
||||
functable.insert_string(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];
|
||||
#ifndef NOT_TWEAK_COMPILER
|
||||
functable.insert_string(s, s->strstart + 2 - MIN_MATCH, MIN_MATCH - 2);
|
||||
#else
|
||||
functable.insert_string(s, s->strstart + 2 - MIN_MATCH, 1);
|
||||
#if MIN_MATCH != 3
|
||||
#warning Call insert_string() MIN_MATCH-3 more times
|
||||
#endif
|
||||
#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->sym_next)
|
||||
FLUSH_BLOCK(s, 0);
|
||||
return block_done;
|
||||
}
|
||||
327
libs/zlibng/deflate_medium.c
Normal file
327
libs/zlibng/deflate_medium.c
Normal file
@ -0,0 +1,327 @@
|
||||
/* 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
|
||||
*/
|
||||
#ifndef NO_MEDIUM_STRATEGY
|
||||
#include "zbuild.h"
|
||||
#include "deflate.h"
|
||||
#include "deflate_p.h"
|
||||
#include "match_p.h"
|
||||
#include "functable.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 literals */
|
||||
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 literals */
|
||||
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) {
|
||||
functable.insert_string(s, match.strstart, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
match.strstart++;
|
||||
match.match_length--;
|
||||
if (match.match_length > 0) {
|
||||
if (match.strstart >= match.orgstart) {
|
||||
if (match.strstart + match.match_length - 1 >= match.orgstart) {
|
||||
functable.insert_string(s, match.strstart, match.match_length);
|
||||
} else {
|
||||
functable.insert_string(s, match.strstart, match.orgstart - match.strstart + 1);
|
||||
}
|
||||
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)) {
|
||||
functable.insert_string(s, match.strstart, 1);
|
||||
}
|
||||
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)) {
|
||||
if (likely(match.strstart + match.match_length - 1 >= match.orgstart)) {
|
||||
functable.insert_string(s, match.strstart, match.match_length);
|
||||
} else {
|
||||
functable.insert_string(s, match.strstart, match.orgstart - match.strstart + 1);
|
||||
}
|
||||
}
|
||||
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 >= (MIN_MATCH - 2))
|
||||
#ifndef NOT_TWEAK_COMPILER
|
||||
functable.insert_string(s, match.strstart + 2 - MIN_MATCH, MIN_MATCH - 2);
|
||||
#else
|
||||
functable.insert_string(s, match.strstart + 2 - MIN_MATCH, 1);
|
||||
#if MIN_MATCH != 3
|
||||
#warning Call insert_string() MIN_MATCH-3 more times
|
||||
#endif
|
||||
#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;
|
||||
|
||||
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 <= 1)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
ZLIB_INTERNAL 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) {
|
||||
functable.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 = functable.insert_string(s, s->strstart, 1);
|
||||
}
|
||||
|
||||
/* 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 && (current_match.strstart + current_match.match_length) < (s->window_size - MIN_LOOKAHEAD)) {
|
||||
s->strstart = current_match.strstart + current_match.match_length;
|
||||
hash_head = functable.insert_string(s, s->strstart, 1);
|
||||
|
||||
/* 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->sym_next)
|
||||
FLUSH_BLOCK(s, 0);
|
||||
|
||||
return block_done;
|
||||
}
|
||||
#endif
|
||||
77
libs/zlibng/deflate_p.h
Normal file
77
libs/zlibng/deflate_p.h
Normal file
@ -0,0 +1,77 @@
|
||||
/* 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
|
||||
|
||||
/* Forward declare common non-inlined functions declared in deflate.c */
|
||||
|
||||
#ifdef ZLIB_DEBUG
|
||||
void check_match(deflate_state *s, IPos start, IPos match, int length);
|
||||
#else
|
||||
#define check_match(s, start, match, length)
|
||||
#endif
|
||||
void flush_pending(PREFIX3(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).
|
||||
*/
|
||||
|
||||
static inline Pos insert_string_c(deflate_state *const s, const Pos str, unsigned int count) {
|
||||
Pos ret = 0;
|
||||
unsigned int idx;
|
||||
|
||||
for (idx = 0; idx < count; idx++) {
|
||||
UPDATE_HASH(s, s->ins_h, str+idx);
|
||||
|
||||
Pos head = s->head[s->ins_h];
|
||||
if (head != str+idx) {
|
||||
s->prev[(str+idx) & s->w_mask] = head;
|
||||
s->head[s->ins_h] = str+idx;
|
||||
if (idx == count - 1)
|
||||
ret = head;
|
||||
} else if (idx == count - 1) {
|
||||
ret = str + idx;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* 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] : \
|
||||
NULL), \
|
||||
(unsigned long)((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; \
|
||||
}
|
||||
|
||||
/* Maximum stored block length in deflate format (not including header). */
|
||||
#define MAX_STORED 65535
|
||||
|
||||
/* Minimum of a and b. */
|
||||
#define MIN(a, b) ((a) > (b) ? (b) : (a))
|
||||
|
||||
#endif
|
||||
164
libs/zlibng/deflate_slow.c
Normal file
164
libs/zlibng/deflate_slow.c
Normal file
@ -0,0 +1,164 @@
|
||||
/* 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 "zbuild.h"
|
||||
#include "deflate.h"
|
||||
#include "deflate_p.h"
|
||||
#include "match_p.h"
|
||||
#include "functable.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.
|
||||
*/
|
||||
ZLIB_INTERNAL 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) {
|
||||
functable.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 = functable.insert_string(s, s->strstart, 1);
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
unsigned int 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) {
|
||||
functable.insert_string(s, s->strstart, 1);
|
||||
}
|
||||
} while (--s->prev_length != 0);
|
||||
s->match_available = 0;
|
||||
s->match_length = MIN_MATCH-1;
|
||||
s->strstart++;
|
||||
#else
|
||||
{
|
||||
unsigned int mov_fwd = s->prev_length - 2;
|
||||
if (max_insert > s->strstart) {
|
||||
unsigned int insert_cnt = mov_fwd;
|
||||
if (unlikely(insert_cnt > max_insert - s->strstart))
|
||||
insert_cnt = max_insert - s->strstart;
|
||||
|
||||
functable.insert_string(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->sym_next)
|
||||
FLUSH_BLOCK(s, 0);
|
||||
return block_done;
|
||||
}
|
||||
209
libs/zlibng/doc/algorithm.txt
Normal file
209
libs/zlibng/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
libs/zlibng/doc/rfc1950.txt
Normal file
619
libs/zlibng/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
libs/zlibng/doc/rfc1951.txt
Normal file
955
libs/zlibng/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
libs/zlibng/doc/rfc1952.txt
Normal file
675
libs/zlibng/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
libs/zlibng/doc/txtvsbin.txt
Normal file
107
libs/zlibng/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
|
||||
133
libs/zlibng/functable.c
Normal file
133
libs/zlibng/functable.c
Normal file
@ -0,0 +1,133 @@
|
||||
/* functable.c -- Choose relevant optimized functions at runtime
|
||||
* Copyright (C) 2017 Hans Kristian Rosbach
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zbuild.h"
|
||||
#include "functable.h"
|
||||
#include "deflate.h"
|
||||
#include "deflate_p.h"
|
||||
|
||||
#include "gzendian.h"
|
||||
|
||||
/* insert_string */
|
||||
#ifdef X86_SSE4_2_CRC_HASH
|
||||
extern Pos insert_string_sse(deflate_state *const s, const Pos str, unsigned int count);
|
||||
#elif defined(ARM_ACLE_CRC_HASH)
|
||||
extern Pos insert_string_acle(deflate_state *const s, const Pos str, unsigned int count);
|
||||
#endif
|
||||
|
||||
/* fill_window */
|
||||
#ifdef X86_SSE2
|
||||
extern void fill_window_sse(deflate_state *s);
|
||||
#elif defined(__arm__) || defined(__aarch64__) || defined(_M_ARM)
|
||||
extern void fill_window_arm(deflate_state *s);
|
||||
#endif
|
||||
|
||||
/* adler32 */
|
||||
extern uint32_t adler32_c(uint32_t adler, const unsigned char *buf, size_t len);
|
||||
#if (defined(__ARM_NEON__) || defined(__ARM_NEON)) && defined(ARM_NEON_ADLER32)
|
||||
extern uint32_t adler32_neon(uint32_t adler, const unsigned char *buf, size_t len);
|
||||
#endif
|
||||
|
||||
ZLIB_INTERNAL uint32_t crc32_generic(uint32_t, const unsigned char *, uint64_t);
|
||||
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
extern volatile int crc_table_empty;
|
||||
extern void make_crc_table(void);
|
||||
#endif
|
||||
|
||||
#ifdef __ARM_FEATURE_CRC32
|
||||
extern uint32_t crc32_acle(uint32_t, const unsigned char *, uint64_t);
|
||||
#endif
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
extern uint32_t crc32_little(uint32_t, const unsigned char *, uint64_t);
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
extern uint32_t crc32_big(uint32_t, const unsigned char *, uint64_t);
|
||||
#endif
|
||||
|
||||
/* stub definitions */
|
||||
ZLIB_INTERNAL Pos insert_string_stub(deflate_state *const s, const Pos str, unsigned int count);
|
||||
ZLIB_INTERNAL void fill_window_stub(deflate_state *s);
|
||||
ZLIB_INTERNAL uint32_t adler32_stub(uint32_t adler, const unsigned char *buf, size_t len);
|
||||
ZLIB_INTERNAL uint32_t crc32_stub(uint32_t crc, const unsigned char *buf, uint64_t len);
|
||||
|
||||
/* functable init */
|
||||
ZLIB_INTERNAL __thread struct functable_s functable = {fill_window_stub,insert_string_stub,adler32_stub,crc32_stub};
|
||||
|
||||
|
||||
/* stub functions */
|
||||
ZLIB_INTERNAL Pos insert_string_stub(deflate_state *const s, const Pos str, unsigned int count) {
|
||||
// Initialize default
|
||||
functable.insert_string=&insert_string_c;
|
||||
|
||||
#ifdef X86_SSE4_2_CRC_HASH
|
||||
if (x86_cpu_has_sse42)
|
||||
functable.insert_string=&insert_string_sse;
|
||||
#elif defined(__ARM_FEATURE_CRC32) && defined(ARM_ACLE_CRC_HASH)
|
||||
if (arm_cpu_has_crc32)
|
||||
functable.insert_string=&insert_string_acle;
|
||||
#endif
|
||||
|
||||
return functable.insert_string(s, str, count);
|
||||
}
|
||||
|
||||
ZLIB_INTERNAL void fill_window_stub(deflate_state *s) {
|
||||
// Initialize default
|
||||
functable.fill_window=&fill_window_c;
|
||||
|
||||
#ifdef X86_SSE2
|
||||
# if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2)
|
||||
if (x86_cpu_has_sse2)
|
||||
# endif
|
||||
functable.fill_window=&fill_window_sse;
|
||||
#elif defined(__arm__) || defined(__aarch64__) || defined(_M_ARM)
|
||||
functable.fill_window=&fill_window_arm;
|
||||
#endif
|
||||
|
||||
functable.fill_window(s);
|
||||
}
|
||||
|
||||
ZLIB_INTERNAL uint32_t adler32_stub(uint32_t adler, const unsigned char *buf, size_t len) {
|
||||
// Initialize default
|
||||
functable.adler32=&adler32_c;
|
||||
|
||||
#if (defined(__ARM_NEON__) || defined(__ARM_NEON)) && defined(ARM_NEON_ADLER32)
|
||||
if (arm_cpu_has_neon)
|
||||
functable.adler32=&adler32_neon;
|
||||
#endif
|
||||
|
||||
return functable.adler32(adler, buf, len);
|
||||
}
|
||||
|
||||
ZLIB_INTERNAL uint32_t crc32_stub(uint32_t crc, const unsigned char *buf, uint64_t len) {
|
||||
|
||||
|
||||
Assert(sizeof(uint64_t) >= sizeof(size_t),
|
||||
"crc32_z takes size_t but internally we have a uint64_t len");
|
||||
/* return a function pointer for optimized arches here after a capability test */
|
||||
|
||||
#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
|
||||
functable.crc32=crc32_little;
|
||||
# if defined(__ARM_FEATURE_CRC32) && defined(ARM_ACLE_CRC_HASH)
|
||||
if (arm_cpu_has_crc32)
|
||||
functable.crc32=crc32_acle;
|
||||
# endif
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
functable.crc32=crc32_big;
|
||||
#else
|
||||
# error No endian defined
|
||||
#endif
|
||||
} else {
|
||||
functable.crc32=crc32_generic;
|
||||
}
|
||||
|
||||
return functable.crc32(crc, buf, len);
|
||||
}
|
||||
21
libs/zlibng/functable.h
Normal file
21
libs/zlibng/functable.h
Normal file
@ -0,0 +1,21 @@
|
||||
/* functable.h -- Struct containing function pointers to optimized functions
|
||||
* Copyright (C) 2017 Hans Kristian Rosbach
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifndef FUNCTABLE_H_
|
||||
#define FUNCTABLE_H_
|
||||
|
||||
#include "deflate.h"
|
||||
|
||||
struct functable_s {
|
||||
void (* fill_window) (deflate_state *s);
|
||||
Pos (* insert_string) (deflate_state *const s, const Pos str, unsigned int count);
|
||||
uint32_t (* adler32) (uint32_t adler, const unsigned char *buf, size_t len);
|
||||
uint32_t (* crc32) (uint32_t crc, const unsigned char *buf, uint64_t len);
|
||||
};
|
||||
|
||||
ZLIB_INTERNAL extern __thread struct functable_s functable;
|
||||
|
||||
|
||||
#endif
|
||||
24
libs/zlibng/gzclose.c
Normal file
24
libs/zlibng/gzclose.c
Normal file
@ -0,0 +1,24 @@
|
||||
/* gzclose.c -- zlib gzclose() function
|
||||
* Copyright (C) 2004, 2010 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zbuild.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 PREFIX(gzclose)(gzFile file) {
|
||||
#ifndef NO_GZCOMPRESS
|
||||
gz_state *state;
|
||||
|
||||
if (file == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (gz_state *)file;
|
||||
|
||||
return state->mode == GZ_READ ? PREFIX(gzclose_r)(file) : PREFIX(gzclose_w)(file);
|
||||
#else
|
||||
return PREFIX(gzclose_r)(file);
|
||||
#endif
|
||||
}
|
||||
60
libs/zlibng/gzendian.h
Normal file
60
libs/zlibng/gzendian.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* gzendian.h -- define BYTE_ORDER for endian tests
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifndef ENDIAN_H_
|
||||
#define ENDIAN_H_
|
||||
|
||||
/* First check whether the compiler knows the target __BYTE_ORDER__. */
|
||||
#if defined(__BYTE_ORDER__)
|
||||
# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
# if !defined(LITTLE_ENDIAN)
|
||||
# define LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__
|
||||
# endif
|
||||
# if !defined(BYTE_ORDER)
|
||||
# define BYTE_ORDER LITTLE_ENDIAN
|
||||
# endif
|
||||
# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
# if !defined(BIG_ENDIAN)
|
||||
# define BIG_ENDIAN __ORDER_BIG_ENDIAN__
|
||||
# endif
|
||||
# if !defined(BYTE_ORDER)
|
||||
# define BYTE_ORDER BIG_ENDIAN
|
||||
# endif
|
||||
# endif
|
||||
#elif defined(__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) || defined (_M_ARM)
|
||||
# define BYTE_ORDER LITTLE_ENDIAN
|
||||
# else
|
||||
# error Unknown endianness!
|
||||
# endif
|
||||
#elif defined(__linux__)
|
||||
# include <endian.h>
|
||||
#elif defined(__APPLE__) || defined(__arm__) || defined(__aarch64__)
|
||||
# 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
|
||||
|
||||
#endif
|
||||
166
libs/zlibng/gzguts.h
Normal file
166
libs/zlibng/gzguts.h
Normal file
@ -0,0 +1,166 @@
|
||||
#ifndef GZGUTS_H_
|
||||
#define GZGUTS_H_
|
||||
/* gzguts.h -- zlib internal header definitions for gz* operations
|
||||
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 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>
|
||||
|
||||
#if defined(ZLIB_COMPAT)
|
||||
# include "zlib.h"
|
||||
#else
|
||||
# include "zlib-ng.h"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
# include <stddef.h>
|
||||
#endif
|
||||
|
||||
#if !defined(_MSC_VER) || defined(__MINGW__)
|
||||
# include <unistd.h> /* for lseek(), read(), close(), write(), unlink() */
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) || defined(WIN32)
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || 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
|
||||
|
||||
/* 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 PREFIX(gzopen64)(const char *, const char *);
|
||||
ZEXTERN z_off64_t ZEXPORT PREFIX(gzseek64)(gzFile, z_off64_t, int);
|
||||
ZEXTERN z_off64_t ZEXPORT PREFIX(gztell64)(gzFile);
|
||||
ZEXTERN z_off64_t ZEXPORT PREFIX(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) */
|
||||
#if defined(S390_DFLTCC_DEFLATE) || defined(S390_DFLTCC_INFLATE)
|
||||
#define GZBUFSIZE 262144 /* DFLTCC works faster with larger buffers */
|
||||
#else
|
||||
#define GZBUFSIZE 8192
|
||||
#endif
|
||||
|
||||
/* 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 */
|
||||
PREFIX3(stream) strm; /* stream structure in-place (not a pointer) */
|
||||
} gz_state;
|
||||
typedef gz_state *gz_statep;
|
||||
|
||||
/* shared functions */
|
||||
void ZLIB_INTERNAL gz_error(gz_state *, 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
libs/zlibng/gzlib.c
Normal file
518
libs/zlibng/gzlib.c
Normal file
@ -0,0 +1,518 @@
|
||||
/* gzlib.c -- zlib functions common to reading and writing gzip files
|
||||
* Copyright (C) 2004-2017 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zbuild.h"
|
||||
#include "gzguts.h"
|
||||
|
||||
#if defined(WIN32) && !defined(__BORLANDC__)
|
||||
# define LSEEK _lseeki64
|
||||
#else
|
||||
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
|
||||
# define LSEEK lseek64
|
||||
#else
|
||||
# define LSEEK lseek
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Local functions */
|
||||
static void gz_reset(gz_state *);
|
||||
static gzFile gz_open(const void *, int, const char *);
|
||||
|
||||
/* Reset gzip file state */
|
||||
static void gz_reset(gz_state *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. */
|
||||
static gzFile gz_open(const void *path, int fd, const char *mode) {
|
||||
gz_state *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_state *)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
|
||||
(void)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 PREFIX(gzopen)(const char *path, const char *mode) {
|
||||
return gz_open(path, -1, mode);
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
gzFile ZEXPORT PREFIX(gzopen64)(const char *path, const char *mode) {
|
||||
return gz_open(path, -1, mode);
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
gzFile ZEXPORT PREFIX(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;
|
||||
(void)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 PREFIX(gzopen_w)(const wchar_t *path, const char *mode) {
|
||||
return gz_open(path, -2, mode);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT PREFIX(gzbuffer)(gzFile file, unsigned size) {
|
||||
gz_state *state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_state *)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 PREFIX(gzrewind)(gzFile file) {
|
||||
gz_state *state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_state *)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 PREFIX(gzseek64)(gzFile file, z_off64_t offset, int whence) {
|
||||
unsigned n;
|
||||
z_off64_t ret;
|
||||
gz_state *state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_state *)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 - (z_off64_t)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 (PREFIX(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 PREFIX(gzseek)(gzFile file, z_off_t offset, int whence) {
|
||||
z_off64_t ret;
|
||||
|
||||
ret = PREFIX(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 PREFIX(gztell64)(gzFile file) {
|
||||
gz_state *state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_state *)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 PREFIX(gztell)(gzFile file) {
|
||||
z_off64_t ret;
|
||||
|
||||
ret = PREFIX(gztell64)(file);
|
||||
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off64_t ZEXPORT PREFIX(gzoffset64)(gzFile file) {
|
||||
z_off64_t offset;
|
||||
gz_state *state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_state *)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 PREFIX(gzoffset)(gzFile file) {
|
||||
z_off64_t ret;
|
||||
|
||||
ret = PREFIX(gzoffset64)(file);
|
||||
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT PREFIX(gzeof)(gzFile file) {
|
||||
gz_state *state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return 0;
|
||||
state = (gz_state *)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 PREFIX(gzerror)(gzFile file, int *errnum) {
|
||||
gz_state *state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return NULL;
|
||||
state = (gz_state *)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 PREFIX(gzclearerr)(gzFile file) {
|
||||
gz_state *state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return;
|
||||
state = (gz_state *)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_state *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;
|
||||
}
|
||||
(void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, "%s%s%s", state->path, ": ", msg);
|
||||
}
|
||||
|
||||
#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
|
||||
599
libs/zlibng/gzread.c
Normal file
599
libs/zlibng/gzread.c
Normal file
@ -0,0 +1,599 @@
|
||||
/* gzread.c -- zlib functions for reading gzip files
|
||||
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zbuild.h"
|
||||
#include "gzguts.h"
|
||||
|
||||
/* Local functions */
|
||||
static int gz_load(gz_state *, unsigned char *, unsigned, unsigned *);
|
||||
static int gz_avail(gz_state *);
|
||||
static int gz_look(gz_state *);
|
||||
static int gz_decomp(gz_state *);
|
||||
static int gz_fetch(gz_state *);
|
||||
static int gz_skip(gz_state *, z_off64_t);
|
||||
static size_t gz_read(gz_state *, void *, size_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. */
|
||||
static int gz_load(gz_state *state, unsigned char *buf, unsigned len, unsigned *have) {
|
||||
ssize_t ret;
|
||||
|
||||
*have = 0;
|
||||
do {
|
||||
ret = read(state->fd, buf + *have, len - *have);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
*have += (unsigned)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. */
|
||||
static int gz_avail(gz_state *state) {
|
||||
unsigned got;
|
||||
PREFIX3(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. */
|
||||
static int gz_look(gz_state *state) {
|
||||
PREFIX3(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) {
|
||||
free(state->out);
|
||||
free(state->in);
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
state->size = state->want;
|
||||
|
||||
/* allocate inflate memory */
|
||||
state->strm.zalloc = NULL;
|
||||
state->strm.zfree = NULL;
|
||||
state->strm.opaque = NULL;
|
||||
state->strm.avail_in = 0;
|
||||
state->strm.next_in = NULL;
|
||||
if (PREFIX(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) {
|
||||
PREFIX(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. */
|
||||
static int gz_decomp(gz_state *state) {
|
||||
int ret = Z_OK;
|
||||
unsigned had;
|
||||
PREFIX3(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 = PREFIX(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. */
|
||||
static int gz_fetch(gz_state *state) {
|
||||
PREFIX3(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. */
|
||||
static int gz_skip(gz_state *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;
|
||||
}
|
||||
|
||||
/* Read len bytes into buf from file, or less than len up to the end of the
|
||||
input. Return the number of bytes read. If zero is returned, either the
|
||||
end of file was reached, or there was an error. state->err must be
|
||||
consulted in that case to determine which. */
|
||||
static size_t gz_read(gz_state *state, void *buf, size_t len) {
|
||||
size_t got;
|
||||
unsigned n;
|
||||
|
||||
/* 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 0;
|
||||
}
|
||||
|
||||
/* get len bytes to buf, or less than len if at the end */
|
||||
got = 0;
|
||||
do {
|
||||
/* set n to the maximum amount of len that fits in an unsigned int */
|
||||
n = (unsigned)-1;
|
||||
if (n > len)
|
||||
n = (unsigned)len;
|
||||
|
||||
/* first just try copying data from the output buffer */
|
||||
if (state->x.have) {
|
||||
if (state->x.have < n)
|
||||
n = state->x.have;
|
||||
memcpy(buf, state->x.next, n);
|
||||
state->x.next += n;
|
||||
state->x.have -= n;
|
||||
}
|
||||
|
||||
/* output buffer empty -- return if we're at the end of the input */
|
||||
else if (state->eof && state->strm.avail_in == 0) {
|
||||
state->past = 1; /* tried to read past end */
|
||||
break;
|
||||
}
|
||||
|
||||
/* need output data -- for small len or new stream load up our output
|
||||
buffer */
|
||||
else if (state->how == LOOK || n < (state->size << 1)) {
|
||||
/* get more output, looking for header if required */
|
||||
if (gz_fetch(state) == -1)
|
||||
return 0;
|
||||
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 */
|
||||
}
|
||||
|
||||
/* large len -- read directly into user buffer */
|
||||
else if (state->how == COPY) { /* read directly */
|
||||
if (gz_load(state, (unsigned char *)buf, n, &n) == -1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* large len -- decompress directly into user buffer */
|
||||
else { /* state->how == GZIP */
|
||||
state->strm.avail_out = n;
|
||||
state->strm.next_out = (unsigned char *)buf;
|
||||
if (gz_decomp(state) == -1)
|
||||
return 0;
|
||||
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 */
|
||||
return got;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT PREFIX(gzread)(gzFile file, void *buf, unsigned len) {
|
||||
gz_state *state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_state *)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;
|
||||
|
||||
/* since an int is returned, make sure len fits in one, otherwise return
|
||||
with an error (this avoids a flaw in the interface) */
|
||||
if ((int)len < 0) {
|
||||
gz_error(state, Z_STREAM_ERROR, "request does not fit in an int");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* read len or fewer bytes to buf */
|
||||
len = (unsigned)gz_read(state, buf, len);
|
||||
|
||||
/* check for an error */
|
||||
if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR)
|
||||
return -1;
|
||||
|
||||
/* return the number of bytes read (this is assured to fit in an int) */
|
||||
return (int)len;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
size_t ZEXPORT PREFIX(gzfread)(void *buf, size_t size, size_t nitems, gzFile file) {
|
||||
size_t len;
|
||||
gz_state *state;
|
||||
|
||||
/* Exit early if size is zero, also prevents potential division by zero */
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return 0;
|
||||
state = (gz_state *)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 0;
|
||||
|
||||
/* compute bytes to read -- error on overflow */
|
||||
len = nitems * size;
|
||||
if (size && len / size != nitems) {
|
||||
gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* read len or fewer bytes to buf, return the number of full items read */
|
||||
return len ? gz_read(state, buf, len) / size : 0;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
#undef gzgetc
|
||||
#undef zng_gzgetc
|
||||
int ZEXPORT PREFIX(gzgetc)(gzFile file) {
|
||||
unsigned char buf[1];
|
||||
gz_state *state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_state *)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 gz_read() */
|
||||
return gz_read(state, buf, 1) < 1 ? -1 : buf[0];
|
||||
}
|
||||
|
||||
int ZEXPORT PREFIX(gzgetc_)(gzFile file) {
|
||||
return PREFIX(gzgetc)(file);
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT PREFIX(gzungetc)(int c, gzFile file) {
|
||||
gz_state *state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_state *)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] = (unsigned char)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] = (unsigned char)c;
|
||||
state->x.pos--;
|
||||
state->past = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
char * ZEXPORT PREFIX(gzgets)(gzFile file, char *buf, int len) {
|
||||
unsigned left, n;
|
||||
char *str;
|
||||
unsigned char *eol;
|
||||
gz_state *state;
|
||||
|
||||
/* check parameters and get internal structure */
|
||||
if (file == NULL || buf == NULL || len < 1)
|
||||
return NULL;
|
||||
state = (gz_state *)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 PREFIX(gzdirect)(gzFile file) {
|
||||
gz_state *state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return 0;
|
||||
|
||||
state = (gz_state *)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 PREFIX(gzclose_r)(gzFile file) {
|
||||
int ret, err;
|
||||
gz_state *state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
state = (gz_state *)file;
|
||||
|
||||
/* check that we're reading */
|
||||
if (state->mode != GZ_READ)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
/* free memory and close file */
|
||||
if (state->size) {
|
||||
PREFIX(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;
|
||||
}
|
||||
516
libs/zlibng/gzwrite.c
Normal file
516
libs/zlibng/gzwrite.c
Normal file
@ -0,0 +1,516 @@
|
||||
/* gzwrite.c -- zlib functions for writing gzip files
|
||||
* Copyright (C) 2004-2017 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zbuild.h"
|
||||
#include <stdarg.h>
|
||||
#include "gzguts.h"
|
||||
|
||||
/* Local functions */
|
||||
static int gz_init(gz_state *);
|
||||
static int gz_comp(gz_state *, int);
|
||||
static int gz_zero(gz_state *, z_off64_t);
|
||||
static size_t gz_write(gz_state *, void const *, size_t);
|
||||
|
||||
/* Initialize state for writing a gzip file. Mark initialization by setting
|
||||
state->size to non-zero. Return -1 on a memory allocation failure, or 0 on
|
||||
success. */
|
||||
static int gz_init(gz_state *state) {
|
||||
int ret;
|
||||
PREFIX3(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 = NULL;
|
||||
strm->zfree = NULL;
|
||||
strm->opaque = NULL;
|
||||
ret = PREFIX(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 or if gz_init()
|
||||
fails to allocate memory, 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. */
|
||||
static int gz_comp(gz_state *state, int flush) {
|
||||
int ret;
|
||||
ssize_t got;
|
||||
unsigned have;
|
||||
PREFIX3(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) {
|
||||
got = write(state->fd, strm->next_in, strm->avail_in);
|
||||
if (got < 0 || (unsigned)got != strm->avail_in) {
|
||||
gz_error(state, Z_ERRNO, zstrerror());
|
||||
return -1;
|
||||
}
|
||||
strm->avail_in = 0;
|
||||
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))) {
|
||||
have = (unsigned)(strm->next_out - state->x.next);
|
||||
if (have && ((got = write(state->fd, state->x.next, (unsigned long)have)) < 0 || (unsigned)got != have)) {
|
||||
gz_error(state, Z_ERRNO, zstrerror());
|
||||
return -1;
|
||||
}
|
||||
if (strm->avail_out == 0) {
|
||||
strm->avail_out = state->size;
|
||||
strm->next_out = state->out;
|
||||
state->x.next = state->out;
|
||||
}
|
||||
state->x.next = strm->next_out;
|
||||
}
|
||||
|
||||
/* compress */
|
||||
have = strm->avail_out;
|
||||
ret = PREFIX(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)
|
||||
PREFIX(deflateReset)(strm);
|
||||
|
||||
/* all done, no errors */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compress len zeros to output. Return -1 on a write error or memory
|
||||
allocation failure by gz_comp(), or 0 on success. */
|
||||
static int gz_zero(gz_state *state, z_off64_t len) {
|
||||
int first;
|
||||
unsigned n;
|
||||
PREFIX3(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;
|
||||
}
|
||||
|
||||
/* Write len bytes from buf to file. Return the number of bytes written. If
|
||||
the returned value is less than len, then there was an error. */
|
||||
static size_t gz_write(gz_state *state, void const *buf, size_t len) {
|
||||
size_t put = len;
|
||||
|
||||
/* 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 (state->strm.avail_in == 0)
|
||||
state->strm.next_in = state->in;
|
||||
have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
|
||||
state->in);
|
||||
copy = state->size - have;
|
||||
if (copy > len)
|
||||
copy = (unsigned)len;
|
||||
memcpy(state->in + have, buf, copy);
|
||||
state->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 (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return 0;
|
||||
|
||||
/* directly compress user buffer to file */
|
||||
state->strm.next_in = (const unsigned char *)buf;
|
||||
do {
|
||||
unsigned n = (unsigned)-1;
|
||||
if (n > len)
|
||||
n = (unsigned)len;
|
||||
state->strm.avail_in = n;
|
||||
state->x.pos += n;
|
||||
if (gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return 0;
|
||||
len -= n;
|
||||
} while (len);
|
||||
}
|
||||
|
||||
/* input was all buffered or compressed */
|
||||
return put;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT PREFIX(gzwrite)(gzFile file, void const *buf, unsigned len) {
|
||||
gz_state *state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return 0;
|
||||
state = (gz_state *)file;
|
||||
|
||||
/* 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 a flaw in the interface) */
|
||||
if ((int)len < 0) {
|
||||
gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* write len bytes from buf (the return value will fit in an int) */
|
||||
return (int)gz_write(state, buf, len);
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
size_t ZEXPORT PREFIX(gzfwrite)(void const *buf, size_t size, size_t nitems, gzFile file) {
|
||||
size_t len;
|
||||
gz_state *state;
|
||||
|
||||
/* Exit early if size is zero, also prevents potential division by zero */
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return 0;
|
||||
state = (gz_state *)file;
|
||||
|
||||
/* check that we're writing and that there's no error */
|
||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
||||
return 0;
|
||||
|
||||
/* compute bytes to read -- error on overflow */
|
||||
len = nitems * size;
|
||||
if (size && len / size != nitems) {
|
||||
gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* write len bytes to buf, return the number of full items written */
|
||||
return len ? gz_write(state, buf, len) / size : 0;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT PREFIX(gzputc)(gzFile file, int c) {
|
||||
unsigned have;
|
||||
unsigned char buf[1];
|
||||
gz_state *state;
|
||||
PREFIX3(stream) *strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_state *)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] = (unsigned char)c;
|
||||
strm->avail_in++;
|
||||
state->x.pos++;
|
||||
return c & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
/* no room in buffer or not initialized, use gz_write() */
|
||||
buf[0] = (unsigned char)c;
|
||||
if (gz_write(state, buf, 1) != 1)
|
||||
return -1;
|
||||
return c & 0xff;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT PREFIX(gzputs)(gzFile file, const char *s) {
|
||||
size_t len, put;
|
||||
gz_state *state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_state *)file;
|
||||
|
||||
/* check that we're writing and that there's no error */
|
||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
||||
return -1;
|
||||
|
||||
/* write string */
|
||||
len = strlen(s);
|
||||
if ((int)len < 0 || (unsigned)len != len) {
|
||||
gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
|
||||
return -1;
|
||||
}
|
||||
put = gz_write(state, s, len);
|
||||
return put < len ? -1 : (int)len;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORTVA PREFIX(gzvprintf)(gzFile file, const char *format, va_list va) {
|
||||
int len;
|
||||
unsigned left;
|
||||
char *next;
|
||||
gz_state *state;
|
||||
PREFIX3(stream) *strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (gz_state *)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;
|
||||
|
||||
/* make sure we have some buffer space */
|
||||
if (state->size == 0 && gz_init(state) == -1)
|
||||
return state->err;
|
||||
|
||||
/* check for seek request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_zero(state, state->skip) == -1)
|
||||
return state->err;
|
||||
}
|
||||
|
||||
/* 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 *)(state->in + (strm->next_in - state->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 || (unsigned)len >= state->size || next[state->size - 1] != 0)
|
||||
return 0;
|
||||
|
||||
/* update buffer and position, compress first half if past that */
|
||||
strm->avail_in += (unsigned)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 state->err;
|
||||
memmove(state->in, state->in + state->size, left);
|
||||
strm->next_in = state->in;
|
||||
strm->avail_in = left;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int ZEXPORTVA PREFIX(gzprintf)(gzFile file, const char *format, ...) {
|
||||
va_list va;
|
||||
int ret;
|
||||
|
||||
va_start(va, format);
|
||||
ret = PREFIX(gzvprintf)(file, format, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT PREFIX(gzflush)(gzFile file, int flush) {
|
||||
gz_state *state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (gz_state *)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 state->err;
|
||||
}
|
||||
|
||||
/* compress remaining data with requested flush */
|
||||
(void)gz_comp(state, flush);
|
||||
return state->err;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT PREFIX(gzsetparams)(gzFile file, int level, int strategy) {
|
||||
gz_state *state;
|
||||
PREFIX3(stream) *strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (gz_state *)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 state->err;
|
||||
}
|
||||
|
||||
/* 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_BLOCK) == -1)
|
||||
return state->err;
|
||||
PREFIX(deflateParams)(strm, level, strategy);
|
||||
}
|
||||
state->level = level;
|
||||
state->strategy = strategy;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT PREFIX(gzclose_w)(gzFile file) {
|
||||
int ret = Z_OK;
|
||||
gz_state *state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (gz_state *)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)PREFIX(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;
|
||||
}
|
||||
614
libs/zlibng/infback.c
Normal file
614
libs/zlibng/infback.c
Normal file
@ -0,0 +1,614 @@
|
||||
/* infback.c -- inflate using a call-back interface
|
||||
* Copyright (C) 1995-2016 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 "zbuild.h"
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
#include "inflate.h"
|
||||
#include "inffast.h"
|
||||
|
||||
/* function prototypes */
|
||||
static void fixedtables(struct inflate_state *state);
|
||||
|
||||
/*
|
||||
strm provides memory allocation functions in zalloc and zfree, or
|
||||
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 PREFIX(inflateBackInit_)(PREFIX3(stream) *strm, int windowBits, unsigned char *window,
|
||||
const char *version, int stream_size) {
|
||||
struct inflate_state *state;
|
||||
|
||||
if (version == NULL || version[0] != PREFIX2(VERSION)[0] || stream_size != (int)(sizeof(PREFIX3(stream))))
|
||||
return Z_VERSION_ERROR;
|
||||
if (strm == NULL || window == NULL || windowBits < 8 || windowBits > 15)
|
||||
return Z_STREAM_ERROR;
|
||||
strm->msg = NULL; /* in case we return an error */
|
||||
if (strm->zalloc == NULL) {
|
||||
strm->zalloc = zcalloc;
|
||||
strm->opaque = NULL;
|
||||
}
|
||||
if (strm->zfree == NULL)
|
||||
strm->zfree = zcfree;
|
||||
state = (struct inflate_state *)ZALLOC(strm, 1, sizeof(struct inflate_state));
|
||||
if (state == NULL)
|
||||
return Z_MEM_ERROR;
|
||||
Tracev((stderr, "inflate: allocated\n"));
|
||||
strm->state = (struct internal_state *)state;
|
||||
state->dmax = 32768U;
|
||||
state->wbits = (unsigned int)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.
|
||||
*/
|
||||
static 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 = 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 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 NULL or the state was not initialized.
|
||||
*/
|
||||
int ZEXPORT PREFIX(inflateBack)(PREFIX3(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 == NULL || strm->state == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state *)strm->state;
|
||||
|
||||
/* Reset the state */
|
||||
strm->msg = NULL;
|
||||
state->mode = TYPE;
|
||||
state->last = 0;
|
||||
state->whave = 0;
|
||||
next = strm->next_in;
|
||||
have = next != 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 >= INFLATE_FAST_MIN_HAVE &&
|
||||
left >= INFLATE_FAST_MIN_LEFT) {
|
||||
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 PREFIX(inflateBackEnd)(PREFIX3(stream) *strm) {
|
||||
if (strm == NULL || strm->state == NULL || strm->zfree == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
ZFREE(strm, strm->state);
|
||||
strm->state = NULL;
|
||||
Tracev((stderr, "inflate: end\n"));
|
||||
return Z_OK;
|
||||
}
|
||||
389
libs/zlibng/inffast.c
Normal file
389
libs/zlibng/inffast.c
Normal file
@ -0,0 +1,389 @@
|
||||
/* inffast.c -- fast decoding
|
||||
* Copyright (C) 1995-2017 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zbuild.h"
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
#include "inflate.h"
|
||||
#include "inffast.h"
|
||||
#include "memcopy.h"
|
||||
|
||||
/* Return the low n bits of the bit accumulator (n < 16) */
|
||||
#define BITS(n) \
|
||||
(hold & ((UINT64_C(1) << (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 >= INFLATE_FAST_MIN_HAVE
|
||||
strm->avail_out >= INFLATE_FAST_MIN_LEFT
|
||||
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.
|
||||
|
||||
- On some architectures, it can be significantly faster (e.g. up to 1.2x
|
||||
faster on x86_64) to load from strm->next_in 64 bits, or 8 bytes, at a
|
||||
time, so INFLATE_FAST_MIN_HAVE == 8.
|
||||
|
||||
- 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(PREFIX3(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 INFFAST_CHUNKSIZE
|
||||
unsigned char *safe; /* can use chunkcopy provided out < safe */
|
||||
#endif
|
||||
#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 */
|
||||
|
||||
/* hold is a local copy of strm->hold. By default, hold satisfies the same
|
||||
invariants that strm->hold does, namely that (hold >> bits) == 0. This
|
||||
invariant is kept by loading bits into hold one byte at a time, like:
|
||||
|
||||
hold |= next_byte_of_input << bits; in++; bits += 8;
|
||||
|
||||
If we need to ensure that bits >= 15 then this code snippet is simply
|
||||
repeated. Over one iteration of the outermost do/while loop, this
|
||||
happens up to six times (48 bits of input), as described in the NOTES
|
||||
above.
|
||||
|
||||
However, on some little endian architectures, it can be significantly
|
||||
faster to load 64 bits once instead of 8 bits six times:
|
||||
|
||||
if (bits <= 16) {
|
||||
hold |= next_8_bytes_of_input << bits; in += 6; bits += 48;
|
||||
}
|
||||
|
||||
Unlike the simpler one byte load, shifting the next_8_bytes_of_input
|
||||
by bits will overflow and lose those high bits, up to 2 bytes' worth.
|
||||
The conservative estimate is therefore that we have read only 6 bytes
|
||||
(48 bits). Again, as per the NOTES above, 48 bits is sufficient for the
|
||||
rest of the iteration, and we will not need to load another 8 bytes.
|
||||
|
||||
Inside this function, we no longer satisfy (hold >> bits) == 0, but
|
||||
this is not problematic, even if that overflow does not land on an 8 bit
|
||||
byte boundary. Those excess bits will eventually shift down lower as the
|
||||
Huffman decoder consumes input, and when new input bits need to be loaded
|
||||
into the bits variable, the same input bits will be or'ed over those
|
||||
existing bits. A bitwise or is idempotent: (a | b | b) equals (a | b).
|
||||
Note that we therefore write that load operation as "hold |= etc" and not
|
||||
"hold += etc".
|
||||
|
||||
Outside that loop, at the end of the function, hold is bitwise and'ed
|
||||
with (1<<bits)-1 to drop those excess bits so that, on function exit, we
|
||||
keep the invariant that (state->hold >> state->bits) == 0.
|
||||
*/
|
||||
uint64_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 */
|
||||
const 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;
|
||||
last = in + (strm->avail_in - (INFLATE_FAST_MIN_HAVE - 1));
|
||||
out = strm->next_out;
|
||||
beg = out - (start - strm->avail_out);
|
||||
end = out + (strm->avail_out - (INFLATE_FAST_MIN_LEFT - 1));
|
||||
|
||||
#ifdef INFFAST_CHUNKSIZE
|
||||
safe = out + strm->avail_out;
|
||||
#endif
|
||||
#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 |= load_64_bits(in, bits);
|
||||
in += 6;
|
||||
bits += 48;
|
||||
}
|
||||
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));
|
||||
*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 |= load_64_bits(in, bits);
|
||||
in += 6;
|
||||
bits += 48;
|
||||
}
|
||||
len += BITS(op);
|
||||
DROPBITS(op);
|
||||
}
|
||||
Tracevv((stderr, "inflate: length %u\n", len));
|
||||
if (bits < 15) {
|
||||
hold |= load_64_bits(in, bits);
|
||||
in += 6;
|
||||
bits += 48;
|
||||
}
|
||||
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 |= load_64_bits(in, bits);
|
||||
in += 6;
|
||||
bits += 48;
|
||||
}
|
||||
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 {
|
||||
*out++ = 0;
|
||||
} while (--len);
|
||||
continue;
|
||||
}
|
||||
len -= op - whave;
|
||||
do {
|
||||
*out++ = 0;
|
||||
} while (--op > whave);
|
||||
if (op == 0) {
|
||||
from = out - dist;
|
||||
do {
|
||||
*out++ = *from++;
|
||||
} while (--len);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifdef INFFAST_CHUNKSIZE
|
||||
from = window;
|
||||
if (wnext == 0) { /* very common case */
|
||||
from += wsize - op;
|
||||
} else if (wnext >= op) { /* contiguous in window */
|
||||
from += wnext - op;
|
||||
} else { /* wrap around window */
|
||||
op -= wnext;
|
||||
from += wsize - op;
|
||||
if (op < len) { /* some from end of window */
|
||||
len -= op;
|
||||
out = chunkcopysafe(out, from, op, safe);
|
||||
from = window; /* more from start of window */
|
||||
op = wnext;
|
||||
/* This (rare) case can create a situation where
|
||||
the first chunkcopy below must be checked.
|
||||
*/
|
||||
}
|
||||
}
|
||||
if (op < len) { /* still need some from output */
|
||||
len -= op;
|
||||
out = chunkcopysafe(out, from, op, safe);
|
||||
out = chunkunroll(out, &dist, &len);
|
||||
out = chunkcopysafe(out, out - dist, len, safe);
|
||||
} else {
|
||||
out = chunkcopysafe(out, from, len, safe);
|
||||
}
|
||||
#else
|
||||
from = window;
|
||||
if (wnext == 0) { /* very common case */
|
||||
from += wsize - op;
|
||||
if (op < len) { /* some from window */
|
||||
len -= op;
|
||||
do {
|
||||
*out++ = *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 {
|
||||
*out++ = *from++;
|
||||
} while (--op);
|
||||
from = window;
|
||||
if (wnext < len) { /* some from start of window */
|
||||
op = wnext;
|
||||
len -= op;
|
||||
do {
|
||||
*out++ = *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 {
|
||||
*out++ = *from++;
|
||||
} while (--op);
|
||||
from = out - dist; /* rest from output */
|
||||
}
|
||||
}
|
||||
|
||||
out = chunk_copy(out, from, (int) (out - from), len);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef INFFAST_CHUNKSIZE
|
||||
/* Whole reference is in range of current output. No
|
||||
range checks are necessary because we start with room
|
||||
for at least 258 bytes of output, so unroll and roundoff
|
||||
operations can write beyond `out+len` so long as they
|
||||
stay within 258 bytes of `out`.
|
||||
*/
|
||||
if (dist >= len || dist >= INFFAST_CHUNKSIZE)
|
||||
out = chunkcopy(out, out - dist, len);
|
||||
else
|
||||
out = chunkmemset(out, dist, len);
|
||||
#else
|
||||
if (len < sizeof(uint64_t))
|
||||
out = set_bytes(out, out - dist, dist, len);
|
||||
else if (dist == 1)
|
||||
out = byte_memset(out, len);
|
||||
else
|
||||
out = chunk_memset(out, out - dist, dist, len);
|
||||
#endif
|
||||
}
|
||||
} 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 &= (UINT64_C(1) << bits) - 1;
|
||||
|
||||
/* update state and return */
|
||||
strm->next_in = in;
|
||||
strm->next_out = out;
|
||||
strm->avail_in =
|
||||
(unsigned)(in < last ? (INFLATE_FAST_MIN_HAVE - 1) + (last - in)
|
||||
: (INFLATE_FAST_MIN_HAVE - 1) - (in - last));
|
||||
strm->avail_out =
|
||||
(unsigned)(out < end ? (INFLATE_FAST_MIN_LEFT - 1) + (end - out)
|
||||
: (INFLATE_FAST_MIN_LEFT - 1) - (out - end));
|
||||
|
||||
Assert(bits <= 32, "Remaining bits greater than 32");
|
||||
state->hold = (uint32_t)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
|
||||
*/
|
||||
18
libs/zlibng/inffast.h
Normal file
18
libs/zlibng/inffast.h
Normal file
@ -0,0 +1,18 @@
|
||||
#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(PREFIX3(stream) *strm, unsigned long start);
|
||||
|
||||
#define INFLATE_FAST_MIN_HAVE 8
|
||||
#define INFLATE_FAST_MIN_LEFT 258
|
||||
|
||||
#endif /* INFFAST_H_ */
|
||||
94
libs/zlibng/inffixed.h
Normal file
94
libs/zlibng/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}
|
||||
};
|
||||
1577
libs/zlibng/inflate.c
Normal file
1577
libs/zlibng/inflate.c
Normal file
File diff suppressed because it is too large
Load Diff
132
libs/zlibng/inflate.h
Normal file
132
libs/zlibng/inflate.h
Normal file
@ -0,0 +1,132 @@
|
||||
/* inflate.h -- internal inflate state definition
|
||||
* Copyright (C) 1995-2016 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 = 16180, /* 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 7K bytes, not
|
||||
including the allocated sliding window, which is up to 32K bytes. */
|
||||
struct inflate_state {
|
||||
PREFIX3(stream) *strm; /* pointer back to this zlib stream */
|
||||
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,
|
||||
bit 2 true to validate check value */
|
||||
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 */
|
||||
PREFIX(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 */
|
||||
};
|
||||
|
||||
int ZLIB_INTERNAL inflate_ensure_window(struct inflate_state *state);
|
||||
|
||||
#endif /* INFLATE_H_ */
|
||||
297
libs/zlibng/inftrees.c
Normal file
297
libs/zlibng/inftrees.c
Normal file
@ -0,0 +1,297 @@
|
||||
/* inftrees.c -- generate Huffman trees for efficient decoding
|
||||
* Copyright (C) 1995-2016 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zbuild.h"
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
|
||||
#define MAXBITS 15
|
||||
|
||||
const char inflate_copyright[] = " inflate 1.2.11.f Copyright 1995-2016 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 */
|
||||
unsigned match; /* use base and extra for symbol >= match */
|
||||
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, 77, 202};
|
||||
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 */
|
||||
match = 20;
|
||||
break;
|
||||
case LENS:
|
||||
base = lbase;
|
||||
extra = lext;
|
||||
match = 257;
|
||||
break;
|
||||
default: /* DISTS */
|
||||
base = dbase;
|
||||
extra = dext;
|
||||
match = 0;
|
||||
}
|
||||
|
||||
/* 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 (work[sym] + 1U < match) {
|
||||
here.op = (unsigned char)0;
|
||||
here.val = work[sym];
|
||||
} else if (work[sym] >= match) {
|
||||
here.op = (unsigned char)(extra[work[sym] - match]);
|
||||
here.val = base[work[sym] - match];
|
||||
} 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
libs/zlibng/inftrees.h
Normal file
66
libs/zlibng/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_ */
|
||||
512
libs/zlibng/match_p.h
Normal file
512
libs/zlibng/match_p.h
Normal file
@ -0,0 +1,512 @@
|
||||
/*
|
||||
* 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 "zbuild.h"
|
||||
#include "deflate.h"
|
||||
|
||||
#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
|
||||
|
||||
/* ARM 32-bit clang/gcc builds perform better, on average, with std2. Both gcc and clang and define __GNUC__. */
|
||||
# if defined(__GNUC__) && defined(__arm__) && !defined(__aarch64__)
|
||||
# define std2_longest_match
|
||||
/* 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. */
|
||||
# elif(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__)
|
||||
# if defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64)
|
||||
# include "arch/x86/ctzl.h"
|
||||
# elif defined(_M_ARM)
|
||||
# include "arch/arm/ctzl.h"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef std1_longest_match
|
||||
|
||||
/*
|
||||
* Standard longest_match
|
||||
*
|
||||
*/
|
||||
static inline 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 : (unsigned int)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 {
|
||||
if (cur_match >= s->strstart) {
|
||||
break;
|
||||
}
|
||||
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 < TRIGGER_LEVEL)
|
||||
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
|
||||
*
|
||||
*/
|
||||
static inline 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 look 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;
|
||||
memcpy(&scan_start, scan, sizeof(scan_start));
|
||||
memcpy(&scan_end, scan + best_len - 1, sizeof(scan_end));
|
||||
|
||||
Assert((unsigned long)s->strstart <= s->window_size - MIN_LOOKAHEAD, "need lookahead");
|
||||
do {
|
||||
unsigned char *match;
|
||||
if (cur_match >= s->strstart) {
|
||||
break;
|
||||
}
|
||||
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.
|
||||
*/
|
||||
uint16_t val;
|
||||
memcpy(&val, match + best_len - 1, sizeof(val));
|
||||
if (likely(val != scan_end))
|
||||
continue;
|
||||
|
||||
memcpy(&val, match, sizeof(val));
|
||||
if (val != 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 {
|
||||
uint16_t mval, sval;
|
||||
|
||||
memcpy(&mval, match, sizeof(mval));
|
||||
memcpy(&sval, scan, sizeof(sval));
|
||||
if (mval != sval)
|
||||
break;
|
||||
match += sizeof(mval);
|
||||
scan += sizeof(sval);
|
||||
|
||||
memcpy(&mval, match, sizeof(mval));
|
||||
memcpy(&sval, scan, sizeof(sval));
|
||||
if (mval != sval)
|
||||
break;
|
||||
match += sizeof(mval);
|
||||
scan += sizeof(sval);
|
||||
|
||||
memcpy(&mval, match, sizeof(mval));
|
||||
memcpy(&sval, scan, sizeof(sval));
|
||||
if (mval != sval)
|
||||
break;
|
||||
match += sizeof(mval);
|
||||
scan += sizeof(sval);
|
||||
|
||||
memcpy(&mval, match, sizeof(mval));
|
||||
memcpy(&sval, scan, sizeof(sval));
|
||||
if (mval != sval)
|
||||
break;
|
||||
match += sizeof(mval);
|
||||
scan += sizeof(sval);
|
||||
} while (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;
|
||||
memcpy(&scan_end, scan + best_len - 1, sizeof(scan_end));
|
||||
} 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 < TRIGGER_LEVEL)
|
||||
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 below (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
|
||||
* -------------------------------------------------
|
||||
*/
|
||||
|
||||
static inline unsigned longest_match(deflate_state *const s, IPos cur_match) {
|
||||
unsigned int strstart = s->strstart;
|
||||
unsigned chain_length = s->max_chain_length;/* max hash chain length */
|
||||
unsigned char *window = s->window;
|
||||
register unsigned char *scan = window + 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 = strstart > (IPos)MAX_DIST(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 = window + strstart + MAX_MATCH;
|
||||
|
||||
uint16_t scan_start, scan_end;
|
||||
|
||||
memcpy(&scan_start, scan, sizeof(scan_start));
|
||||
memcpy(&scan_end, scan+best_len-1, sizeof(scan_end));
|
||||
|
||||
/* 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)strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
|
||||
|
||||
do {
|
||||
if (cur_match >= strstart) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
int cont = 1;
|
||||
do {
|
||||
match = window + cur_match;
|
||||
if (likely(memcmp(match+best_len-1, &scan_end, sizeof(scan_end)) != 0)) {
|
||||
if ((cur_match = prev[cur_match & wmask]) > limit
|
||||
&& --chain_length != 0) {
|
||||
continue;
|
||||
} else {
|
||||
cont = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} while (1);
|
||||
|
||||
if (!cont)
|
||||
break;
|
||||
|
||||
if (memcmp(match, &scan_start, sizeof(scan_start)) != 0)
|
||||
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, mv, xor;
|
||||
|
||||
memcpy(&sv, scan, sizeof(sv));
|
||||
memcpy(&mv, match, sizeof(mv));
|
||||
|
||||
xor = sv ^ mv;
|
||||
|
||||
if (xor) {
|
||||
int match_byte = __builtin_ctzl(xor) / 8;
|
||||
scan += match_byte;
|
||||
break;
|
||||
} else {
|
||||
scan += sizeof(unsigned long);
|
||||
match += sizeof(unsigned long);
|
||||
}
|
||||
} while (scan < strend);
|
||||
|
||||
if (scan > strend)
|
||||
scan = strend;
|
||||
|
||||
Assert(scan <= 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;
|
||||
memcpy(&scan_end, scan+best_len-1, sizeof(scan_end));
|
||||
} 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 < TRIGGER_LEVEL)
|
||||
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
|
||||
674
libs/zlibng/memcopy.h
Normal file
674
libs/zlibng/memcopy.h
Normal file
@ -0,0 +1,674 @@
|
||||
/* memcopy.h -- inline functions to copy small data chunks.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
#ifndef MEMCOPY_H_
|
||||
#define MEMCOPY_H_
|
||||
|
||||
#include "gzendian.h"
|
||||
|
||||
/* Load 64 bits from IN and place the bytes at offset BITS in the result. */
|
||||
static inline uint64_t load_64_bits(const unsigned char *in, unsigned bits) {
|
||||
uint64_t chunk;
|
||||
memcpy(&chunk, in, sizeof(chunk));
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
return chunk << bits;
|
||||
#else
|
||||
return ZSWAP64(chunk) << bits;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (defined(__GNUC__) || defined(__clang__)) && defined(__ARM_NEON__)
|
||||
#include <arm_neon.h>
|
||||
typedef uint8x16_t inffast_chunk_t;
|
||||
#define INFFAST_CHUNKSIZE sizeof(inffast_chunk_t)
|
||||
#endif
|
||||
|
||||
#if defined(X86_SSE2)
|
||||
#include <immintrin.h>
|
||||
typedef __m128i inffast_chunk_t;
|
||||
#define INFFAST_CHUNKSIZE sizeof(inffast_chunk_t)
|
||||
#endif
|
||||
|
||||
#ifdef INFFAST_CHUNKSIZE
|
||||
/*
|
||||
Ask the compiler to perform a wide, unaligned load with an machine
|
||||
instruction appropriate for the inffast_chunk_t type.
|
||||
*/
|
||||
static inline inffast_chunk_t loadchunk(unsigned char const* s) {
|
||||
inffast_chunk_t c;
|
||||
memcpy(&c, s, sizeof(c));
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
Ask the compiler to perform a wide, unaligned store with an machine
|
||||
instruction appropriate for the inffast_chunk_t type.
|
||||
*/
|
||||
static inline void storechunk(unsigned char* d, inffast_chunk_t c) {
|
||||
memcpy(d, &c, sizeof(c));
|
||||
}
|
||||
|
||||
/*
|
||||
Behave like memcpy, but assume that it's OK to overwrite at least
|
||||
INFFAST_CHUNKSIZE bytes of output even if the length is shorter than this,
|
||||
that the length is non-zero, and that `from` lags `out` by at least
|
||||
INFFAST_CHUNKSIZE bytes (or that they don't overlap at all or simply that
|
||||
the distance is less than the length of the copy).
|
||||
|
||||
Aside from better memory bus utilisation, this means that short copies
|
||||
(INFFAST_CHUNKSIZE bytes or fewer) will fall straight through the loop
|
||||
without iteration, which will hopefully make the branch prediction more
|
||||
reliable.
|
||||
*/
|
||||
static inline unsigned char* chunkcopy(unsigned char *out, unsigned char const *from, unsigned len) {
|
||||
--len;
|
||||
storechunk(out, loadchunk(from));
|
||||
out += (len % INFFAST_CHUNKSIZE) + 1;
|
||||
from += (len % INFFAST_CHUNKSIZE) + 1;
|
||||
len /= INFFAST_CHUNKSIZE;
|
||||
while (len > 0) {
|
||||
storechunk(out, loadchunk(from));
|
||||
out += INFFAST_CHUNKSIZE;
|
||||
from += INFFAST_CHUNKSIZE;
|
||||
--len;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/*
|
||||
Behave like chunkcopy, but avoid writing beyond of legal output.
|
||||
*/
|
||||
static inline unsigned char* chunkcopysafe(unsigned char *out, unsigned char const *from, unsigned len,
|
||||
unsigned char *safe) {
|
||||
if ((safe - out) < (ptrdiff_t)INFFAST_CHUNKSIZE) {
|
||||
if (len & 8) {
|
||||
memcpy(out, from, 8);
|
||||
out += 8;
|
||||
from += 8;
|
||||
}
|
||||
if (len & 4) {
|
||||
memcpy(out, from, 4);
|
||||
out += 4;
|
||||
from += 4;
|
||||
}
|
||||
if (len & 2) {
|
||||
memcpy(out, from, 2);
|
||||
out += 2;
|
||||
from += 2;
|
||||
}
|
||||
if (len & 1) {
|
||||
*out++ = *from++;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
return chunkcopy(out, from, len);
|
||||
}
|
||||
|
||||
/*
|
||||
Perform short copies until distance can be rewritten as being at least
|
||||
INFFAST_CHUNKSIZE.
|
||||
|
||||
This assumes that it's OK to overwrite at least the first
|
||||
2*INFFAST_CHUNKSIZE bytes of output even if the copy is shorter than this.
|
||||
This assumption holds because inflate_fast() starts every iteration with at
|
||||
least 258 bytes of output space available (258 being the maximum length
|
||||
output from a single token; see inflate_fast()'s assumptions below).
|
||||
*/
|
||||
static inline unsigned char* chunkunroll(unsigned char *out, unsigned *dist, unsigned *len) {
|
||||
unsigned char const *from = out - *dist;
|
||||
while (*dist < *len && *dist < INFFAST_CHUNKSIZE) {
|
||||
storechunk(out, loadchunk(from));
|
||||
out += *dist;
|
||||
*len -= *dist;
|
||||
*dist += *dist;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
static inline inffast_chunk_t chunkmemset_1(unsigned char *from) {
|
||||
#if defined(X86_SSE2)
|
||||
int8_t c;
|
||||
memcpy(&c, from, sizeof(c));
|
||||
return _mm_set1_epi8(c);
|
||||
#elif defined(__ARM_NEON__) || defined(__ARM_NEON)
|
||||
return vld1q_dup_u8(from);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline inffast_chunk_t chunkmemset_2(unsigned char *from) {
|
||||
int16_t c;
|
||||
memcpy(&c, from, sizeof(c));
|
||||
#if defined(X86_SSE2)
|
||||
return _mm_set1_epi16(c);
|
||||
#elif defined(__ARM_NEON__) || defined(__ARM_NEON)
|
||||
return vreinterpretq_u8_s16(vdupq_n_s16(c));
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline inffast_chunk_t chunkmemset_4(unsigned char *from) {
|
||||
int32_t c;
|
||||
memcpy(&c, from, sizeof(c));
|
||||
#if defined(X86_SSE2)
|
||||
return _mm_set1_epi32(c);
|
||||
#elif defined(__ARM_NEON__) || defined(__ARM_NEON)
|
||||
return vreinterpretq_u8_s32(vdupq_n_s32(c));
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline inffast_chunk_t chunkmemset_8(unsigned char *from) {
|
||||
#if defined(X86_SSE2)
|
||||
int64_t c;
|
||||
memcpy(&c, from, sizeof(c));
|
||||
return _mm_set1_epi64x(c);
|
||||
#elif defined(__ARM_NEON__) || defined(__ARM_NEON)
|
||||
return vcombine_u8(vld1_u8(from), vld1_u8(from));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__ARM_NEON__) || defined(__ARM_NEON)
|
||||
static inline unsigned char *chunkmemset_3(unsigned char *out, unsigned char *from, unsigned dist, unsigned len) {
|
||||
uint8x8x3_t chunks;
|
||||
unsigned sz = sizeof(chunks);
|
||||
if (len < sz) {
|
||||
out = chunkunroll(out, &dist, &len);
|
||||
return chunkcopy(out, out - dist, len);
|
||||
}
|
||||
|
||||
/* Load 3 bytes 'a,b,c' from FROM and duplicate across all lanes:
|
||||
chunks[0] = {a,a,a,a,a,a,a,a}
|
||||
chunks[1] = {b,b,b,b,b,b,b,b}
|
||||
chunks[2] = {c,c,c,c,c,c,c,c}. */
|
||||
chunks = vld3_dup_u8(from);
|
||||
|
||||
unsigned rem = len % sz;
|
||||
len -= rem;
|
||||
while (len) {
|
||||
/* Store "a,b,c, ..., a,b,c". */
|
||||
vst3_u8(out, chunks);
|
||||
out += sz;
|
||||
len -= sz;
|
||||
}
|
||||
|
||||
if (!rem)
|
||||
return out;
|
||||
|
||||
/* Last, deal with the case when LEN is not a multiple of SZ. */
|
||||
out = chunkunroll(out, &dist, &rem);
|
||||
return chunkcopy(out, out - dist, rem);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__aarch64__)
|
||||
static inline unsigned char *chunkmemset_6(unsigned char *out, unsigned char *from, unsigned dist, unsigned len) {
|
||||
uint16x8x3_t chunks;
|
||||
unsigned sz = sizeof(chunks);
|
||||
if (len < sz) {
|
||||
out = chunkunroll(out, &dist, &len);
|
||||
return chunkcopy(out, out - dist, len);
|
||||
}
|
||||
|
||||
/* Load 6 bytes 'ab,cd,ef' from FROM and duplicate across all lanes:
|
||||
chunks[0] = {ab,ab,ab,ab,ab,ab,ab,ab}
|
||||
chunks[1] = {cd,cd,cd,cd,cd,cd,cd,cd}
|
||||
chunks[2] = {ef,ef,ef,ef,ef,ef,ef,ef}. */
|
||||
chunks = vld3q_dup_u16((unsigned short *)from);
|
||||
|
||||
unsigned rem = len % sz;
|
||||
len -= rem;
|
||||
while (len) {
|
||||
/* Store "ab,cd,ef, ..., ab,cd,ef". */
|
||||
vst3q_u16((unsigned short *)out, chunks);
|
||||
out += sz;
|
||||
len -= sz;
|
||||
}
|
||||
|
||||
if (rem)
|
||||
return out;
|
||||
|
||||
/* Last, deal with the case when LEN is not a multiple of SZ. */
|
||||
out = chunkunroll(out, &dist, &rem);
|
||||
return chunkcopy(out, out - dist, rem);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Copy DIST bytes from OUT - DIST into OUT + DIST * k, for 0 <= k < LEN/DIST. Return OUT + LEN. */
|
||||
static inline unsigned char *chunkmemset(unsigned char *out, unsigned dist, unsigned len) {
|
||||
Assert(len >= sizeof(uint64_t), "chunkmemset should be called on larger chunks");
|
||||
Assert(dist > 0, "cannot have a distance 0");
|
||||
|
||||
unsigned char *from = out - dist;
|
||||
inffast_chunk_t chunk;
|
||||
unsigned sz = sizeof(chunk);
|
||||
if (len < sz) {
|
||||
do {
|
||||
*out++ = *from++;
|
||||
--len;
|
||||
} while (len != 0);
|
||||
return out;
|
||||
}
|
||||
|
||||
switch (dist) {
|
||||
case 1: {
|
||||
chunk = chunkmemset_1(from);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
chunk = chunkmemset_2(from);
|
||||
break;
|
||||
}
|
||||
#if defined(__ARM_NEON__) || defined(__ARM_NEON)
|
||||
case 3:
|
||||
return chunkmemset_3(out, from, dist, len);
|
||||
#endif
|
||||
case 4: {
|
||||
chunk = chunkmemset_4(from);
|
||||
break;
|
||||
}
|
||||
#if defined(__aarch64__)
|
||||
case 6:
|
||||
return chunkmemset_6(out, from, dist, len);
|
||||
#endif
|
||||
case 8: {
|
||||
chunk = chunkmemset_8(from);
|
||||
break;
|
||||
}
|
||||
case 16:
|
||||
memcpy(&chunk, from, sz);
|
||||
break;
|
||||
|
||||
default:
|
||||
out = chunkunroll(out, &dist, &len);
|
||||
return chunkcopy(out, out - dist, len);
|
||||
}
|
||||
|
||||
unsigned rem = len % sz;
|
||||
len -= rem;
|
||||
while (len) {
|
||||
memcpy(out, &chunk, sz);
|
||||
out += sz;
|
||||
len -= sz;
|
||||
}
|
||||
|
||||
/* Last, deal with the case when LEN is not a multiple of SZ. */
|
||||
if (rem)
|
||||
memcpy(out, &chunk, rem);
|
||||
out += rem;
|
||||
return out;
|
||||
}
|
||||
|
||||
static inline unsigned char* chunkmemsetsafe(unsigned char *out, unsigned dist, unsigned len, unsigned left) {
|
||||
if (left < (unsigned)(3 * INFFAST_CHUNKSIZE)) {
|
||||
while (len > 0) {
|
||||
*out = *(out - dist);
|
||||
out++;
|
||||
--len;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
return chunkmemset(out, dist, len);
|
||||
}
|
||||
|
||||
#else /* INFFAST_CHUNKSIZE */
|
||||
|
||||
static inline unsigned char *copy_1_bytes(unsigned char *out, unsigned char *from) {
|
||||
*out++ = *from;
|
||||
return out;
|
||||
}
|
||||
|
||||
static inline unsigned char *copy_2_bytes(unsigned char *out, unsigned char *from) {
|
||||
uint16_t chunk;
|
||||
unsigned sz = sizeof(chunk);
|
||||
memcpy(&chunk, from, sz);
|
||||
memcpy(out, &chunk, sz);
|
||||
return out + sz;
|
||||
}
|
||||
|
||||
static inline unsigned char *copy_3_bytes(unsigned char *out, unsigned char *from) {
|
||||
out = copy_1_bytes(out, from);
|
||||
return copy_2_bytes(out, from + 1);
|
||||
}
|
||||
|
||||
static inline unsigned char *copy_4_bytes(unsigned char *out, unsigned char *from) {
|
||||
uint32_t chunk;
|
||||
unsigned sz = sizeof(chunk);
|
||||
memcpy(&chunk, from, sz);
|
||||
memcpy(out, &chunk, sz);
|
||||
return out + sz;
|
||||
}
|
||||
|
||||
static inline unsigned char *copy_5_bytes(unsigned char *out, unsigned char *from) {
|
||||
out = copy_1_bytes(out, from);
|
||||
return copy_4_bytes(out, from + 1);
|
||||
}
|
||||
|
||||
static inline unsigned char *copy_6_bytes(unsigned char *out, unsigned char *from) {
|
||||
out = copy_2_bytes(out, from);
|
||||
return copy_4_bytes(out, from + 2);
|
||||
}
|
||||
|
||||
static inline unsigned char *copy_7_bytes(unsigned char *out, unsigned char *from) {
|
||||
out = copy_3_bytes(out, from);
|
||||
return copy_4_bytes(out, from + 3);
|
||||
}
|
||||
|
||||
static inline unsigned char *copy_8_bytes(unsigned char *out, unsigned char *from) {
|
||||
uint64_t chunk;
|
||||
unsigned sz = sizeof(chunk);
|
||||
memcpy(&chunk, from, sz);
|
||||
memcpy(out, &chunk, sz);
|
||||
return out + sz;
|
||||
}
|
||||
|
||||
/* Copy LEN bytes (7 or fewer) from FROM into OUT. Return OUT + LEN. */
|
||||
static inline unsigned char *copy_bytes(unsigned char *out, unsigned char *from, unsigned len) {
|
||||
Assert(len < 8, "copy_bytes should be called with less than 8 bytes");
|
||||
|
||||
#ifndef UNALIGNED_OK
|
||||
while (len--) {
|
||||
*out++ = *from++;
|
||||
}
|
||||
return out;
|
||||
#else
|
||||
switch (len) {
|
||||
case 7:
|
||||
return copy_7_bytes(out, from);
|
||||
case 6:
|
||||
return copy_6_bytes(out, from);
|
||||
case 5:
|
||||
return copy_5_bytes(out, from);
|
||||
case 4:
|
||||
return copy_4_bytes(out, from);
|
||||
case 3:
|
||||
return copy_3_bytes(out, from);
|
||||
case 2:
|
||||
return copy_2_bytes(out, from);
|
||||
case 1:
|
||||
return copy_1_bytes(out, from);
|
||||
case 0:
|
||||
return out;
|
||||
default:
|
||||
Assert(0, "should not happen");
|
||||
}
|
||||
|
||||
return out;
|
||||
#endif /* UNALIGNED_OK */
|
||||
}
|
||||
|
||||
/* Copy LEN bytes (7 or fewer) from FROM into OUT. Return OUT + LEN. */
|
||||
static inline unsigned char *set_bytes(unsigned char *out, unsigned char *from, unsigned dist, unsigned len) {
|
||||
Assert(len < 8, "set_bytes should be called with less than 8 bytes");
|
||||
|
||||
#ifndef UNALIGNED_OK
|
||||
(void)dist;
|
||||
while (len--) {
|
||||
*out++ = *from++;
|
||||
}
|
||||
return out;
|
||||
#else
|
||||
if (dist >= len)
|
||||
return copy_bytes(out, from, len);
|
||||
|
||||
switch (dist) {
|
||||
case 6:
|
||||
Assert(len == 7, "len should be exactly 7");
|
||||
out = copy_6_bytes(out, from);
|
||||
return copy_1_bytes(out, from);
|
||||
|
||||
case 5:
|
||||
Assert(len == 6 || len == 7, "len should be either 6 or 7");
|
||||
out = copy_5_bytes(out, from);
|
||||
return copy_bytes(out, from, len - 5);
|
||||
|
||||
case 4:
|
||||
Assert(len == 5 || len == 6 || len == 7, "len should be either 5, 6, or 7");
|
||||
out = copy_4_bytes(out, from);
|
||||
return copy_bytes(out, from, len - 4);
|
||||
|
||||
case 3:
|
||||
Assert(4 <= len && len <= 7, "len should be between 4 and 7");
|
||||
out = copy_3_bytes(out, from);
|
||||
switch (len) {
|
||||
case 7:
|
||||
return copy_4_bytes(out, from);
|
||||
case 6:
|
||||
return copy_3_bytes(out, from);
|
||||
case 5:
|
||||
return copy_2_bytes(out, from);
|
||||
case 4:
|
||||
return copy_1_bytes(out, from);
|
||||
default:
|
||||
Assert(0, "should not happen");
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
Assert(3 <= len && len <= 7, "len should be between 3 and 7");
|
||||
out = copy_2_bytes(out, from);
|
||||
switch (len) {
|
||||
case 7:
|
||||
out = copy_4_bytes(out, from);
|
||||
out = copy_1_bytes(out, from);
|
||||
return out;
|
||||
case 6:
|
||||
out = copy_4_bytes(out, from);
|
||||
return out;
|
||||
case 5:
|
||||
out = copy_2_bytes(out, from);
|
||||
out = copy_1_bytes(out, from);
|
||||
return out;
|
||||
case 4:
|
||||
out = copy_2_bytes(out, from);
|
||||
return out;
|
||||
case 3:
|
||||
out = copy_1_bytes(out, from);
|
||||
return out;
|
||||
default:
|
||||
Assert(0, "should not happen");
|
||||
break;
|
||||
}
|
||||
|
||||
case 1:
|
||||
Assert(2 <= len && len <= 7, "len should be between 2 and 7");
|
||||
unsigned char c = *from;
|
||||
switch (len) {
|
||||
case 7:
|
||||
memset(out, c, 7);
|
||||
return out + 7;
|
||||
case 6:
|
||||
memset(out, c, 6);
|
||||
return out + 6;
|
||||
case 5:
|
||||
memset(out, c, 5);
|
||||
return out + 5;
|
||||
case 4:
|
||||
memset(out, c, 4);
|
||||
return out + 4;
|
||||
case 3:
|
||||
memset(out, c, 3);
|
||||
return out + 3;
|
||||
case 2:
|
||||
memset(out, c, 2);
|
||||
return out + 2;
|
||||
default:
|
||||
Assert(0, "should not happen");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
#endif /* UNALIGNED_OK */
|
||||
}
|
||||
|
||||
/* Byte by byte semantics: copy LEN bytes from OUT + DIST and write them to OUT. Return OUT + LEN. */
|
||||
static inline unsigned char *chunk_memcpy(unsigned char *out, unsigned char *from, unsigned len) {
|
||||
unsigned sz = sizeof(uint64_t);
|
||||
Assert(len >= sz, "chunk_memcpy should be called on larger chunks");
|
||||
|
||||
/* Copy a few bytes to make sure the loop below has a multiple of SZ bytes to be copied. */
|
||||
copy_8_bytes(out, from);
|
||||
|
||||
unsigned rem = len % sz;
|
||||
len /= sz;
|
||||
out += rem;
|
||||
from += rem;
|
||||
|
||||
unsigned by8 = len % sz;
|
||||
len -= by8;
|
||||
switch (by8) {
|
||||
case 7:
|
||||
out = copy_8_bytes(out, from);
|
||||
from += sz;
|
||||
case 6:
|
||||
out = copy_8_bytes(out, from);
|
||||
from += sz;
|
||||
case 5:
|
||||
out = copy_8_bytes(out, from);
|
||||
from += sz;
|
||||
case 4:
|
||||
out = copy_8_bytes(out, from);
|
||||
from += sz;
|
||||
case 3:
|
||||
out = copy_8_bytes(out, from);
|
||||
from += sz;
|
||||
case 2:
|
||||
out = copy_8_bytes(out, from);
|
||||
from += sz;
|
||||
case 1:
|
||||
out = copy_8_bytes(out, from);
|
||||
from += sz;
|
||||
}
|
||||
|
||||
while (len) {
|
||||
out = copy_8_bytes(out, from);
|
||||
from += sz;
|
||||
out = copy_8_bytes(out, from);
|
||||
from += sz;
|
||||
out = copy_8_bytes(out, from);
|
||||
from += sz;
|
||||
out = copy_8_bytes(out, from);
|
||||
from += sz;
|
||||
out = copy_8_bytes(out, from);
|
||||
from += sz;
|
||||
out = copy_8_bytes(out, from);
|
||||
from += sz;
|
||||
out = copy_8_bytes(out, from);
|
||||
from += sz;
|
||||
out = copy_8_bytes(out, from);
|
||||
from += sz;
|
||||
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Memset LEN bytes in OUT with the value at OUT - 1. Return OUT + LEN. */
|
||||
static inline unsigned char *byte_memset(unsigned char *out, unsigned len) {
|
||||
unsigned sz = sizeof(uint64_t);
|
||||
Assert(len >= sz, "byte_memset should be called on larger chunks");
|
||||
|
||||
unsigned char *from = out - 1;
|
||||
unsigned char c = *from;
|
||||
|
||||
/* First, deal with the case when LEN is not a multiple of SZ. */
|
||||
memset(out, c, sz);
|
||||
unsigned rem = len % sz;
|
||||
len /= sz;
|
||||
out += rem;
|
||||
|
||||
unsigned by8 = len % 8;
|
||||
len -= by8;
|
||||
switch (by8) {
|
||||
case 7:
|
||||
memset(out, c, sz);
|
||||
out += sz;
|
||||
case 6:
|
||||
memset(out, c, sz);
|
||||
out += sz;
|
||||
case 5:
|
||||
memset(out, c, sz);
|
||||
out += sz;
|
||||
case 4:
|
||||
memset(out, c, sz);
|
||||
out += sz;
|
||||
case 3:
|
||||
memset(out, c, sz);
|
||||
out += sz;
|
||||
case 2:
|
||||
memset(out, c, sz);
|
||||
out += sz;
|
||||
case 1:
|
||||
memset(out, c, sz);
|
||||
out += sz;
|
||||
}
|
||||
|
||||
while (len) {
|
||||
/* When sz is a constant, the compiler replaces __builtin_memset with an
|
||||
inline version that does not incur a function call overhead. */
|
||||
memset(out, c, sz);
|
||||
out += sz;
|
||||
memset(out, c, sz);
|
||||
out += sz;
|
||||
memset(out, c, sz);
|
||||
out += sz;
|
||||
memset(out, c, sz);
|
||||
out += sz;
|
||||
memset(out, c, sz);
|
||||
out += sz;
|
||||
memset(out, c, sz);
|
||||
out += sz;
|
||||
memset(out, c, sz);
|
||||
out += sz;
|
||||
memset(out, c, sz);
|
||||
out += sz;
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Copy DIST bytes from OUT - DIST into OUT + DIST * k, for 0 <= k < LEN/DIST. Return OUT + LEN. */
|
||||
static inline unsigned char *chunk_memset(unsigned char *out, unsigned char *from, unsigned dist, unsigned len) {
|
||||
if (dist >= len)
|
||||
return chunk_memcpy(out, from, len);
|
||||
|
||||
Assert(len >= sizeof(uint64_t), "chunk_memset should be called on larger chunks");
|
||||
|
||||
/* Double up the size of the memset pattern until reaching the largest pattern of size less than SZ. */
|
||||
unsigned sz = sizeof(uint64_t);
|
||||
while (dist < len && dist < sz) {
|
||||
copy_8_bytes(out, from);
|
||||
|
||||
out += dist;
|
||||
len -= dist;
|
||||
dist += dist;
|
||||
|
||||
/* Make sure the next memcpy has at least SZ bytes to be copied. */
|
||||
if (len < sz)
|
||||
/* Finish up byte by byte when there are not enough bytes left. */
|
||||
return set_bytes(out, from, dist, len);
|
||||
}
|
||||
|
||||
return chunk_memcpy(out, from, len);
|
||||
}
|
||||
|
||||
/* Byte by byte semantics: copy LEN bytes from FROM and write them to OUT. Return OUT + LEN. */
|
||||
static inline unsigned char *chunk_copy(unsigned char *out, unsigned char *from, int dist, unsigned len) {
|
||||
if (len < sizeof(uint64_t)) {
|
||||
if (dist > 0)
|
||||
return set_bytes(out, from, dist, len);
|
||||
|
||||
return copy_bytes(out, from, len);
|
||||
}
|
||||
|
||||
if (dist == 1)
|
||||
return byte_memset(out, len);
|
||||
|
||||
if (dist > 0)
|
||||
return chunk_memset(out, from, dist, len);
|
||||
|
||||
return chunk_memcpy(out, from, len);
|
||||
}
|
||||
#endif /* INFFAST_CHUNKSIZE */
|
||||
#endif /* MEMCOPY_H_ */
|
||||
2
libs/zlibng/test/.gitignore
vendored
Normal file
2
libs/zlibng/test/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# ignore Makefiles; they're all automatically generated
|
||||
Makefile
|
||||
BIN
libs/zlibng/test/CVE-2002-0059/test.gz
Normal file
BIN
libs/zlibng/test/CVE-2002-0059/test.gz
Normal file
Binary file not shown.
20
libs/zlibng/test/CVE-2003-0107.c
Normal file
20
libs/zlibng/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
libs/zlibng/test/CVE-2004-0797/test.gz
Normal file
BIN
libs/zlibng/test/CVE-2004-0797/test.gz
Normal file
Binary file not shown.
BIN
libs/zlibng/test/CVE-2005-1849/test.gz
Normal file
BIN
libs/zlibng/test/CVE-2005-1849/test.gz
Normal file
Binary file not shown.
BIN
libs/zlibng/test/CVE-2005-2096/test.gz
Normal file
BIN
libs/zlibng/test/CVE-2005-2096/test.gz
Normal file
Binary file not shown.
10
libs/zlibng/test/INDEX
Normal file
10
libs/zlibng/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
|
||||
|
||||
105
libs/zlibng/test/Makefile.in
Normal file
105
libs/zlibng/test/Makefile.in
Normal file
@ -0,0 +1,105 @@
|
||||
# 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=
|
||||
TEST_LDFLAGS=-L.. ../libz.a
|
||||
WITH_FUZZERS=
|
||||
|
||||
COMPATTESTS =
|
||||
QEMU_RUN=
|
||||
QEMU_VER:=$(shell command -v $(QEMU_RUN) --version 2> /dev/null)
|
||||
|
||||
all: oldtests cvetests $(COMPATTESTS) fuzzer
|
||||
|
||||
oldtests: #set by ../configure
|
||||
check_cross_dep:
|
||||
ifneq (,$(QEMU_RUN))
|
||||
ifeq (,$(QEMU_VER))
|
||||
$(error "You need QEMU to run tests on non-native platform")
|
||||
endif
|
||||
endif
|
||||
|
||||
ALL_SRC_FILES := $(wildcard ../*)
|
||||
|
||||
# Only check the fuzzer when it is a stand-alone executable.
|
||||
ifneq (,$(LIB_FUZZING_ENGINE))
|
||||
fuzzer:
|
||||
else
|
||||
ifeq (0,$(WITH_FUZZERS))
|
||||
fuzzer:
|
||||
else
|
||||
fuzzer:
|
||||
@${QEMU_RUN} ../checksum_fuzzer$(EXE) $(ALL_SRC_FILES) && \
|
||||
${QEMU_RUN} ../compress_fuzzer$(EXE) $(ALL_SRC_FILES) && \
|
||||
${QEMU_RUN} ../example_small_fuzzer$(EXE) $(ALL_SRC_FILES) && \
|
||||
${QEMU_RUN} ../example_large_fuzzer$(EXE) $(ALL_SRC_FILES) && \
|
||||
${QEMU_RUN} ../example_flush_fuzzer$(EXE) $(ALL_SRC_FILES) && \
|
||||
${QEMU_RUN} ../example_dict_fuzzer$(EXE) $(ALL_SRC_FILES) && \
|
||||
${QEMU_RUN} ../minigzip_fuzzer$(EXE) $(ALL_SRC_FILES)
|
||||
endif
|
||||
endif
|
||||
|
||||
teststatic: check_cross_dep
|
||||
@TMPST=tmpst_$$; \
|
||||
if echo hello world | ${QEMU_RUN} ../minigzip$(EXE) | ${QEMU_RUN} ../minigzip$(EXE) -d && ${QEMU_RUN} ../example$(EXE) $$TMPST ; then \
|
||||
echo ' *** zlib test OK ***'; \
|
||||
else \
|
||||
echo ' *** zlib test FAILED ***'; exit 1; \
|
||||
fi
|
||||
@rm -f tmpst_$$
|
||||
|
||||
testshared: check_cross_dep
|
||||
@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 | ${QEMU_RUN} ../minigzipsh$(EXE) | ${QEMU_RUN} ../minigzipsh$(EXE) -d && ${QEMU_RUN} ../examplesh$(EXE) $$TMPSH; then \
|
||||
echo ' *** zlib shared test OK ***'; \
|
||||
else \
|
||||
echo ' *** zlib shared test FAILED ***'; exit 1; \
|
||||
fi
|
||||
@rm -f tmpsh_$$
|
||||
|
||||
test64: check_cross_dep
|
||||
@TMP64=tmp64_$$; \
|
||||
if echo hello world | ${QEMU_RUN} ../minigzip64$(EXE) | ${QEMU_RUN} ../minigzip64$(EXE) -d && ${QEMU_RUN} ../example64$(EXE) $$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: check_cross_dep
|
||||
@EXE=$(EXE) QEMU_RUN="${QEMU_RUN}" $(SRCDIR)/testCVEinputs.sh
|
||||
|
||||
testCVE-2003-0107: CVE-2003-0107$(EXE) check_cross_dep
|
||||
@if ${QEMU_RUN} ./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
|
||||
552
libs/zlibng/test/example.c
Normal file
552
libs/zlibng/test/example.c
Normal file
@ -0,0 +1,552 @@
|
||||
/* example.c -- usage example of the zlib compression library
|
||||
* Copyright (C) 1995-2006, 2011, 2016 Jean-loup Gailly
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#include "zbuild.h"
|
||||
#ifdef ZLIB_COMPAT
|
||||
# include "zlib.h"
|
||||
#else
|
||||
# include "zlib-ng.h"
|
||||
#endif
|
||||
|
||||
#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); \
|
||||
} \
|
||||
}
|
||||
|
||||
static const char hello[] = "hello, hello!";
|
||||
/* "hello world" would be more standard, but the repeated "hello"
|
||||
* stresses the compression code better, sorry...
|
||||
*/
|
||||
|
||||
static const char dictionary[] = "hello";
|
||||
static unsigned long dictId = 0; /* Adler32 value of the dictionary */
|
||||
|
||||
|
||||
void test_compress (unsigned char *compr, z_size_t comprLen,unsigned char *uncompr, z_size_t uncomprLen);
|
||||
void test_gzio (const char *fname, unsigned char *uncompr, z_size_t uncomprLen);
|
||||
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, z_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 = NULL;
|
||||
static free_func zfree = NULL;
|
||||
|
||||
/* ===========================================================================
|
||||
* Test compress() and uncompress()
|
||||
*/
|
||||
void test_compress(unsigned char *compr, z_size_t comprLen, unsigned char *uncompr, z_size_t uncomprLen)
|
||||
{
|
||||
int err;
|
||||
size_t len = strlen(hello)+1;
|
||||
|
||||
err = PREFIX(compress)(compr, &comprLen, (const unsigned char*)hello, (z_size_t)len);
|
||||
CHECK_ERR(err, "compress");
|
||||
|
||||
strcpy((char*)uncompr, "garbage");
|
||||
|
||||
err = PREFIX(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);
|
||||
}
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Test read/write of .gz files
|
||||
*/
|
||||
void test_gzio(const char *fname, unsigned char *uncompr, z_size_t 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 = PREFIX(gzopen)(fname, "wb");
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "gzopen error\n");
|
||||
exit(1);
|
||||
}
|
||||
PREFIX(gzputc)(file, 'h');
|
||||
if (PREFIX(gzputs)(file, "ello") != 4) {
|
||||
fprintf(stderr, "gzputs err: %s\n", PREFIX(gzerror)(file, &err));
|
||||
exit(1);
|
||||
}
|
||||
if (PREFIX(gzprintf)(file, ", %s!", "hello") != 8) {
|
||||
fprintf(stderr, "gzprintf err: %s\n", PREFIX(gzerror)(file, &err));
|
||||
exit(1);
|
||||
}
|
||||
PREFIX(gzseek)(file, 1L, SEEK_CUR); /* add one zero byte */
|
||||
PREFIX(gzclose)(file);
|
||||
|
||||
file = PREFIX(gzopen)(fname, "rb");
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "gzopen error\n");
|
||||
exit(1);
|
||||
}
|
||||
strcpy((char*)uncompr, "garbage");
|
||||
|
||||
if (PREFIX(gzread)(file, uncompr, (unsigned)uncomprLen) != len) {
|
||||
fprintf(stderr, "gzread err: %s\n", PREFIX(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 = PREFIX(gzseek)(file, -8L, SEEK_CUR);
|
||||
if (pos != 6 || PREFIX(gztell)(file) != pos) {
|
||||
fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",
|
||||
(long)pos, (long)PREFIX(gztell)(file));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (PREFIX(gzgetc)(file) != ' ') {
|
||||
fprintf(stderr, "gzgetc error\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (PREFIX(gzungetc)(' ', file) != ' ') {
|
||||
fprintf(stderr, "gzungetc error\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
PREFIX(gzgets)(file, (char*)uncompr, (int)uncomprLen);
|
||||
if (strlen((char*)uncompr) != 7) { /* " hello!" */
|
||||
fprintf(stderr, "gzgets err after gzseek: %s\n", PREFIX(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);
|
||||
}
|
||||
|
||||
PREFIX(gzclose)(file);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Test deflate() with small buffers
|
||||
*/
|
||||
void test_deflate(unsigned char *compr, size_t comprLen)
|
||||
{
|
||||
PREFIX3(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;
|
||||
c_stream.total_in = 0;
|
||||
c_stream.total_out = 0;
|
||||
|
||||
err = PREFIX(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 = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
|
||||
CHECK_ERR(err, "deflate");
|
||||
}
|
||||
/* Finish the stream, still forcing small buffers: */
|
||||
for (;;) {
|
||||
c_stream.avail_out = 1;
|
||||
err = PREFIX(deflate)(&c_stream, Z_FINISH);
|
||||
if (err == Z_STREAM_END) break;
|
||||
CHECK_ERR(err, "deflate");
|
||||
}
|
||||
|
||||
err = PREFIX(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;
|
||||
PREFIX3(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;
|
||||
d_stream.total_in = 0;
|
||||
d_stream.total_out = 0;
|
||||
|
||||
err = PREFIX(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 = PREFIX(inflate)(&d_stream, Z_NO_FLUSH);
|
||||
if (err == Z_STREAM_END) break;
|
||||
CHECK_ERR(err, "inflate");
|
||||
}
|
||||
|
||||
err = PREFIX(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);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int diff;
|
||||
|
||||
/* ===========================================================================
|
||||
* 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)
|
||||
{
|
||||
PREFIX3(stream) c_stream; /* compression stream */
|
||||
int err;
|
||||
|
||||
c_stream.zalloc = zalloc;
|
||||
c_stream.zfree = zfree;
|
||||
c_stream.opaque = (void *)0;
|
||||
|
||||
err = PREFIX(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 = PREFIX(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: */
|
||||
PREFIX(deflateParams)(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
|
||||
c_stream.next_in = compr;
|
||||
diff = (unsigned int)(c_stream.next_out - compr);
|
||||
c_stream.avail_in = diff;
|
||||
err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
|
||||
CHECK_ERR(err, "deflate");
|
||||
|
||||
/* Switch back to compressing mode: */
|
||||
PREFIX(deflateParams)(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
|
||||
c_stream.next_in = uncompr;
|
||||
c_stream.avail_in = (unsigned int)uncomprLen;
|
||||
err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
|
||||
CHECK_ERR(err, "deflate");
|
||||
|
||||
err = PREFIX(deflate)(&c_stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
fprintf(stderr, "deflate should report Z_STREAM_END\n");
|
||||
exit(1);
|
||||
}
|
||||
err = PREFIX(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;
|
||||
PREFIX3(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;
|
||||
d_stream.total_in = 0;
|
||||
d_stream.total_out = 0;
|
||||
|
||||
err = PREFIX(inflateInit)(&d_stream);
|
||||
CHECK_ERR(err, "inflateInit");
|
||||
|
||||
for (;;) {
|
||||
d_stream.next_out = uncompr; /* discard the output */
|
||||
d_stream.avail_out = (unsigned int)uncomprLen;
|
||||
err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH);
|
||||
if (err == Z_STREAM_END) break;
|
||||
CHECK_ERR(err, "large inflate");
|
||||
}
|
||||
|
||||
err = PREFIX(inflateEnd)(&d_stream);
|
||||
CHECK_ERR(err, "inflateEnd");
|
||||
|
||||
if (d_stream.total_out != 2*uncomprLen + diff) {
|
||||
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, z_size_t *comprLen)
|
||||
{
|
||||
PREFIX3(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 = PREFIX(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 = PREFIX(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 = PREFIX(deflate)(&c_stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
CHECK_ERR(err, "deflate");
|
||||
}
|
||||
err = PREFIX(deflateEnd)(&c_stream);
|
||||
CHECK_ERR(err, "deflateEnd");
|
||||
|
||||
*comprLen = (z_size_t)c_stream.total_out;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Test inflateSync()
|
||||
*/
|
||||
void test_sync(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen)
|
||||
{
|
||||
int err;
|
||||
PREFIX3(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 = PREFIX(inflateInit)(&d_stream);
|
||||
CHECK_ERR(err, "inflateInit");
|
||||
|
||||
d_stream.next_out = uncompr;
|
||||
d_stream.avail_out = (unsigned int)uncomprLen;
|
||||
|
||||
err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH);
|
||||
CHECK_ERR(err, "inflate");
|
||||
|
||||
d_stream.avail_in = (unsigned int)comprLen-2; /* read all compressed data */
|
||||
err = PREFIX(inflateSync)(&d_stream); /* but skip the damaged part */
|
||||
CHECK_ERR(err, "inflateSync");
|
||||
|
||||
err = PREFIX(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 = PREFIX(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)
|
||||
{
|
||||
PREFIX3(stream) c_stream; /* compression stream */
|
||||
int err;
|
||||
|
||||
c_stream.zalloc = zalloc;
|
||||
c_stream.zfree = zfree;
|
||||
c_stream.opaque = (void *)0;
|
||||
c_stream.adler = 0;
|
||||
|
||||
err = PREFIX(deflateInit)(&c_stream, Z_BEST_COMPRESSION);
|
||||
CHECK_ERR(err, "deflateInit");
|
||||
|
||||
err = PREFIX(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 = PREFIX(deflate)(&c_stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
fprintf(stderr, "deflate should report Z_STREAM_END\n");
|
||||
exit(1);
|
||||
}
|
||||
err = PREFIX(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;
|
||||
PREFIX3(stream) d_stream; /* decompression stream */
|
||||
|
||||
strcpy((char*)uncompr, "garbage garbage garbage");
|
||||
|
||||
d_stream.zalloc = zalloc;
|
||||
d_stream.zfree = zfree;
|
||||
d_stream.opaque = (void *)0;
|
||||
d_stream.adler = 0;
|
||||
d_stream.next_in = compr;
|
||||
d_stream.avail_in = (unsigned int)comprLen;
|
||||
|
||||
err = PREFIX(inflateInit)(&d_stream);
|
||||
CHECK_ERR(err, "inflateInit");
|
||||
|
||||
d_stream.next_out = uncompr;
|
||||
d_stream.avail_out = (unsigned int)uncomprLen;
|
||||
|
||||
for (;;) {
|
||||
err = PREFIX(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 = PREFIX(inflateSetDictionary)(&d_stream, (const unsigned char*)dictionary,
|
||||
(int)sizeof(dictionary));
|
||||
}
|
||||
CHECK_ERR(err, "inflate with dict");
|
||||
}
|
||||
|
||||
err = PREFIX(inflateEnd)(&d_stream);
|
||||
CHECK_ERR(err, "inflateEnd");
|
||||
|
||||
if (strncmp((char*)uncompr, hello, sizeof(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;
|
||||
z_size_t comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
|
||||
z_size_t uncomprLen = comprLen;
|
||||
static const char* myVersion = PREFIX2(VERSION);
|
||||
|
||||
if (zVersion()[0] != myVersion[0]) {
|
||||
fprintf(stderr, "incompatible zlib version\n");
|
||||
exit(1);
|
||||
|
||||
} else if (strcmp(zVersion(), PREFIX2(VERSION)) != 0) {
|
||||
fprintf(stderr, "warning: different zlib version\n");
|
||||
}
|
||||
|
||||
printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n",
|
||||
PREFIX2(VERSION), PREFIX2(VERNUM), PREFIX(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 == NULL || uncompr == NULL) {
|
||||
printf("out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
test_compress(compr, comprLen, uncompr, uncomprLen);
|
||||
|
||||
test_gzio((argc > 1 ? argv[1] : TESTFILE),
|
||||
uncompr, uncomprLen);
|
||||
|
||||
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;
|
||||
}
|
||||
73
libs/zlibng/test/fuzz/checksum_fuzzer.c
Normal file
73
libs/zlibng/test/fuzz/checksum_fuzzer.c
Normal file
@ -0,0 +1,73 @@
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "zbuild.h"
|
||||
#ifdef ZLIB_COMPAT
|
||||
# include "zlib.h"
|
||||
#else
|
||||
# include "zlib-ng.h"
|
||||
#endif
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataLen) {
|
||||
uint32_t crc0 = PREFIX(crc32)(0L, NULL, 0);
|
||||
uint32_t crc1 = crc0;
|
||||
uint32_t crc2 = crc0;
|
||||
uint32_t adler0 = PREFIX(adler32)(0L, NULL, 0);
|
||||
uint32_t adler1 = adler0;
|
||||
uint32_t adler2 = adler0;
|
||||
/* Checksum with a buffer of size equal to the first byte in the input. */
|
||||
uint32_t buffSize = data[0];
|
||||
uint32_t offset = 0;
|
||||
uint32_t op[32];
|
||||
|
||||
/* Discard inputs larger than 1Mb. */
|
||||
static size_t kMaxSize = 1024 * 1024;
|
||||
if (dataLen < 1 || dataLen > kMaxSize)
|
||||
return 0;
|
||||
|
||||
/* Make sure the buffer has at least a byte. */
|
||||
if (buffSize == 0)
|
||||
++buffSize;
|
||||
|
||||
/* CRC32 */
|
||||
PREFIX(crc32_combine_gen)(op, buffSize);
|
||||
for (offset = 0; offset + buffSize <= dataLen; offset += buffSize) {
|
||||
uint32_t crc3 = PREFIX(crc32_z)(crc0, data + offset, buffSize);
|
||||
uint32_t crc4 = PREFIX(crc32_combine_op)(crc1, crc3, op);
|
||||
crc1 = PREFIX(crc32_z)(crc1, data + offset, buffSize);
|
||||
assert(crc1 == crc4);
|
||||
}
|
||||
crc1 = PREFIX(crc32_z)(crc1, data + offset, dataLen % buffSize);
|
||||
|
||||
crc2 = PREFIX(crc32_z)(crc2, data, dataLen);
|
||||
|
||||
assert(crc1 == crc2);
|
||||
assert(PREFIX(crc32_combine)(crc1, crc2, dataLen) ==
|
||||
PREFIX(crc32_combine)(crc1, crc1, dataLen));
|
||||
|
||||
/* Fast CRC32 combine. */
|
||||
PREFIX(crc32_combine_gen)(op, dataLen);
|
||||
assert(PREFIX(crc32_combine_op)(crc1, crc2, op) ==
|
||||
PREFIX(crc32_combine_op)(crc2, crc1, op));
|
||||
assert(PREFIX(crc32_combine)(crc1, crc2, dataLen) ==
|
||||
PREFIX(crc32_combine_op)(crc2, crc1, op));
|
||||
|
||||
/* Adler32 */
|
||||
for (offset = 0; offset + buffSize <= dataLen; offset += buffSize)
|
||||
adler1 = PREFIX(adler32_z)(adler1, data + offset, buffSize);
|
||||
adler1 = PREFIX(adler32_z)(adler1, data + offset, dataLen % buffSize);
|
||||
|
||||
adler2 = PREFIX(adler32_z)(adler2, data, dataLen);
|
||||
|
||||
assert(adler1 == adler2);
|
||||
assert(PREFIX(adler32_combine)(adler1, adler2, dataLen) ==
|
||||
PREFIX(adler32_combine)(adler1, adler1, dataLen));
|
||||
|
||||
/* This function must return 0. */
|
||||
return 0;
|
||||
}
|
||||
87
libs/zlibng/test/fuzz/compress_fuzzer.c
Normal file
87
libs/zlibng/test/fuzz/compress_fuzzer.c
Normal file
@ -0,0 +1,87 @@
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "zbuild.h"
|
||||
#ifdef ZLIB_COMPAT
|
||||
# include "zlib.h"
|
||||
#else
|
||||
# include "zlib-ng.h"
|
||||
#endif
|
||||
|
||||
static const uint8_t *data;
|
||||
static size_t dataLen;
|
||||
|
||||
static void check_compress_level(uint8_t *compr, size_t comprLen,
|
||||
uint8_t *uncompr, size_t uncomprLen,
|
||||
int level) {
|
||||
PREFIX(compress2)(compr, &comprLen, data, dataLen, level);
|
||||
PREFIX(uncompress)(uncompr, &uncomprLen, compr, comprLen);
|
||||
|
||||
/* Make sure compress + uncompress gives back the input data. */
|
||||
assert(dataLen == uncomprLen);
|
||||
assert(0 == memcmp(data, uncompr, dataLen));
|
||||
}
|
||||
|
||||
#define put_byte(s, i, c) {s[i] = (unsigned char)(c);}
|
||||
|
||||
static void write_zlib_header(uint8_t *s) {
|
||||
unsigned level_flags = 0; /* compression level (0..3) */
|
||||
unsigned w_bits = 8; /* window size log2(w_size) (8..16) */
|
||||
unsigned int header = (Z_DEFLATED + ((w_bits-8)<<4)) << 8;
|
||||
header |= (level_flags << 6);
|
||||
|
||||
header += 31 - (header % 31);
|
||||
|
||||
/* s is guaranteed to be longer than 2 bytes. */
|
||||
put_byte(s, 0, (unsigned char)(header >> 8));
|
||||
put_byte(s, 1, (unsigned char)(header & 0xff));
|
||||
}
|
||||
|
||||
static void check_decompress(uint8_t *compr, size_t comprLen) {
|
||||
/* We need to write a valid zlib header of size two bytes. Copy the input data
|
||||
in a larger buffer. Do not modify the input data to avoid libFuzzer error:
|
||||
fuzz target overwrites its const input. */
|
||||
size_t copyLen = dataLen + 2;
|
||||
uint8_t *copy = (uint8_t *)malloc(copyLen);
|
||||
memcpy(copy + 2, data, dataLen);
|
||||
write_zlib_header(copy);
|
||||
|
||||
PREFIX(uncompress)(compr, &comprLen, copy, copyLen);
|
||||
free(copy);
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *d, size_t size) {
|
||||
/* compressBound does not provide enough space for low compression levels. */
|
||||
size_t comprLen = 100 + 2 * PREFIX(compressBound)(size);
|
||||
size_t uncomprLen = size;
|
||||
uint8_t *compr, *uncompr;
|
||||
|
||||
/* Discard inputs larger than 1Mb. */
|
||||
static size_t kMaxSize = 1024 * 1024;
|
||||
|
||||
if (size < 1 || size > kMaxSize)
|
||||
return 0;
|
||||
|
||||
data = d;
|
||||
dataLen = size;
|
||||
compr = (uint8_t *)calloc(1, comprLen);
|
||||
uncompr = (uint8_t *)calloc(1, uncomprLen);
|
||||
|
||||
check_compress_level(compr, comprLen, uncompr, uncomprLen, 1);
|
||||
check_compress_level(compr, comprLen, uncompr, uncomprLen, 3);
|
||||
check_compress_level(compr, comprLen, uncompr, uncomprLen, 6);
|
||||
check_compress_level(compr, comprLen, uncompr, uncomprLen, 7);
|
||||
|
||||
check_decompress(compr, comprLen);
|
||||
|
||||
free(compr);
|
||||
free(uncompr);
|
||||
|
||||
/* This function must return 0. */
|
||||
return 0;
|
||||
}
|
||||
170
libs/zlibng/test/fuzz/example_dict_fuzzer.c
Normal file
170
libs/zlibng/test/fuzz/example_dict_fuzzer.c
Normal file
@ -0,0 +1,170 @@
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "zbuild.h"
|
||||
#ifdef ZLIB_COMPAT
|
||||
# include "zlib.h"
|
||||
#else
|
||||
# include "zlib-ng.h"
|
||||
#endif
|
||||
|
||||
#define CHECK_ERR(err, msg) { \
|
||||
if (err != Z_OK) { \
|
||||
fprintf(stderr, "%s error: %d\n", msg, err); \
|
||||
exit(1); \
|
||||
} \
|
||||
}
|
||||
|
||||
static const uint8_t *data;
|
||||
static size_t dataLen;
|
||||
static alloc_func zalloc = NULL;
|
||||
static free_func zfree = NULL;
|
||||
static size_t dictionaryLen = 0;
|
||||
static unsigned long dictId; /* Adler32 value of the dictionary */
|
||||
|
||||
/* ===========================================================================
|
||||
* Test deflate() with preset dictionary
|
||||
*/
|
||||
void test_dict_deflate(unsigned char **compr, size_t *comprLen)
|
||||
{
|
||||
PREFIX3(stream) c_stream; /* compression stream */
|
||||
int err;
|
||||
int level = data[0] % 11 - 1; /* [-1..9]
|
||||
compression levels
|
||||
#define Z_NO_COMPRESSION 0
|
||||
#define Z_BEST_SPEED 1
|
||||
#define Z_BEST_COMPRESSION 9
|
||||
#define Z_DEFAULT_COMPRESSION (-1) */
|
||||
|
||||
int method = Z_DEFLATED; /* The deflate compression method (the only one
|
||||
supported in this version) */
|
||||
int windowBits = 8 + data[0] % 8; /* The windowBits parameter is the base
|
||||
two logarithm of the window size (the size of the history buffer). It
|
||||
should be in the range 8..15 for this version of the library. */
|
||||
int memLevel = 1 + data[0] % 9; /* memLevel=1 uses minimum memory but is
|
||||
slow and reduces compression ratio; memLevel=9 uses maximum memory for
|
||||
optimal speed. */
|
||||
int strategy = data[0] % 5; /* [0..4]
|
||||
#define Z_FILTERED 1
|
||||
#define Z_HUFFMAN_ONLY 2
|
||||
#define Z_RLE 3
|
||||
#define Z_FIXED 4
|
||||
#define Z_DEFAULT_STRATEGY 0 */
|
||||
|
||||
/* deflate would fail for no-compression or for speed levels. */
|
||||
if (level == 0 || level == 1)
|
||||
level = -1;
|
||||
|
||||
c_stream.zalloc = zalloc;
|
||||
c_stream.zfree = zfree;
|
||||
c_stream.opaque = (void *)0;
|
||||
|
||||
err = PREFIX(deflateInit2)(&c_stream, level, method, windowBits, memLevel,
|
||||
strategy);
|
||||
CHECK_ERR(err, "deflateInit");
|
||||
|
||||
err = PREFIX(deflateSetDictionary)(
|
||||
&c_stream, (const unsigned char *)data, dictionaryLen);
|
||||
CHECK_ERR(err, "deflateSetDictionary");
|
||||
|
||||
/* deflateBound does not provide enough space for low compression levels. */
|
||||
*comprLen = 100 + 2 * PREFIX(deflateBound)(&c_stream, dataLen);
|
||||
*compr = (uint8_t *)calloc(1, *comprLen);
|
||||
|
||||
dictId = c_stream.adler;
|
||||
c_stream.next_out = *compr;
|
||||
c_stream.avail_out = (unsigned int)(*comprLen);
|
||||
|
||||
c_stream.next_in = data;
|
||||
c_stream.avail_in = dataLen;
|
||||
|
||||
err = PREFIX(deflate)(&c_stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
fprintf(stderr, "deflate dict should report Z_STREAM_END\n");
|
||||
exit(1);
|
||||
}
|
||||
err = PREFIX(deflateEnd)(&c_stream);
|
||||
CHECK_ERR(err, "deflateEnd");
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Test inflate() with a preset dictionary
|
||||
*/
|
||||
void test_dict_inflate(unsigned char *compr, size_t comprLen) {
|
||||
int err;
|
||||
PREFIX3(stream) d_stream; /* decompression stream */
|
||||
unsigned char *uncompr;
|
||||
|
||||
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 = PREFIX(inflateInit)(&d_stream);
|
||||
CHECK_ERR(err, "inflateInit");
|
||||
|
||||
uncompr = (uint8_t *)calloc(1, dataLen);
|
||||
d_stream.next_out = uncompr;
|
||||
d_stream.avail_out = (unsigned int)dataLen;
|
||||
|
||||
for (;;) {
|
||||
err = PREFIX(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 = PREFIX(inflateSetDictionary)(
|
||||
&d_stream, (const unsigned char *)data, dictionaryLen);
|
||||
}
|
||||
CHECK_ERR(err, "inflate with dict");
|
||||
}
|
||||
|
||||
err = PREFIX(inflateEnd)(&d_stream);
|
||||
CHECK_ERR(err, "inflateEnd");
|
||||
|
||||
if (memcmp(uncompr, data, dataLen)) {
|
||||
fprintf(stderr, "bad inflate with dict\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
free(uncompr);
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *d, size_t size) {
|
||||
size_t comprLen = 0;
|
||||
uint8_t *compr;
|
||||
|
||||
/* Discard inputs larger than 100Kb. */
|
||||
static size_t kMaxSize = 100 * 1024;
|
||||
|
||||
if (size < 1 || size > kMaxSize)
|
||||
return 0;
|
||||
|
||||
data = d;
|
||||
dataLen = size;
|
||||
|
||||
/* Set up the contents of the dictionary. The size of the dictionary is
|
||||
intentionally selected to be of unusual size. To help cover more corner
|
||||
cases, the size of the dictionary is read from the input data. */
|
||||
dictionaryLen = data[0];
|
||||
if (dictionaryLen > dataLen)
|
||||
dictionaryLen = dataLen;
|
||||
|
||||
test_dict_deflate(&compr, &comprLen);
|
||||
test_dict_inflate(compr, comprLen);
|
||||
|
||||
free(compr);
|
||||
|
||||
/* This function must return 0. */
|
||||
return 0;
|
||||
}
|
||||
126
libs/zlibng/test/fuzz/example_flush_fuzzer.c
Normal file
126
libs/zlibng/test/fuzz/example_flush_fuzzer.c
Normal file
@ -0,0 +1,126 @@
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "zbuild.h"
|
||||
#ifdef ZLIB_COMPAT
|
||||
# include "zlib.h"
|
||||
#else
|
||||
# include "zlib-ng.h"
|
||||
#endif
|
||||
|
||||
#define CHECK_ERR(err, msg) { \
|
||||
if (err != Z_OK) { \
|
||||
fprintf(stderr, "%s error: %d\n", msg, err); \
|
||||
exit(1); \
|
||||
} \
|
||||
}
|
||||
|
||||
static const uint8_t *data;
|
||||
static size_t dataLen;
|
||||
static alloc_func zalloc = NULL;
|
||||
static free_func zfree = NULL;
|
||||
|
||||
/* ===========================================================================
|
||||
* Test deflate() with full flush
|
||||
*/
|
||||
void test_flush(unsigned char *compr, z_size_t *comprLen) {
|
||||
PREFIX3(stream) c_stream; /* compression stream */
|
||||
int err;
|
||||
unsigned int len = dataLen;
|
||||
|
||||
c_stream.zalloc = zalloc;
|
||||
c_stream.zfree = zfree;
|
||||
c_stream.opaque = (void *)0;
|
||||
|
||||
err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION);
|
||||
CHECK_ERR(err, "deflateInit");
|
||||
|
||||
c_stream.next_in = (const unsigned char *)data;
|
||||
c_stream.next_out = compr;
|
||||
c_stream.avail_in = 3;
|
||||
c_stream.avail_out = (unsigned int)*comprLen;
|
||||
err = PREFIX(deflate)(&c_stream, Z_FULL_FLUSH);
|
||||
CHECK_ERR(err, "deflate flush 1");
|
||||
|
||||
compr[3]++; /* force an error in first compressed block */
|
||||
c_stream.avail_in = len - 3;
|
||||
|
||||
err = PREFIX(deflate)(&c_stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
CHECK_ERR(err, "deflate flush 2");
|
||||
}
|
||||
err = PREFIX(deflateEnd)(&c_stream);
|
||||
CHECK_ERR(err, "deflateEnd");
|
||||
|
||||
*comprLen = (z_size_t)c_stream.total_out;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Test inflateSync()
|
||||
*/
|
||||
void test_sync(unsigned char *compr, size_t comprLen, unsigned char *uncompr,
|
||||
size_t uncomprLen) {
|
||||
int err;
|
||||
PREFIX3(stream) d_stream; /* decompression stream */
|
||||
|
||||
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 = PREFIX(inflateInit)(&d_stream);
|
||||
CHECK_ERR(err, "inflateInit");
|
||||
|
||||
d_stream.next_out = uncompr;
|
||||
d_stream.avail_out = (unsigned int)uncomprLen;
|
||||
|
||||
err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH);
|
||||
CHECK_ERR(err, "inflate");
|
||||
|
||||
d_stream.avail_in = (unsigned int)comprLen - 2; /* read all compressed data */
|
||||
err = PREFIX(inflateSync)(&d_stream); /* but skip the damaged part */
|
||||
CHECK_ERR(err, "inflateSync");
|
||||
|
||||
err = PREFIX(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 = PREFIX(inflateEnd)(&d_stream);
|
||||
CHECK_ERR(err, "inflateEnd");
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *d, size_t size) {
|
||||
size_t comprLen = 100 + 2 * PREFIX(compressBound)(size);
|
||||
size_t uncomprLen = size;
|
||||
uint8_t *compr, *uncompr;
|
||||
|
||||
/* Discard inputs larger than 1Mb. */
|
||||
static size_t kMaxSize = 1024 * 1024;
|
||||
|
||||
// This test requires at least 3 bytes of input data.
|
||||
if (size <= 3 || size > kMaxSize)
|
||||
return 0;
|
||||
|
||||
data = d;
|
||||
dataLen = size;
|
||||
compr = (uint8_t *)calloc(1, comprLen);
|
||||
uncompr = (uint8_t *)calloc(1, uncomprLen);
|
||||
|
||||
test_flush(compr, &comprLen);
|
||||
test_sync(compr, comprLen, uncompr, uncomprLen);
|
||||
|
||||
free(compr);
|
||||
free(uncompr);
|
||||
|
||||
/* This function must return 0. */
|
||||
return 0;
|
||||
}
|
||||
143
libs/zlibng/test/fuzz/example_large_fuzzer.c
Normal file
143
libs/zlibng/test/fuzz/example_large_fuzzer.c
Normal file
@ -0,0 +1,143 @@
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "zbuild.h"
|
||||
#ifdef ZLIB_COMPAT
|
||||
# include "zlib.h"
|
||||
#else
|
||||
# include "zlib-ng.h"
|
||||
#endif
|
||||
|
||||
#define CHECK_ERR(err, msg) { \
|
||||
if (err != Z_OK) { \
|
||||
fprintf(stderr, "%s error: %d\n", msg, err); \
|
||||
exit(1); \
|
||||
} \
|
||||
}
|
||||
|
||||
static const uint8_t *data;
|
||||
static size_t dataLen;
|
||||
static alloc_func zalloc = NULL;
|
||||
static free_func zfree = NULL;
|
||||
static unsigned int diff;
|
||||
|
||||
/* ===========================================================================
|
||||
* 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) {
|
||||
PREFIX3(stream) c_stream; /* compression stream */
|
||||
int err;
|
||||
|
||||
c_stream.zalloc = zalloc;
|
||||
c_stream.zfree = zfree;
|
||||
c_stream.opaque = (void *)0;
|
||||
|
||||
err = PREFIX(deflateInit)(&c_stream, Z_BEST_COMPRESSION);
|
||||
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 = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
|
||||
CHECK_ERR(err, "deflate large 1");
|
||||
if (c_stream.avail_in != 0) {
|
||||
fprintf(stderr, "deflate not greedy\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Feed in already compressed data and switch to no compression: */
|
||||
PREFIX(deflateParams)(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
|
||||
c_stream.next_in = compr;
|
||||
diff = (unsigned int)(c_stream.next_out - compr);
|
||||
c_stream.avail_in = diff;
|
||||
err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
|
||||
CHECK_ERR(err, "deflate large 2");
|
||||
|
||||
/* Switch back to compressing mode: */
|
||||
PREFIX(deflateParams)(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
|
||||
c_stream.next_in = uncompr;
|
||||
c_stream.avail_in = (unsigned int)uncomprLen;
|
||||
err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
|
||||
CHECK_ERR(err, "deflate large 3");
|
||||
|
||||
err = PREFIX(deflate)(&c_stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
fprintf(stderr, "deflate large should report Z_STREAM_END\n");
|
||||
exit(1);
|
||||
}
|
||||
err = PREFIX(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;
|
||||
PREFIX3(stream) d_stream; /* decompression stream */
|
||||
|
||||
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 = PREFIX(inflateInit)(&d_stream);
|
||||
CHECK_ERR(err, "inflateInit");
|
||||
|
||||
for (;;) {
|
||||
d_stream.next_out = uncompr; /* discard the output */
|
||||
d_stream.avail_out = (unsigned int)uncomprLen;
|
||||
err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH);
|
||||
if (err == Z_STREAM_END)
|
||||
break;
|
||||
CHECK_ERR(err, "large inflate");
|
||||
}
|
||||
|
||||
err = PREFIX(inflateEnd)(&d_stream);
|
||||
CHECK_ERR(err, "inflateEnd");
|
||||
|
||||
if (d_stream.total_out != 2 * uncomprLen + diff) {
|
||||
fprintf(stderr, "bad large inflate: %zu\n", d_stream.total_out);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *d, size_t size) {
|
||||
size_t comprLen = 100 + 3 * size;
|
||||
size_t uncomprLen = comprLen;
|
||||
uint8_t *compr, *uncompr;
|
||||
|
||||
/* Discard inputs larger than 512Kb. */
|
||||
static size_t kMaxSize = 512 * 1024;
|
||||
|
||||
if (size < 1 || size > kMaxSize)
|
||||
return 0;
|
||||
|
||||
data = d;
|
||||
dataLen = size;
|
||||
compr = (uint8_t *)calloc(1, comprLen);
|
||||
uncompr = (uint8_t *)calloc(1, uncomprLen);
|
||||
|
||||
test_large_deflate(compr, comprLen, uncompr, uncomprLen);
|
||||
test_large_inflate(compr, comprLen, uncompr, uncomprLen);
|
||||
|
||||
free(compr);
|
||||
free(uncompr);
|
||||
|
||||
/* This function must return 0. */
|
||||
return 0;
|
||||
}
|
||||
124
libs/zlibng/test/fuzz/example_small_fuzzer.c
Normal file
124
libs/zlibng/test/fuzz/example_small_fuzzer.c
Normal file
@ -0,0 +1,124 @@
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "zbuild.h"
|
||||
#ifdef ZLIB_COMPAT
|
||||
# include "zlib.h"
|
||||
#else
|
||||
# include "zlib-ng.h"
|
||||
#endif
|
||||
|
||||
#define CHECK_ERR(err, msg) { \
|
||||
if (err != Z_OK) { \
|
||||
fprintf(stderr, "%s error: %d\n", msg, err); \
|
||||
exit(1); \
|
||||
} \
|
||||
}
|
||||
|
||||
static const uint8_t *data;
|
||||
static size_t dataLen;
|
||||
static alloc_func zalloc = NULL;
|
||||
static free_func zfree = NULL;
|
||||
|
||||
/* ===========================================================================
|
||||
* Test deflate() with small buffers
|
||||
*/
|
||||
void test_deflate(unsigned char *compr, size_t comprLen) {
|
||||
PREFIX3(stream) c_stream; /* compression stream */
|
||||
int err;
|
||||
unsigned long len = dataLen;
|
||||
|
||||
c_stream.zalloc = zalloc;
|
||||
c_stream.zfree = zfree;
|
||||
c_stream.opaque = (void *)0;
|
||||
|
||||
err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION);
|
||||
CHECK_ERR(err, "deflateInit");
|
||||
|
||||
c_stream.next_in = (const unsigned char *)data;
|
||||
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 = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
|
||||
CHECK_ERR(err, "deflate small 1");
|
||||
}
|
||||
/* Finish the stream, still forcing small buffers: */
|
||||
for (;;) {
|
||||
c_stream.avail_out = 1;
|
||||
err = PREFIX(deflate)(&c_stream, Z_FINISH);
|
||||
if (err == Z_STREAM_END)
|
||||
break;
|
||||
CHECK_ERR(err, "deflate small 2");
|
||||
}
|
||||
|
||||
err = PREFIX(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;
|
||||
PREFIX3(stream) d_stream; /* decompression stream */
|
||||
|
||||
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 = PREFIX(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 = PREFIX(inflate)(&d_stream, Z_NO_FLUSH);
|
||||
if (err == Z_STREAM_END)
|
||||
break;
|
||||
CHECK_ERR(err, "inflate");
|
||||
}
|
||||
|
||||
err = PREFIX(inflateEnd)(&d_stream);
|
||||
CHECK_ERR(err, "inflateEnd");
|
||||
|
||||
if (memcmp(uncompr, data, dataLen)) {
|
||||
fprintf(stderr, "bad inflate\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *d, size_t size) {
|
||||
size_t comprLen = PREFIX(compressBound)(size);
|
||||
size_t uncomprLen = size;
|
||||
uint8_t *compr, *uncompr;
|
||||
|
||||
/* Discard inputs larger than 1Mb. */
|
||||
static size_t kMaxSize = 1024 * 1024;
|
||||
|
||||
if (size < 1 || size > kMaxSize)
|
||||
return 0;
|
||||
|
||||
data = d;
|
||||
dataLen = size;
|
||||
compr = (uint8_t *)calloc(1, comprLen);
|
||||
uncompr = (uint8_t *)calloc(1, uncomprLen);
|
||||
|
||||
test_deflate(compr, comprLen);
|
||||
test_inflate(compr, comprLen, uncompr, uncomprLen);
|
||||
|
||||
free(compr);
|
||||
free(uncompr);
|
||||
|
||||
/* This function must return 0. */
|
||||
return 0;
|
||||
}
|
||||
326
libs/zlibng/test/fuzz/minigzip_fuzzer.c
Normal file
326
libs/zlibng/test/fuzz/minigzip_fuzzer.c
Normal file
@ -0,0 +1,326 @@
|
||||
/* minigzip.c -- simulate gzip using the zlib compression library
|
||||
* Copyright (C) 1995-2006, 2010, 2011, 2016 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 "zbuild.h"
|
||||
#ifdef ZLIB_COMPAT
|
||||
# include "zlib.h"
|
||||
#else
|
||||
# include "zlib-ng.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef USE_MMAP
|
||||
# include <sys/types.h>
|
||||
# include <sys/mman.h>
|
||||
# include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#ifndef UNALIGNED_OK
|
||||
# include <malloc.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
|
||||
|
||||
static 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
|
||||
/* Clear out the contents of buf before reading from the file to avoid
|
||||
MemorySanitizer: use-of-uninitialized-value warnings. */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
for (;;) {
|
||||
len = (int)fread(buf, 1, sizeof(buf), in);
|
||||
if (ferror(in)) {
|
||||
perror("fread");
|
||||
exit(1);
|
||||
}
|
||||
if (len == 0) break;
|
||||
|
||||
if (PREFIX(gzwrite)(out, buf, (unsigned)len) != len) error(PREFIX(gzerror)(out, &err));
|
||||
}
|
||||
fclose(in);
|
||||
if (PREFIX(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 = PREFIX(gzwrite)(out, (char *)buf, (unsigned)buf_len);
|
||||
|
||||
if (len != (int)buf_len) error(PREFIX(gzerror)(out, &err));
|
||||
|
||||
munmap(buf, buf_len);
|
||||
fclose(in);
|
||||
if (PREFIX(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 = PREFIX(gzread)(in, buf, sizeof(buf));
|
||||
if (len < 0) error (PREFIX(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 (PREFIX(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 = PREFIX(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 = PREFIX(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);
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataLen) {
|
||||
char *inFileName = "/tmp/minigzip_fuzzer.out";
|
||||
char *outFileName = "/tmp/minigzip_fuzzer.out.gz";
|
||||
char outmode[20];
|
||||
FILE *in;
|
||||
char buf[BUFLEN];
|
||||
uint32_t offset = 0;
|
||||
|
||||
/* Discard inputs larger than 1Mb. */
|
||||
static size_t kMaxSize = 1024 * 1024;
|
||||
if (dataLen < 1 || dataLen > kMaxSize)
|
||||
return 0;
|
||||
|
||||
in = fopen(inFileName, "w");
|
||||
if (fwrite(data, 1, (unsigned)dataLen, in) != dataLen)
|
||||
error("failed fwrite");
|
||||
if (fclose(in))
|
||||
error("failed fclose");
|
||||
|
||||
memset(outmode, 0, sizeof(outmode));
|
||||
snprintf(outmode, sizeof(outmode), "%s", "wb");
|
||||
|
||||
/* Compression level: [0..9]. */
|
||||
outmode[2] = data[0] % 10;
|
||||
|
||||
switch (data[0] % 4) {
|
||||
default:
|
||||
case 0:
|
||||
outmode[3] = 0;
|
||||
break;
|
||||
case 1:
|
||||
/* compress with Z_FILTERED */
|
||||
outmode[3] = 'f';
|
||||
break;
|
||||
case 2:
|
||||
/* compress with Z_HUFFMAN_ONLY */
|
||||
outmode[3] = 'h';
|
||||
break;
|
||||
case 3:
|
||||
/* compress with Z_RLE */
|
||||
outmode[3] = 'R';
|
||||
break;
|
||||
}
|
||||
|
||||
file_compress(inFileName, outmode);
|
||||
file_uncompress(outFileName);
|
||||
|
||||
/* Check that the uncompressed file matches the input data. */
|
||||
in = fopen(inFileName, "rb");
|
||||
if (in == NULL) {
|
||||
perror(inFileName);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
for (;;) {
|
||||
int len = (int)fread(buf, 1, sizeof(buf), in);
|
||||
if (ferror(in)) {
|
||||
perror("fread");
|
||||
exit(1);
|
||||
}
|
||||
if (len == 0)
|
||||
break;
|
||||
assert(0 == memcmp(data + offset, buf, len));
|
||||
offset += len;
|
||||
}
|
||||
|
||||
if (fclose(in))
|
||||
error("failed fclose");
|
||||
|
||||
/* This function must return 0. */
|
||||
return 0;
|
||||
}
|
||||
35
libs/zlibng/test/fuzz/standalone_fuzz_target_runner.c
Normal file
35
libs/zlibng/test/fuzz/standalone_fuzz_target_runner.c
Normal file
@ -0,0 +1,35 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int i;
|
||||
fprintf(stderr, "StandaloneFuzzTargetMain: running %d inputs\n", argc - 1);
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
size_t len, n_read, err;
|
||||
unsigned char *buf;
|
||||
FILE *f = fopen(argv[i], "rb+");
|
||||
if (!f) {
|
||||
/* Failed to open this file: it may be a directory. */
|
||||
fprintf(stderr, "Skipping: %s\n", argv[i]);
|
||||
continue;
|
||||
}
|
||||
fprintf(stderr, "Running: %s %s\n", argv[0], argv[i]);
|
||||
fseek(f, 0, SEEK_END);
|
||||
len = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
buf = (unsigned char *)malloc(len);
|
||||
n_read = fread(buf, 1, len, f);
|
||||
assert(n_read == len);
|
||||
LLVMFuzzerTestOneInput(buf, len);
|
||||
free(buf);
|
||||
err = fclose(f);
|
||||
assert(err == 0);
|
||||
fprintf(stderr, "Done: %s: (%d bytes)\n", argv[i], (int)n_read);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
669
libs/zlibng/test/infcover.c
Normal file
669
libs/zlibng/test/infcover.c
Normal file
@ -0,0 +1,669 @@
|
||||
/* infcover.c -- test zlib's inflate routines with full code coverage
|
||||
* Copyright (C) 2011, 2016 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 "zbuild.h"
|
||||
#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 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 = NULL;
|
||||
strm->zalloc = NULL;
|
||||
strm->zfree = 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 = 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 = 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, 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 = 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 = 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(NULL, 0); assert(ret == Z_STREAM_ERROR);
|
||||
ret = inflateEnd(NULL); assert(ret == Z_STREAM_ERROR);
|
||||
ret = inflateCopy(NULL, 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 = 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 == NULL) {
|
||||
next = 0;
|
||||
return 0; /* no input (already provided at next_in) */
|
||||
}
|
||||
state = (void *)((z_stream *)desc)->state;
|
||||
if (state != 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 != 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_(NULL, 0, win, 0, 0);
|
||||
assert(ret == Z_VERSION_ERROR);
|
||||
ret = inflateBackInit(NULL, 0, win); assert(ret == Z_STREAM_ERROR);
|
||||
ret = inflateBack(NULL, NULL, NULL, NULL, NULL);
|
||||
assert(ret == Z_STREAM_ERROR);
|
||||
ret = inflateBackEnd(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, NULL, push, NULL);
|
||||
assert(ret == Z_STREAM_END);
|
||||
/* force output error */
|
||||
strm.avail_in = 3;
|
||||
strm.next_in = (void *)"\x63\x00";
|
||||
ret = inflateBack(&strm, pull, NULL, push, &strm);
|
||||
assert(ret == Z_BUF_ERROR);
|
||||
/* force mode error by mucking with state */
|
||||
ret = inflateBack(&strm, pull, &strm, push, 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 = 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, NULL, push, 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;
|
||||
}
|
||||
361
libs/zlibng/test/minigzip.c
Normal file
361
libs/zlibng/test/minigzip.c
Normal file
@ -0,0 +1,361 @@
|
||||
/* minigzip.c -- simulate gzip using the zlib compression library
|
||||
* Copyright (C) 1995-2006, 2010, 2011, 2016 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$ */
|
||||
|
||||
#define _POSIX_SOURCE 1 /* This file needs POSIX for fdopen(). */
|
||||
#define _POSIX_C_SOURCE 200112 /* For snprintf(). */
|
||||
|
||||
#include "zbuild.h"
|
||||
#ifdef ZLIB_COMPAT
|
||||
# include "zlib.h"
|
||||
#else
|
||||
# include "zlib-ng.h"
|
||||
#endif
|
||||
#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
|
||||
|
||||
#ifndef UNALIGNED_OK
|
||||
# include <malloc.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)
|
||||
|
||||
#if defined(S390_DFLTCC_DEFLATE) || defined(S390_DFLTCC_INFLATE)
|
||||
#define BUFLEN 262144 /* DFLTCC works faster with larger buffers */
|
||||
#else
|
||||
#define BUFLEN 16384 /* read buffer size */
|
||||
#endif
|
||||
#define BUFLENW (BUFLEN * 3) /* write buffer size */
|
||||
#define MAX_NAME_LEN 1024
|
||||
|
||||
static 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
|
||||
/* Clear out the contents of buf before reading from the file to avoid
|
||||
MemorySanitizer: use-of-uninitialized-value warnings. */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
for (;;) {
|
||||
len = (int)fread(buf, 1, sizeof(buf), in);
|
||||
if (ferror(in)) {
|
||||
perror("fread");
|
||||
exit(1);
|
||||
}
|
||||
if (len == 0) break;
|
||||
|
||||
if (PREFIX(gzwrite)(out, buf, (unsigned)len) != len) error(PREFIX(gzerror)(out, &err));
|
||||
}
|
||||
fclose(in);
|
||||
if (PREFIX(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 = PREFIX(gzwrite)(out, (char *)buf, (unsigned)buf_len);
|
||||
|
||||
if (len != (int)buf_len) error(PREFIX(gzerror)(out, &err));
|
||||
|
||||
munmap(buf, buf_len);
|
||||
fclose(in);
|
||||
if (PREFIX(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 = PREFIX(gzread)(in, buf, sizeof(buf));
|
||||
if (len < 0) error (PREFIX(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 (PREFIX(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 = PREFIX(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 = PREFIX(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
|
||||
* -0 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] >= '0' && (*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 = PREFIX(gzdopen)(fileno(stdin), "rb");
|
||||
if (file == NULL) error("can't gzdopen stdin");
|
||||
gz_uncompress(file, stdout);
|
||||
} else {
|
||||
file = PREFIX(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 = PREFIX(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 = PREFIX(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;
|
||||
}
|
||||
31
libs/zlibng/test/testCVEinputs.sh
Normal file
31
libs/zlibng/test/testCVEinputs.sh
Normal file
@ -0,0 +1,31 @@
|
||||
#!/bin/bash
|
||||
TESTDIR="$(dirname "$0")"
|
||||
|
||||
# check for QEMU if QEMU_RUN is set
|
||||
if [ ! -z "${QEMU_RUN}" ]; then
|
||||
QEMU_VERSION=$(${QEMU_RUN} --version 2> /dev/null)
|
||||
if [ -z "${QEMU_VERSION}" ]; then
|
||||
echo "**** You need QEMU to run tests on non-native platform"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
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
|
||||
${QEMU_RUN} ../minigzip${EXE} -d < "$testcase"
|
||||
# we expect that a 1 error code is OK
|
||||
# for a vulnerable failure we'd expect 134 or similar
|
||||
if [ $? -ne 1 ] && [ $? -ne 0 ]; 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
libs/zlibng/treebuild.xml
Normal file
116
libs/zlibng/treebuild.xml
Normal file
@ -0,0 +1,116 @@
|
||||
<?xml version="1.0" ?>
|
||||
<package name="zlib" version="1.2.11">
|
||||
<library name="zlib" dlversion="1.2.11" 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 -DZLIB_DEBUG
|
||||
#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
|
||||
-->
|
||||
1086
libs/zlibng/trees.c
Normal file
1086
libs/zlibng/trees.c
Normal file
File diff suppressed because it is too large
Load Diff
132
libs/zlibng/trees.h
Normal file
132
libs/zlibng/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}}
|
||||
};
|
||||
|
||||
static 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
|
||||
};
|
||||
|
||||
static 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
|
||||
};
|
||||
|
||||
static 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_ */
|
||||
89
libs/zlibng/uncompr.c
Normal file
89
libs/zlibng/uncompr.c
Normal file
@ -0,0 +1,89 @@
|
||||
/* uncompr.c -- decompress a memory buffer
|
||||
* Copyright (C) 1995-2003, 2010, 2014, 2016 Jean-loup Gailly, Mark Adler.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include "zbuild.h"
|
||||
#ifdef ZLIB_COMPAT
|
||||
# include "zlib.h"
|
||||
#else
|
||||
# include "zlib-ng.h"
|
||||
#endif
|
||||
|
||||
/* ===========================================================================
|
||||
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 size of the decompressed data and *sourceLen is the number
|
||||
of source bytes consumed. Upon return, source + *sourceLen points to the
|
||||
first unused input byte.
|
||||
|
||||
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 PREFIX(uncompress2)(unsigned char *dest, z_size_t *destLen, const unsigned char *source, z_size_t *sourceLen) {
|
||||
PREFIX3(stream) stream;
|
||||
int err;
|
||||
const unsigned int max = (unsigned int)-1;
|
||||
z_size_t len, left;
|
||||
unsigned char buf[1]; /* for detection of incomplete stream when *destLen == 0 */
|
||||
|
||||
len = *sourceLen;
|
||||
if (*destLen) {
|
||||
left = *destLen;
|
||||
*destLen = 0;
|
||||
}
|
||||
else {
|
||||
left = 1;
|
||||
dest = buf;
|
||||
}
|
||||
|
||||
stream.next_in = (const unsigned char *)source;
|
||||
stream.avail_in = 0;
|
||||
stream.zalloc = NULL;
|
||||
stream.zfree = NULL;
|
||||
stream.opaque = NULL;
|
||||
|
||||
err = PREFIX(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 = len > (unsigned long)max ? max : (unsigned int)len;
|
||||
len -= stream.avail_in;
|
||||
}
|
||||
err = PREFIX(inflate)(&stream, Z_NO_FLUSH);
|
||||
} while (err == Z_OK);
|
||||
|
||||
*sourceLen -= len + stream.avail_in;
|
||||
if (dest != buf)
|
||||
*destLen = (z_size_t)stream.total_out;
|
||||
else if (stream.total_out && err == Z_BUF_ERROR)
|
||||
left = 1;
|
||||
|
||||
PREFIX(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;
|
||||
}
|
||||
|
||||
int ZEXPORT PREFIX(uncompress)(unsigned char *dest, z_size_t *destLen, const unsigned char *source, z_size_t sourceLen)
|
||||
{
|
||||
return PREFIX(uncompress2)(dest, destLen, source, &sourceLen);
|
||||
}
|
||||
397
libs/zlibng/win32/DLL_FAQ.txt
Normal file
397
libs/zlibng/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>
|
||||
170
libs/zlibng/win32/Makefile.arm
Normal file
170
libs/zlibng/win32/Makefile.arm
Normal file
@ -0,0 +1,170 @@
|
||||
# Makefile for zlib using Microsoft (Visual) C
|
||||
# zlib is copyright (C) 1995-2006 Jean-loup Gailly and Mark Adler
|
||||
#
|
||||
# Usage:
|
||||
# nmake -f win32/Makefile.arm (standard build)
|
||||
# nmake -f win32/Makefile.arm 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 -DUNALIGNED_OK -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1
|
||||
LDFLAGS = -nologo -debug -incremental:no -opt:ref -manifest
|
||||
ARFLAGS = -nologo
|
||||
RCFLAGS = /dARM /r
|
||||
DEFFILE = zlib.def
|
||||
RCFILE = zlib1.rc
|
||||
RESFILE = zlib1.res
|
||||
WITH_GZFILEOP =
|
||||
WITH_ACLE =
|
||||
WITH_NEON =
|
||||
WITH_VFPV3 =
|
||||
NEON_ARCH = /arch:VFPv4
|
||||
SUFFIX =
|
||||
|
||||
OBJS = adler32.obj armfeature.obj compress.obj crc32.obj deflate.obj deflate_fast.obj deflate_slow.obj \
|
||||
deflate_medium.obj \
|
||||
functable.obj infback.obj inflate.obj inftrees.obj inffast.obj trees.obj uncompr.obj zutil.obj fill_window_arm.obj
|
||||
!if "$(WITH_GZFILEOP)" != ""
|
||||
WFLAGS = $(WFLAGS) -DWITH_GZFILEOP
|
||||
OBJS = $(OBJS) gzclose.obj gzlib.obj gzread.obj gzwrite.obj
|
||||
DEFFILE = zlibcompat.def
|
||||
!else
|
||||
STATICLIB = zlib-ng.lib
|
||||
SHAREDLIB = zlib-ng1.dll
|
||||
IMPLIB = zngdll.lib
|
||||
DEFFILE = zlib-ng.def
|
||||
RCFILE = zlib-ng1.rc
|
||||
RESFILE = zlib-ng1.res
|
||||
SUFFIX = -ng
|
||||
!endif
|
||||
!if "$(WITH_ACLE)" != ""
|
||||
WFLAGS = $(WFLAGS) -DARM_ACLE_CRC_HASH
|
||||
OBJS = $(OBJS) crc32_acle.obj insert_string_acle.obj
|
||||
!endif
|
||||
!if "$(WITH_VFPV3)" != ""
|
||||
NEON_ARCH = /arch:VFPv3
|
||||
!endif
|
||||
!if "$(WITH_NEON)" != ""
|
||||
CFLAGS = $(CFLAGS) $(NEON_ARCH)
|
||||
WFLAGS = $(WFLAGS) -D__ARM_NEON__=1 -DARM_NEON_ADLER32 -DARM_NOCHECK_NEON
|
||||
OBJS = $(OBJS) adler32_neon.obj
|
||||
!endif
|
||||
|
||||
# targets
|
||||
all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \
|
||||
example.exe minigzip.exe example_d.exe minigzip_d.exe
|
||||
|
||||
zconf: $(TOP)/zconf$(SUFFIX).h.in
|
||||
$(CP) $(TOP)\zconf$(SUFFIX).h.in $(TOP)\zconf$(SUFFIX).h
|
||||
|
||||
$(STATICLIB): zconf $(OBJS)
|
||||
$(AR) $(ARFLAGS) -out:$@ $(OBJS)
|
||||
|
||||
$(IMPLIB): $(SHAREDLIB)
|
||||
|
||||
$(SHAREDLIB): zconf $(TOP)/win32/$(DEFFILE) $(OBJS) $(RESFILE)
|
||||
$(LD) $(LDFLAGS) -def:$(TOP)/win32/$(DEFFILE) -dll -implib:$(IMPLIB) \
|
||||
-out:$@ -base:0x5A4C0000 $(OBJS) $(RESFILE)
|
||||
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/arm}.c.obj:
|
||||
$(CC) -c -I$(TOP) $(WFLAGS) $(CFLAGS) $<
|
||||
|
||||
{$(TOP)/test}.c.obj:
|
||||
$(CC) -c -I$(TOP) $(WFLAGS) $(CFLAGS) $<
|
||||
|
||||
$(TOP)/zconf$(SUFFIX).h: zconf
|
||||
|
||||
SRCDIR = $(TOP)
|
||||
# Keep the dependences in sync with top-level Makefile.in
|
||||
adler32.obj: $(SRCDIR)/adler32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/functable.h $(SRCDIR)/adler32_p.h
|
||||
functable.obj: $(SRCDIR)/functable.c $(SRCDIR)/zbuild.h $(SRCDIR)/functable.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/gzendian.h $(SRCDIR)/arch/x86/x86.h
|
||||
gzclose.obj: $(SRCDIR)/gzclose.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h
|
||||
gzlib.obj: $(SRCDIR)/gzlib.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h
|
||||
gzread.obj: $(SRCDIR)/gzread.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h
|
||||
gzwrite.obj: $(SRCDIR)/gzwrite.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h
|
||||
compress.obj: $(SRCDIR)/compress.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h
|
||||
uncompr.obj: $(SRCDIR)/uncompr.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h
|
||||
crc32.obj: $(SRCDIR)/crc32.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzendian.h $(SRCDIR)/deflate.h $(SRCDIR)/functable.h $(SRCDIR)/crc32.h
|
||||
deflate.obj: $(SRCDIR)/deflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h
|
||||
deflate_fast.obj: $(SRCDIR)/deflate_fast.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/match_p.h $(SRCDIR)/functable.h
|
||||
deflate_medium.obj: $(SRCDIR)/deflate_medium.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/match_p.h $(SRCDIR)/functable.h
|
||||
deflate_slow.obj: $(SRCDIR)/deflate_slow.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/match_p.h $(SRCDIR)/functable.h
|
||||
infback.obj: $(SRCDIR)/infback.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h
|
||||
inffast.obj: $(SRCDIR)/inffast.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/memcopy.h
|
||||
inflate.obj: $(SRCDIR)/inflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/memcopy.h $(SRCDIR)/functable.h
|
||||
inftrees.obj: $(SRCDIR)/inftrees.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h
|
||||
trees.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/trees.h
|
||||
zutil.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/gzguts.h
|
||||
|
||||
example.obj: $(TOP)/test/example.c $(TOP)/zbuild.h $(TOP)/zlib$(SUFFIX).h
|
||||
|
||||
minigzip.obj: $(TOP)/test/minigzip.c $(TOP)/zbuild.h $(TOP)/zlib$(SUFFIX).h
|
||||
|
||||
$(RESFILE): $(TOP)/win32/$(RCFILE)
|
||||
$(RC) $(RCFLAGS) /fo$@ $(TOP)/win32/$(RCFILE)
|
||||
|
||||
# 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
|
||||
|
||||
distclean: clean
|
||||
-del zconf$(SUFFIX).h
|
||||
162
libs/zlibng/win32/Makefile.msc
Normal file
162
libs/zlibng/win32/Makefile.msc
Normal file
@ -0,0 +1,162 @@
|
||||
# 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 -DX86_CPUID -DX86_SSE4_2_CRC_HASH -DUNALIGNED_OK -DX86_QUICK_STRATEGY
|
||||
LDFLAGS = -nologo -debug -incremental:no -opt:ref -manifest
|
||||
ARFLAGS = -nologo
|
||||
RCFLAGS = /dWIN32 /r
|
||||
DEFFILE = zlib.def
|
||||
RCFILE = zlib1.rc
|
||||
RESFILE = zlib1.res
|
||||
WITH_GZFILEOP =
|
||||
ZLIB_COMPAT =
|
||||
SUFFIX =
|
||||
|
||||
OBJS = adler32.obj compress.obj crc32.obj deflate.obj deflate_fast.obj deflate_quick.obj deflate_slow.obj \
|
||||
deflate_medium.obj \
|
||||
functable.obj infback.obj inflate.obj inftrees.obj inffast.obj trees.obj uncompr.obj zutil.obj \
|
||||
x86.obj fill_window_sse.obj insert_string_sse.obj crc_folding.obj
|
||||
!if "$(ZLIB_COMPAT)" != ""
|
||||
WITH_GZFILEOP = yes
|
||||
WFLAGS = $(WFLAGS) -DZLIB_COMPAT
|
||||
DEFFILE = zlibcompat.def
|
||||
!else
|
||||
STATICLIB = zlib-ng.lib
|
||||
SHAREDLIB = zlib-ng1.dll
|
||||
IMPLIB = zngdll.lib
|
||||
DEFFILE = zlib-ng.def
|
||||
RCFILE = zlib-ng1.rc
|
||||
RESFILE = zlib-ng1.res
|
||||
SUFFIX = -ng
|
||||
!endif
|
||||
|
||||
!if "$(WITH_GZFILEOP)" != ""
|
||||
WFLAGS = $(WFLAGS) -DWITH_GZFILEOP
|
||||
OBJS = $(OBJS) gzclose.obj gzlib.obj gzread.obj gzwrite.obj
|
||||
!endif
|
||||
|
||||
# targets
|
||||
all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \
|
||||
example.exe minigzip.exe example_d.exe minigzip_d.exe
|
||||
|
||||
zconf: $(TOP)/zconf$(SUFFIX).h.in
|
||||
$(CP) $(TOP)\zconf$(SUFFIX).h.in $(TOP)\zconf$(SUFFIX).h
|
||||
|
||||
$(STATICLIB): zconf $(OBJS)
|
||||
$(AR) $(ARFLAGS) -out:$@ $(OBJS)
|
||||
|
||||
$(IMPLIB): $(SHAREDLIB)
|
||||
|
||||
$(SHAREDLIB): zconf $(TOP)/win32/$(DEFFILE) $(OBJS) $(RESFILE)
|
||||
$(LD) $(LDFLAGS) -def:$(TOP)/win32/$(DEFFILE) -dll -implib:$(IMPLIB) \
|
||||
-out:$@ -base:0x5A4C0000 $(OBJS) $(RESFILE)
|
||||
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$(SUFFIX).h: zconf
|
||||
|
||||
SRCDIR = $(TOP)
|
||||
# Keep the dependences in sync with top-level Makefile.in
|
||||
adler32.obj: $(SRCDIR)/adler32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/functable.h $(SRCDIR)/adler32_p.h
|
||||
functable.obj: $(SRCDIR)/functable.c $(SRCDIR)/zbuild.h $(SRCDIR)/functable.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/gzendian.h $(SRCDIR)/arch/x86/x86.h
|
||||
gzclose.obj: $(SRCDIR)/gzclose.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h
|
||||
gzlib.obj: $(SRCDIR)/gzlib.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h
|
||||
gzread.obj: $(SRCDIR)/gzread.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h
|
||||
gzwrite.obj: $(SRCDIR)/gzwrite.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h
|
||||
compress.obj: $(SRCDIR)/compress.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h
|
||||
uncompr.obj: $(SRCDIR)/uncompr.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h
|
||||
crc32.obj: $(SRCDIR)/crc32.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzendian.h $(SRCDIR)/deflate.h $(SRCDIR)/functable.h $(SRCDIR)/crc32.h
|
||||
deflate.obj: $(SRCDIR)/deflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h
|
||||
deflate_fast.obj: $(SRCDIR)/deflate_fast.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/match_p.h $(SRCDIR)/functable.h
|
||||
deflate_medium.obj: $(SRCDIR)/deflate_medium.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/match_p.h $(SRCDIR)/functable.h
|
||||
deflate_quick.obj: $(SRCDIR)/arch/x86/deflate_quick.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/memcopy.h
|
||||
deflate_slow.obj: $(SRCDIR)/deflate_slow.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/match_p.h $(SRCDIR)/functable.h
|
||||
infback.obj: $(SRCDIR)/infback.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h
|
||||
inffast.obj: $(SRCDIR)/inffast.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/memcopy.h
|
||||
inflate.obj: $(SRCDIR)/inflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/memcopy.h $(SRCDIR)/functable.h
|
||||
inftrees.obj: $(SRCDIR)/inftrees.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h
|
||||
trees.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/trees.h
|
||||
zutil.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/gzguts.h
|
||||
|
||||
example.obj: $(TOP)/test/example.c $(TOP)/zbuild.h $(TOP)/zlib$(SUFFIX).h
|
||||
|
||||
minigzip.obj: $(TOP)/test/minigzip.c $(TOP)/zbuild.h $(TOP)/zlib$(SUFFIX).h
|
||||
|
||||
$(RESFILE): $(TOP)/win32/$(RCFILE)
|
||||
$(RC) $(RCFLAGS) /fo$@ $(TOP)/win32/$(RCFILE)
|
||||
|
||||
# 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
|
||||
|
||||
distclean: clean
|
||||
-del zconf$(SUFFIX).h
|
||||
103
libs/zlibng/win32/README-WIN32.txt
Normal file
103
libs/zlibng/win32/README-WIN32.txt
Normal file
@ -0,0 +1,103 @@
|
||||
ZLIB DATA COMPRESSION LIBRARY
|
||||
|
||||
zlib 1.2.11 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.11-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
libs/zlibng/win32/VisualC.txt
Normal file
3
libs/zlibng/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.
|
||||
61
libs/zlibng/win32/zlib-ng.def
Normal file
61
libs/zlibng/win32/zlib-ng.def
Normal file
@ -0,0 +1,61 @@
|
||||
; zlib-ng data compression library
|
||||
EXPORTS
|
||||
; basic functions
|
||||
zlibng_version
|
||||
zng_deflate
|
||||
zng_deflateEnd
|
||||
zng_inflate
|
||||
zng_inflateEnd
|
||||
; advanced functions
|
||||
zng_deflateSetDictionary
|
||||
zng_deflateGetDictionary
|
||||
zng_deflateCopy
|
||||
zng_deflateReset
|
||||
zng_deflateParams
|
||||
zng_deflateTune
|
||||
zng_deflateBound
|
||||
zng_deflatePending
|
||||
zng_deflatePrime
|
||||
zng_deflateSetHeader
|
||||
zng_inflateSetDictionary
|
||||
zng_inflateGetDictionary
|
||||
zng_inflateSync
|
||||
zng_inflateCopy
|
||||
zng_inflateReset
|
||||
zng_inflateReset2
|
||||
zng_inflatePrime
|
||||
zng_inflateMark
|
||||
zng_inflateGetHeader
|
||||
zng_inflateBack
|
||||
zng_inflateBackEnd
|
||||
zng_zlibCompileFlags
|
||||
; utility functions
|
||||
zng_compress
|
||||
zng_compress2
|
||||
zng_compressBound
|
||||
zng_uncompress
|
||||
zng_uncompress2
|
||||
; large file functions
|
||||
zng_adler32_combine64
|
||||
zng_crc32_combine64
|
||||
; checksum functions
|
||||
zng_adler32
|
||||
zng_adler32_z
|
||||
zng_crc32
|
||||
zng_crc32_z
|
||||
zng_adler32_combine
|
||||
zng_crc32_combine
|
||||
; various hacks, don't look :)
|
||||
zng_deflateInit_
|
||||
zng_deflateInit2_
|
||||
zng_inflateInit_
|
||||
zng_inflateInit2_
|
||||
zng_inflateBackInit_
|
||||
zng_zError
|
||||
zng_inflateSyncPoint
|
||||
zng_get_crc_table
|
||||
zng_inflateUndermine
|
||||
zng_inflateValidate
|
||||
zng_inflateCodesUsed
|
||||
zng_inflateResetKeep
|
||||
zng_deflateResetKeep
|
||||
40
libs/zlibng/win32/zlib-ng1.rc
Normal file
40
libs/zlibng/win32/zlib-ng1.rc
Normal file
@ -0,0 +1,40 @@
|
||||
#include <winver.h>
|
||||
#include "../zlib-ng.h"
|
||||
|
||||
#ifdef GCC_WINDRES
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
#else
|
||||
VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
|
||||
#endif
|
||||
FILEVERSION ZLIBNG_VER_MAJOR,ZLIBNG_VER_MINOR,ZLIBNG_VER_REVISION,0
|
||||
PRODUCTVERSION ZLIBNG_VER_MAJOR,ZLIBNG_VER_MINOR,ZLIBNG_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", ZLIBNG_VERSION "\0"
|
||||
VALUE "InternalName", "zlib-ng1.dll\0"
|
||||
VALUE "LegalCopyright", "(C) 1995-2013 Jean-loup Gailly & Mark Adler\0"
|
||||
VALUE "OriginalFilename", "zlib-ng1.dll\0"
|
||||
VALUE "ProductName", "zlib\0"
|
||||
VALUE "ProductVersion", ZLIBNG_VERSION "\0"
|
||||
VALUE "Comments", "For more information visit http://www.zlib.net/\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0409, 1252
|
||||
END
|
||||
END
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user