summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2023-05-09 00:16:04 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-05-09 00:16:04 +0000
commitd833627b2f683531dd29cad185a8b564f6462ef1 (patch)
tree59cdbe61f3a48dcae45499b147c4fcfce1ff53c1
parentfa55db7eaafc85caa6a6a68e9a791f16eb056c10 (diff)
parent81774276a9cbf47177a1b7555bb6e3ec73bdcd25 (diff)
downloadzlib-d833627b2f683531dd29cad185a8b564f6462ef1.tar.gz
Merge "Upgrade zlib to b890619bc2b193b8fbe9c1c053f4cd19a9791d92" am: 81774276a9
Original change: https://android-review.googlesource.com/c/platform/external/zlib/+/2523495 Change-Id: Id2fced2d7301981aace68afd3d791b98a3defda8 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--BUILD.gn21
-rw-r--r--CMakeLists.txt277
-rw-r--r--METADATA6
-rw-r--r--contrib/optimizations/inffast_chunk.c71
-rw-r--r--contrib/optimizations/inffast_chunk.h26
-rw-r--r--contrib/tests/run_all_unittests.cc2
-rw-r--r--cpu_features.c9
-rw-r--r--cpu_features.h1
-rw-r--r--crc32.c14
-rw-r--r--crc32_simd.c198
-rw-r--r--crc32_simd.h6
-rw-r--r--google/BUILD.gn17
-rw-r--r--google/OWNERS2
-rw-r--r--google/test_data.filelist32
-rw-r--r--google/test_data.globlist8
-rw-r--r--google/zip.cc2
-rw-r--r--google/zip.h2
-rw-r--r--google/zip_reader.cc18
-rw-r--r--google/zip_reader.h2
-rw-r--r--google/zip_reader_unittest.cc2
-rw-r--r--google/zip_unittest.cc10
-rw-r--r--patches/0010-cmake-enable-simd.patch96
-rw-r--r--patches/0011-avx512.patch357
-rw-r--r--zconf.h.cmakein549
-rw-r--r--zlib.3149
-rw-r--r--zlib.map100
-rw-r--r--zlib.pc.cmakein13
27 files changed, 1879 insertions, 111 deletions
diff --git a/BUILD.gn b/BUILD.gn
index b85067a..0ffd486 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -4,6 +4,12 @@
import("//build/config/compiler/compiler.gni")
+declare_args() {
+ # Expose zlib's symbols, used by Node.js to provide zlib APIs for its native
+ # modules.
+ zlib_symbols_visible = false
+}
+
if (build_with_chromium) {
import("//testing/test.gni")
}
@@ -14,6 +20,10 @@ if (current_cpu == "arm" || current_cpu == "arm64") {
config("zlib_config") {
include_dirs = [ "." ]
+
+ if (zlib_symbols_visible) {
+ defines = [ "ZLIB_DLL" ]
+ }
}
config("zlib_internal_config") {
@@ -23,7 +33,7 @@ config("zlib_internal_config") {
# Build code using -O3, see: crbug.com/1084371.
configs = [ "//build/config/compiler:optimize_speed" ]
}
- if (is_debug || use_libfuzzer) {
+ if (is_debug || use_fuzzing_engine) {
# Enable zlib's asserts in debug and fuzzer builds.
defines += [ "ZLIB_DEBUG" ]
}
@@ -358,6 +368,11 @@ component("zlib") {
configs -= [ "//build/config/compiler:chromium_code" ]
configs += [ "//build/config/compiler:no_chromium_code" ]
+ if (zlib_symbols_visible) {
+ configs -= [ "//build/config/gcc:symbol_visibility_hidden" ]
+ configs += [ "//build/config/gcc:symbol_visibility_default" ]
+ }
+
public_configs = [ ":zlib_config" ]
configs += [
@@ -500,6 +515,10 @@ if (build_with_chromium) {
data = [ "google/test/data/" ]
+ if (is_ios) {
+ bundle_deps = [ "google:zlib_pak_bundle_data" ]
+ }
+
deps = [
":zlib",
"google:compression_utils",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8b1ce04..d45b902 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,59 +1,240 @@
-# Copyright 2021 The Android Open Source Project
+cmake_minimum_required(VERSION 3.0)
+set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
+
+project(zlib C)
+
+set(VERSION "1.2.13")
+
+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(CheckFunctionExists)
+include(CheckIncludeFile)
+include(CheckCSourceCompiles)
+enable_testing()
+
+check_include_file(sys/types.h HAVE_SYS_TYPES_H)
+check_include_file(stdint.h HAVE_STDINT_H)
+check_include_file(stddef.h HAVE_STDDEF_H)
+
+option(ENABLE_SIMD_OPTIMIZATIONS "Enable all SIMD optimizations" OFF)
+option(ENABLE_SIMD_AVX512 "Enable SIMD AXV512 optimizations" OFF)
+
+# TODO(cavalcantii): add support for other OSes (e.g. Android, fuchsia, osx)
+# and architectures (e.g. Arm).
+if (ENABLE_SIMD_OPTIMIZATIONS)
+ add_definitions(-DINFLATE_CHUNK_SIMD_SSE2)
+ add_definitions(-DADLER32_SIMD_SSSE3)
+ add_definitions(-DINFLATE_CHUNK_READ_64LE)
+ add_definitions(-DCRC32_SIMD_SSE42_PCLMUL)
+ if (ENABLE_SIMD_AVX512)
+ add_definitions(-DCRC32_SIMD_AVX512_PCLMUL)
+ add_compile_options(-mvpclmulqdq -msse2 -mavx512f -mpclmul)
+ else()
+ add_compile_options(-msse4.2 -mpclmul)
+ endif()
+ add_definitions(-DDEFLATE_SLIDE_HASH_SSE2)
+ # Required by CPU features detection code.
+ add_definitions(-DX86_NOT_WINDOWS)
+ # Apparently some environments (e.g. CentOS) require to explicitly link
+ # with pthread and that is required by the CPU features detection code.
+ find_package (Threads REQUIRED)
+ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread")
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
+endif()
+
+#
+# Check to see if we have large file support
#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
+set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1)
+# We add these other definitions here because CheckTypeSize.cmake
+# in CMake 2.4.x does not automatically do so and we want
+# compatibility with CMake 2.4.x.
+if(HAVE_SYS_TYPES_H)
+ list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H)
+endif()
+if(HAVE_STDINT_H)
+ list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H)
+endif()
+if(HAVE_STDDEF_H)
+ list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H)
+endif()
+check_type_size(off64_t OFF64_T)
+if(HAVE_OFF64_T)
+ add_definitions(-D_LARGEFILE64_SOURCE=1)
+endif()
+set(CMAKE_REQUIRED_DEFINITIONS) # clear variable
+
#
-# http://www.apache.org/licenses/LICENSE-2.0
+# Check for fseeko
#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+check_function_exists(fseeko HAVE_FSEEKO)
+if(NOT HAVE_FSEEKO)
+ add_definitions(-DNO_FSEEKO)
+endif()
#
-# Build zlib for Windows x86_64 using MSVC.
+# Check for unistd.h
#
+check_include_file(unistd.h Z_HAVE_UNISTD_H)
+
+if(MSVC)
+ set(CMAKE_DEBUG_POSTFIX "d")
+ add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
+ add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
+ include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+endif()
+
+if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
+ # If we're doing an out of source build and the user has a zconf.h
+ # in their source tree...
+ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h)
+ message(STATUS "Renaming")
+ message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h")
+ message(STATUS "to 'zconf.h.included' because this file is included with zlib")
+ message(STATUS "but CMake generates it automatically in the build directory.")
+ file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included)
+ endif()
+endif()
+
+set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc)
+configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein
+ ${ZLIB_PC} @ONLY)
+configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein
+ ${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY)
+include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR})
-project(libz LANGUAGES C)
-cmake_minimum_required(VERSION 3.18.1)
-
-add_library(libz STATIC
- # Optimizations for x86-64
- adler32_simd.c
- crc32_simd.c
- crc_folding.c
-
- # Common sources
- adler32.c
- compress.c
- cpu_features.c
- crc32.c
- deflate.c
- gzclose.c
- gzlib.c
- gzread.c
- gzwrite.c
- infback.c
- inffast.c
- inflate.c
- inftrees.c
- trees.c
- uncompr.c
- zutil.c
-)
-target_compile_definitions(libz PRIVATE
- # Enable optimizations: cpu_features.c will enable them at runtime using __cpuid.
- ADLER32_SIMD_SSSE3
- CRC32_SIMD_SSE42_PCLMUL
- INFLATE_CHUNK_READ_64LE
+#============================================================================
+# zlib
+#============================================================================
- X86_WINDOWS
- ZLIB_CONST
+set(ZLIB_PUBLIC_HDRS
+ ${CMAKE_CURRENT_BINARY_DIR}/zconf.h
+ zlib.h
)
+set(ZLIB_PRIVATE_HDRS
+ crc32.h
+ deflate.h
+ gzguts.h
+ inffast.h
+ inffixed.h
+ inflate.h
+ inftrees.h
+ trees.h
+ zutil.h
+)
+set(ZLIB_SRCS
+ adler32.c
+ compress.c
+ crc32.c
+ deflate.c
+ gzclose.c
+ gzlib.c
+ gzread.c
+ gzwrite.c
+ inflate.c
+ infback.c
+ inftrees.c
+ inffast.c
+ trees.c
+ uncompr.c
+ zutil.c
+)
+
+
+#============================================================================
+# Update list of source files if optimizations were enabled
+#============================================================================
+if (ENABLE_SIMD_OPTIMIZATIONS)
+ list(REMOVE_ITEM ZLIB_SRCS inflate.c)
+
+ list(APPEND ZLIB_PRIVATE_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/adler32_simd.h)
+ list(APPEND ZLIB_PRIVATE_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/contrib/optimizations/chunkcopy.h)
+ list(APPEND ZLIB_PRIVATE_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/contrib/optimizations/inffast_chunk.h)
+ list(APPEND ZLIB_PRIVATE_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/cpu_features.h)
+ list(APPEND ZLIB_PRIVATE_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/crc32_simd.h)
+
+ list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/adler32_simd.c)
+ list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/contrib/optimizations/inffast_chunk.c)
+ list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/contrib/optimizations/inflate.c)
+ list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/cpu_features.c)
+ list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/crc32_simd.c)
+ list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/crc_folding.c)
+endif()
+
+# parse the full version number from zlib.h and include in ZLIB_FULL_VERSION
+file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents)
+string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*"
+ "\\1" ZLIB_FULL_VERSION ${_zlib_h_contents})
+
+if(MINGW)
+ # This gets us DLL resource information when compiling on MinGW.
+ if(NOT CMAKE_RC_COMPILER)
+ set(CMAKE_RC_COMPILER windres.exe)
+ endif()
+
+ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
+ COMMAND ${CMAKE_RC_COMPILER}
+ -D GCC_WINDRES
+ -I ${CMAKE_CURRENT_SOURCE_DIR}
+ -I ${CMAKE_CURRENT_BINARY_DIR}
+ -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
+ -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc)
+ set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj)
+endif(MINGW)
+
+add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
+add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
+set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)
+set_target_properties(zlib PROPERTIES SOVERSION 1)
+
+if(NOT CYGWIN)
+ # This property causes shared libraries on Linux to have the full version
+ # encoded into their final filename. We disable this on Cygwin because
+ # it causes cygz-${ZLIB_FULL_VERSION}.dll to be created when cygz.dll
+ # seems to be the default.
+ #
+ # This has no effect with MSVC, on that platform the version info for
+ # the DLL comes from the resource file win32/zlib1.rc
+ set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION})
+endif()
+
+if(UNIX)
+ # On unix-like platforms the library is almost always called libz
+ set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z)
+ if(NOT APPLE)
+ set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"")
+ endif()
+elseif(BUILD_SHARED_LIBS AND WIN32)
+ # Creates zlib1.dll when building shared library version
+ set_target_properties(zlib PROPERTIES SUFFIX "1.dll")
+endif()
+
+if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL )
+ install(TARGETS zlib zlibstatic
+ RUNTIME DESTINATION "${INSTALL_BIN_DIR}"
+ ARCHIVE DESTINATION "${INSTALL_LIB_DIR}"
+ LIBRARY DESTINATION "${INSTALL_LIB_DIR}" )
+endif()
+if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL )
+ install(FILES ${ZLIB_PUBLIC_HDRS} DESTINATION "${INSTALL_INC_DIR}")
+endif()
+if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
+ install(FILES zlib.3 DESTINATION "${INSTALL_MAN_DIR}/man3")
+endif()
+if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
+ install(FILES ${ZLIB_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}")
+endif()
-set(out ${CMAKE_CURRENT_BINARY_DIR})
-configure_file(zconf.h ${out}/dist/include/zconf.h COPYONLY)
-configure_file(zlib.h ${out}/dist/include/zlib.h COPYONLY)
+#============================================================================
+# Benchmarker
+#============================================================================
+enable_language(CXX)
+set(CMAKE_CXX_STANDARD 14) # workaround for older compilers (e.g. g++ 5.4).
+add_executable(zlib_bench contrib/bench/zlib_bench.cc)
+target_link_libraries(zlib_bench zlib)
diff --git a/METADATA b/METADATA
index 7637670..8daadcd 100644
--- a/METADATA
+++ b/METADATA
@@ -9,11 +9,11 @@ third_party {
type: GIT
value: "https://chromium.googlesource.com/chromium/src/third_party/zlib/"
}
- version: "fa5dc4750029333c2486efa38eec7d13890108ed"
+ version: "b890619bc2b193b8fbe9c1c053f4cd19a9791d92"
license_type: NOTICE
last_upgrade_date {
year: 2023
- month: 1
- day: 9
+ month: 4
+ day: 4
}
}
diff --git a/contrib/optimizations/inffast_chunk.c b/contrib/optimizations/inffast_chunk.c
index 5b09487..a38e14d 100644
--- a/contrib/optimizations/inffast_chunk.c
+++ b/contrib/optimizations/inffast_chunk.c
@@ -1,5 +1,6 @@
/* inffast_chunk.c -- fast decoding
* Copyright (C) 1995-2017 Mark Adler
+ * Copyright 2023 The Chromium Authors
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -24,8 +25,8 @@
Entry assumptions:
state->mode == LEN
- strm->avail_in >= INFLATE_FAST_MIN_INPUT (6 or 8 bytes)
- strm->avail_out >= INFLATE_FAST_MIN_OUTPUT (258 bytes)
+ strm->avail_in >= INFLATE_FAST_MIN_INPUT (6 or 8 bytes + 7 bytes)
+ strm->avail_out >= INFLATE_FAST_MIN_OUTPUT (258 bytes + 2 bytes)
start >= strm->avail_out
state->bits < 8
(state->hold >> state->bits) == 0
@@ -42,7 +43,7 @@
Notes:
- INFLATE_FAST_MIN_INPUT: 6 or 8 bytes
+ INFLATE_FAST_MIN_INPUT: 6 or 8 bytes + 7 bytes
- 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,
@@ -64,11 +65,11 @@
(state->hold >> state->bits) == 0
- INFLATE_FAST_MIN_OUTPUT: 258 bytes
+ INFLATE_FAST_MIN_OUTPUT: 258 bytes + 2 bytes for literals = 260 bytes
- 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
+ requires strm->avail_out >= 260 for each loop to avoid checking for
available output space while decoding.
*/
void ZLIB_INTERNAL inflate_fast_chunk_(strm, start)
@@ -124,22 +125,50 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
lmask = (1U << state->lenbits) - 1;
dmask = (1U << state->distbits) - 1;
+#ifdef INFLATE_CHUNK_READ_64LE
+#define REFILL() do { \
+ Assert(bits < 64, "### Too many bits in inflate_fast."); \
+ hold |= read64le(in) << bits; \
+ in += 7; \
+ in -= bits >> 3; \
+ bits |= 56; \
+ } while (0)
+#endif
+
/* decode literals and length/distances until end-of-block or not enough
input data or output space */
do {
- if (bits < 15) {
#ifdef INFLATE_CHUNK_READ_64LE
- hold |= read64le(in) << bits;
- in += 6;
- bits += 48;
+ REFILL();
#else
+ if (bits < 15) {
hold += (unsigned long)(*in++) << bits;
bits += 8;
hold += (unsigned long)(*in++) << bits;
bits += 8;
-#endif
}
+#endif
here = lcode + (hold & lmask);
+#ifdef INFLATE_CHUNK_READ_64LE
+ if (here->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);
+ hold >>= here->bits;
+ bits -= here->bits;
+ here = lcode + (hold & lmask);
+ if (here->op == 0) { /* literal */
+ Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ?
+ "inflate: 2nd literal '%c'\n" :
+ "inflate: 2nd literal 0x%02x\n", here->val));
+ *out++ = (unsigned char)(here->val);
+ hold >>= here->bits;
+ bits -= here->bits;
+ here = lcode + (hold & lmask);
+ }
+ }
+#endif
dolen:
op = (unsigned)(here->bits);
hold >>= op;
@@ -155,33 +184,25 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
len = (unsigned)(here->val);
op &= 15; /* number of extra bits */
if (op) {
+#ifndef INFLATE_CHUNK_READ_64LE
if (bits < op) {
-#ifdef INFLATE_CHUNK_READ_64LE
- hold |= read64le(in) << bits;
- in += 6;
- bits += 48;
-#else
hold += (unsigned long)(*in++) << bits;
bits += 8;
-#endif
}
+#endif
len += (unsigned)hold & ((1U << op) - 1);
hold >>= op;
bits -= op;
}
Tracevv((stderr, "inflate: length %u\n", len));
+#ifndef INFLATE_CHUNK_READ_64LE
if (bits < 15) {
-#ifdef INFLATE_CHUNK_READ_64LE
- hold |= read64le(in) << bits;
- in += 6;
- bits += 48;
-#else
hold += (unsigned long)(*in++) << bits;
bits += 8;
hold += (unsigned long)(*in++) << bits;
bits += 8;
-#endif
}
+#endif
here = dcode + (hold & dmask);
dodist:
op = (unsigned)(here->bits);
@@ -191,11 +212,11 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
if (op & 16) { /* distance base */
dist = (unsigned)(here->val);
op &= 15; /* number of extra bits */
+ /* we have two fast-path loads: 10+10 + 15+5 + 15 = 55,
+ but we may need to refill here in the worst case */
if (bits < op) {
#ifdef INFLATE_CHUNK_READ_64LE
- hold |= read64le(in) << bits;
- in += 6;
- bits += 48;
+ REFILL();
#else
hold += (unsigned long)(*in++) << bits;
bits += 8;
diff --git a/contrib/optimizations/inffast_chunk.h b/contrib/optimizations/inffast_chunk.h
index 39c771b..cc861bd 100644
--- a/contrib/optimizations/inffast_chunk.h
+++ b/contrib/optimizations/inffast_chunk.h
@@ -1,6 +1,7 @@
/* inffast_chunk.h -- header to use inffast_chunk.c
* Copyright (C) 1995-2003, 2010 Mark Adler
* Copyright (C) 2017 ARM, Inc.
+ * Copyright 2023 The Chromium Authors
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -11,16 +12,31 @@
#include "inffast.h"
-/* INFLATE_FAST_MIN_INPUT: the minimum number of input bytes needed so that
- we can safely call inflate_fast() with only one up-front bounds check. One
+/* INFLATE_FAST_MIN_INPUT:
+ The minimum number of input bytes needed so that we can safely call
+ inflate_fast() with only one up-front bounds check. One
length/distance code pair (15 bits for the length code, 5 bits for length
extra, 15 bits for the distance code, 13 bits for distance extra) requires
- reading up to 48 input bits (6 bytes). The wide input data reading option
- requires a little endian machine, and reads 64 input bits (8 bytes).
+ reading up to 48 input bits. Additionally, in the same iteraction, we may
+ decode two literals from the root-table (requiring MIN_OUTPUT = 258 + 2).
+
+ Each root-table entry is up to 10 bits, for a total of 68 input bits each
+ iteraction.
+
+ The refill variant reads 8 bytes from the buffer at a time, and advances
+ the input pointer by up to 7 bytes, ensuring there are at least 56-bits
+ available in the bit-buffer. The technique was documented by Fabian Giesen
+ on his blog as variant 4 in the article 'Reading bits in far too many ways':
+ https://fgiesen.wordpress.com/2018/02/20/
+
+ In the worst case, we may refill twice in the same iteraction, requiring
+ MIN_INPUT = 8 + 7.
*/
#ifdef INFLATE_CHUNK_READ_64LE
#undef INFLATE_FAST_MIN_INPUT
-#define INFLATE_FAST_MIN_INPUT 8
+#define INFLATE_FAST_MIN_INPUT 15
+#undef INFLATE_FAST_MIN_OUTPUT
+#define INFLATE_FAST_MIN_OUTPUT 260
#endif
void ZLIB_INTERNAL inflate_fast_chunk_ OF((z_streamp strm, unsigned start));
diff --git a/contrib/tests/run_all_unittests.cc b/contrib/tests/run_all_unittests.cc
index af2ef5d..4b6115b 100644
--- a/contrib/tests/run_all_unittests.cc
+++ b/contrib/tests/run_all_unittests.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/bind.h"
+#include "base/functional/bind.h"
#include "base/test/launcher/unit_test_launcher.h"
#include "base/test/test_suite.h"
diff --git a/cpu_features.c b/cpu_features.c
index 877d5f2..ac6ee88 100644
--- a/cpu_features.c
+++ b/cpu_features.c
@@ -31,6 +31,7 @@ int ZLIB_INTERNAL arm_cpu_enable_pmull = 0;
int ZLIB_INTERNAL x86_cpu_enable_sse2 = 0;
int ZLIB_INTERNAL x86_cpu_enable_ssse3 = 0;
int ZLIB_INTERNAL x86_cpu_enable_simd = 0;
+int ZLIB_INTERNAL x86_cpu_enable_avx512 = 0;
#ifndef CPU_NO_SIMD
@@ -138,6 +139,10 @@ static void _cpu_check_features(void)
/* On x86 we simply use a instruction to check the CPU features.
* (i.e. CPUID).
*/
+#ifdef CRC32_SIMD_AVX512_PCLMUL
+#include <immintrin.h>
+#include <xsaveintrin.h>
+#endif
static void _cpu_check_features(void)
{
int x86_cpu_has_sse2;
@@ -164,6 +169,10 @@ static void _cpu_check_features(void)
x86_cpu_enable_simd = x86_cpu_has_sse2 &&
x86_cpu_has_sse42 &&
x86_cpu_has_pclmulqdq;
+
+#ifdef CRC32_SIMD_AVX512_PCLMUL
+ x86_cpu_enable_avx512 = _xgetbv(0) & 0x00000040;
+#endif
}
#endif
#endif
diff --git a/cpu_features.h b/cpu_features.h
index 279246c..aed3e83 100644
--- a/cpu_features.h
+++ b/cpu_features.h
@@ -14,5 +14,6 @@ extern int arm_cpu_enable_pmull;
extern int x86_cpu_enable_sse2;
extern int x86_cpu_enable_ssse3;
extern int x86_cpu_enable_simd;
+extern int x86_cpu_enable_avx512;
void cpu_check_features(void);
diff --git a/crc32.c b/crc32.c
index 4486098..acb6972 100644
--- a/crc32.c
+++ b/crc32.c
@@ -773,7 +773,19 @@ unsigned long ZEXPORT crc32_z(crc, buf, len)
}
#endif
-#if defined(CRC32_SIMD_SSE42_PCLMUL)
+#if defined(CRC32_SIMD_AVX512_PCLMUL)
+ if (x86_cpu_enable_avx512 && len >= Z_CRC32_AVX512_MINIMUM_LENGTH) {
+ /* crc32 64-byte chunks */
+ z_size_t chunk_size = len & ~Z_CRC32_AVX512_CHUNKSIZE_MASK;
+ crc = ~crc32_avx512_simd_(buf, chunk_size, ~(uint32_t)crc);
+ /* check remaining data */
+ len -= chunk_size;
+ if (!len)
+ return crc;
+ /* Fall into the default crc32 for the remaining data. */
+ buf += chunk_size;
+ }
+#elif defined(CRC32_SIMD_SSE42_PCLMUL)
if (x86_cpu_enable_simd && len >= Z_CRC32_SSE42_MINIMUM_LENGTH) {
/* crc32 16-byte chunks */
z_size_t chunk_size = len & ~Z_CRC32_SSE42_CHUNKSIZE_MASK;
diff --git a/crc32_simd.c b/crc32_simd.c
index d80beba..7428270 100644
--- a/crc32_simd.c
+++ b/crc32_simd.c
@@ -6,12 +6,11 @@
*/
#include "crc32_simd.h"
-
-#if defined(CRC32_SIMD_SSE42_PCLMUL)
+#if defined(CRC32_SIMD_AVX512_PCLMUL)
/*
- * crc32_sse42_simd_(): compute the crc32 of the buffer, where the buffer
- * length must be at least 64, and a multiple of 16. Based on:
+ * crc32_avx512_simd_(): compute the crc32 of the buffer, where the buffer
+ * length must be at least 256, and a multiple of 64. Based on:
*
* "Fast CRC Computation for Generic Polynomials Using PCLMULQDQ Instruction"
* V. Gopal, E. Ozturk, et al., 2009, http://intel.ly/2ySEwL0
@@ -20,6 +19,197 @@
#include <emmintrin.h>
#include <smmintrin.h>
#include <wmmintrin.h>
+#include <immintrin.h>
+
+uint32_t ZLIB_INTERNAL crc32_avx512_simd_( /* AVX512+PCLMUL */
+ const unsigned char *buf,
+ z_size_t len,
+ uint32_t crc)
+{
+ /*
+ * Definitions of the bit-reflected domain constants k1,k2,k3,k4
+ * are similar to those given at the end of the paper, and remaining
+ * constants and CRC32+Barrett polynomials remain unchanged.
+ *
+ * Replace the index of x from 128 to 512. As follows:
+ * k1 = ( x ^ ( 512 * 4 + 32 ) mod P(x) << 32 )' << 1 = 0x011542778a
+ * k2 = ( x ^ ( 512 * 4 - 32 ) mod P(x) << 32 )' << 1 = 0x01322d1430
+ * k3 = ( x ^ ( 512 + 32 ) mod P(x) << 32 )' << 1 = 0x0154442bd4
+ * k4 = ( x ^ ( 512 - 32 ) mod P(x) << 32 )' << 1 = 0x01c6e41596
+ */
+ static const uint64_t zalign(64) k1k2[] = { 0x011542778a, 0x01322d1430,
+ 0x011542778a, 0x01322d1430,
+ 0x011542778a, 0x01322d1430,
+ 0x011542778a, 0x01322d1430 };
+ static const uint64_t zalign(64) k3k4[] = { 0x0154442bd4, 0x01c6e41596,
+ 0x0154442bd4, 0x01c6e41596,
+ 0x0154442bd4, 0x01c6e41596,
+ 0x0154442bd4, 0x01c6e41596 };
+ static const uint64_t zalign(16) k5k6[] = { 0x01751997d0, 0x00ccaa009e };
+ static const uint64_t zalign(16) k7k8[] = { 0x0163cd6124, 0x0000000000 };
+ static const uint64_t zalign(16) poly[] = { 0x01db710641, 0x01f7011641 };
+ __m512i x0, x1, x2, x3, x4, x5, x6, x7, x8, y5, y6, y7, y8;
+ __m128i a0, a1, a2, a3;
+
+ /*
+ * There's at least one block of 256.
+ */
+ x1 = _mm512_loadu_si512((__m512i *)(buf + 0x00));
+ x2 = _mm512_loadu_si512((__m512i *)(buf + 0x40));
+ x3 = _mm512_loadu_si512((__m512i *)(buf + 0x80));
+ x4 = _mm512_loadu_si512((__m512i *)(buf + 0xC0));
+
+ x1 = _mm512_xor_si512(x1, _mm512_castsi128_si512(_mm_cvtsi32_si128(crc)));
+
+ x0 = _mm512_load_si512((__m512i *)k1k2);
+
+ buf += 256;
+ len -= 256;
+
+ /*
+ * Parallel fold blocks of 256, if any.
+ */
+ while (len >= 256)
+ {
+ x5 = _mm512_clmulepi64_epi128(x1, x0, 0x00);
+ x6 = _mm512_clmulepi64_epi128(x2, x0, 0x00);
+ x7 = _mm512_clmulepi64_epi128(x3, x0, 0x00);
+ x8 = _mm512_clmulepi64_epi128(x4, x0, 0x00);
+
+
+ x1 = _mm512_clmulepi64_epi128(x1, x0, 0x11);
+ x2 = _mm512_clmulepi64_epi128(x2, x0, 0x11);
+ x3 = _mm512_clmulepi64_epi128(x3, x0, 0x11);
+ x4 = _mm512_clmulepi64_epi128(x4, x0, 0x11);
+
+ y5 = _mm512_loadu_si512((__m512i *)(buf + 0x00));
+ y6 = _mm512_loadu_si512((__m512i *)(buf + 0x40));
+ y7 = _mm512_loadu_si512((__m512i *)(buf + 0x80));
+ y8 = _mm512_loadu_si512((__m512i *)(buf + 0xC0));
+
+ x1 = _mm512_xor_si512(x1, x5);
+ x2 = _mm512_xor_si512(x2, x6);
+ x3 = _mm512_xor_si512(x3, x7);
+ x4 = _mm512_xor_si512(x4, x8);
+
+ x1 = _mm512_xor_si512(x1, y5);
+ x2 = _mm512_xor_si512(x2, y6);
+ x3 = _mm512_xor_si512(x3, y7);
+ x4 = _mm512_xor_si512(x4, y8);
+
+ buf += 256;
+ len -= 256;
+ }
+
+ /*
+ * Fold into 512-bits.
+ */
+ x0 = _mm512_load_si512((__m512i *)k3k4);
+
+ x5 = _mm512_clmulepi64_epi128(x1, x0, 0x00);
+ x1 = _mm512_clmulepi64_epi128(x1, x0, 0x11);
+ x1 = _mm512_xor_si512(x1, x2);
+ x1 = _mm512_xor_si512(x1, x5);
+
+ x5 = _mm512_clmulepi64_epi128(x1, x0, 0x00);
+ x1 = _mm512_clmulepi64_epi128(x1, x0, 0x11);
+ x1 = _mm512_xor_si512(x1, x3);
+ x1 = _mm512_xor_si512(x1, x5);
+
+ x5 = _mm512_clmulepi64_epi128(x1, x0, 0x00);
+ x1 = _mm512_clmulepi64_epi128(x1, x0, 0x11);
+ x1 = _mm512_xor_si512(x1, x4);
+ x1 = _mm512_xor_si512(x1, x5);
+
+ /*
+ * Single fold blocks of 64, if any.
+ */
+ while (len >= 64)
+ {
+ x2 = _mm512_loadu_si512((__m512i *)buf);
+
+ x5 = _mm512_clmulepi64_epi128(x1, x0, 0x00);
+ x1 = _mm512_clmulepi64_epi128(x1, x0, 0x11);
+ x1 = _mm512_xor_si512(x1, x2);
+ x1 = _mm512_xor_si512(x1, x5);
+
+ buf += 64;
+ len -= 64;
+ }
+
+ /*
+ * Fold 512-bits to 384-bits.
+ */
+ a0 = _mm_load_si128((__m128i *)k5k6);
+
+ a1 = _mm512_extracti32x4_epi32(x1, 0);
+ a2 = _mm512_extracti32x4_epi32(x1, 1);
+
+ a3 = _mm_clmulepi64_si128(a1, a0, 0x00);
+ a1 = _mm_clmulepi64_si128(a1, a0, 0x11);
+
+ a1 = _mm_xor_si128(a1, a3);
+ a1 = _mm_xor_si128(a1, a2);
+
+ /*
+ * Fold 384-bits to 256-bits.
+ */
+ a2 = _mm512_extracti32x4_epi32(x1, 2);
+ a3 = _mm_clmulepi64_si128(a1, a0, 0x00);
+ a1 = _mm_clmulepi64_si128(a1, a0, 0x11);
+ a1 = _mm_xor_si128(a1, a3);
+ a1 = _mm_xor_si128(a1, a2);
+
+ /*
+ * Fold 256-bits to 128-bits.
+ */
+ a2 = _mm512_extracti32x4_epi32(x1, 3);
+ a3 = _mm_clmulepi64_si128(a1, a0, 0x00);
+ a1 = _mm_clmulepi64_si128(a1, a0, 0x11);
+ a1 = _mm_xor_si128(a1, a3);
+ a1 = _mm_xor_si128(a1, a2);
+
+ /*
+ * Fold 128-bits to 64-bits.
+ */
+ a2 = _mm_clmulepi64_si128(a1, a0, 0x10);
+ a3 = _mm_setr_epi32(~0, 0, ~0, 0);
+ a1 = _mm_srli_si128(a1, 8);
+ a1 = _mm_xor_si128(a1, a2);
+
+ a0 = _mm_loadl_epi64((__m128i*)k7k8);
+ a2 = _mm_srli_si128(a1, 4);
+ a1 = _mm_and_si128(a1, a3);
+ a1 = _mm_clmulepi64_si128(a1, a0, 0x00);
+ a1 = _mm_xor_si128(a1, a2);
+
+ /*
+ * Barret reduce to 32-bits.
+ */
+ a0 = _mm_load_si128((__m128i*)poly);
+
+ a2 = _mm_and_si128(a1, a3);
+ a2 = _mm_clmulepi64_si128(a2, a0, 0x10);
+ a2 = _mm_and_si128(a2, a3);
+ a2 = _mm_clmulepi64_si128(a2, a0, 0x00);
+ a1 = _mm_xor_si128(a1, a2);
+
+ /*
+ * Return the crc32.
+ */
+ return _mm_extract_epi32(a1, 1);
+}
+
+#elif defined(CRC32_SIMD_SSE42_PCLMUL)
+
+/*
+ * crc32_sse42_simd_(): compute the crc32 of the buffer, where the buffer
+ * length must be at least 64, and a multiple of 16.
+ */
+
+#include <emmintrin.h>
+#include <smmintrin.h>
+#include <wmmintrin.h>
uint32_t ZLIB_INTERNAL crc32_sse42_simd_( /* SSE4.2+PCLMUL */
const unsigned char *buf,
diff --git a/crc32_simd.h b/crc32_simd.h
index c0346dc..8462464 100644
--- a/crc32_simd.h
+++ b/crc32_simd.h
@@ -19,12 +19,18 @@ uint32_t ZLIB_INTERNAL crc32_sse42_simd_(const unsigned char* buf,
z_size_t len,
uint32_t crc);
+uint32_t ZLIB_INTERNAL crc32_avx512_simd_(const unsigned char* buf,
+ z_size_t len,
+ uint32_t crc);
+
/*
* crc32_sse42_simd_ buffer size constraints: see the use in zlib/crc32.c
* for computing the crc32 of an arbitrary length buffer.
*/
#define Z_CRC32_SSE42_MINIMUM_LENGTH 64
#define Z_CRC32_SSE42_CHUNKSIZE_MASK 15
+#define Z_CRC32_AVX512_MINIMUM_LENGTH 256
+#define Z_CRC32_AVX512_CHUNKSIZE_MASK 63
/*
* CRC32 checksums using ARMv8-a crypto instructions.
diff --git a/google/BUILD.gn b/google/BUILD.gn
index 35ba1da..122cef5 100644
--- a/google/BUILD.gn
+++ b/google/BUILD.gn
@@ -4,6 +4,10 @@
import("//build_overrides/build.gni")
+if (build_with_chromium && is_ios) {
+ import("//build/config/ios/bundle_data_from_filelist.gni")
+}
+
if (build_with_chromium) {
static_library("zip") {
sources = [
@@ -18,9 +22,9 @@ if (build_with_chromium) {
"zip_writer.h",
]
deps = [
+ "..:minizip",
"//base",
"//base:i18n",
- "//third_party/zlib:minizip",
]
}
@@ -30,11 +34,18 @@ if (build_with_chromium) {
"compression_utils.h",
]
deps = [
+ "..",
"//base",
- "//third_party/zlib",
]
public_deps = [ ":compression_utils_portable" ]
}
+
+ if (is_ios) {
+ bundle_data_from_filelist("zlib_pak_bundle_data") {
+ testonly = true
+ filelist_name = "test_data.filelist"
+ }
+ }
}
# This allows other users of Chromium's zlib library, but don't use Chromium's
@@ -44,5 +55,5 @@ static_library("compression_utils_portable") {
"compression_utils_portable.cc",
"compression_utils_portable.h",
]
- public_deps = [ "//third_party/zlib" ]
+ public_deps = [ ".." ]
}
diff --git a/google/OWNERS b/google/OWNERS
index 411670c..868af3c 100644
--- a/google/OWNERS
+++ b/google/OWNERS
@@ -1,5 +1,3 @@
-fdegros@chromium.org
-noel@chromium.org
satorux@chromium.org
# compression_utils*
diff --git a/google/test_data.filelist b/google/test_data.filelist
new file mode 100644
index 0000000..0a9d20b
--- /dev/null
+++ b/google/test_data.filelist
@@ -0,0 +1,32 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# NOTE: this file is generated by build/ios/update_bundle_filelist.py
+# If it requires updating, you should get a presubmit error with
+# instructions on how to regenerate. Otherwise, do not edit.
+test/data/Different Encryptions.zip
+test/data/Empty Dir Same Name As File.zip
+test/data/Mixed Paths.zip
+test/data/Parent Dir Same Name As File.zip
+test/data/README.md
+test/data/Repeated Dir Name.zip
+test/data/Repeated File Name With Different Cases.zip
+test/data/Repeated File Name.zip
+test/data/SJIS Bug 846195.zip
+test/data/Windows Special Names.zip
+test/data/Wrong CRC.zip
+test/data/create_test_zip.sh
+test/data/empty.zip
+test/data/evil.zip
+test/data/evil_via_absolute_file_name.zip
+test/data/evil_via_invalid_utf8.zip
+test/data/test.zip
+test/data/test/foo.txt
+test/data/test/foo/bar.txt
+test/data/test/foo/bar/.hidden
+test/data/test/foo/bar/baz.txt
+test/data/test/foo/bar/quux.txt
+test/data/test_encrypted.zip
+test/data/test_mismatch_size.zip
+test/data/test_nocompress.zip
+test/data/test_posix_permissions.zip
diff --git a/google/test_data.globlist b/google/test_data.globlist
new file mode 100644
index 0000000..117a1e5
--- /dev/null
+++ b/google/test_data.globlist
@@ -0,0 +1,8 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# See build/ios/update_bundle_filelist.py for details on how .globlist
+# files are used to update their .filelist counterparts.
+test/data/**
+test/data/test/foo/bar/.hidden \ No newline at end of file
diff --git a/google/zip.cc b/google/zip.cc
index 490dcee..87065b9 100644
--- a/google/zip.cc
+++ b/google/zip.cc
@@ -7,10 +7,10 @@
#include <string>
#include <vector>
-#include "base/bind.h"
#include "base/files/file.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
+#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
diff --git a/google/zip.h b/google/zip.h
index e3036c8..ea87786 100644
--- a/google/zip.h
+++ b/google/zip.h
@@ -10,10 +10,10 @@
#include <utility>
#include <vector>
-#include "base/callback.h"
#include "base/containers/span.h"
#include "base/files/file_path.h"
#include "base/files/platform_file.h"
+#include "base/functional/callback.h"
#include "base/time/time.h"
#include "build/build_config.h"
diff --git a/google/zip_reader.cc b/google/zip_reader.cc
index e97027a..9b1030a 100644
--- a/google/zip_reader.cc
+++ b/google/zip_reader.cc
@@ -7,10 +7,10 @@
#include <algorithm>
#include <utility>
-#include "base/bind.h"
#include "base/check.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
+#include "base/functional/bind.h"
#include "base/i18n/icu_string_conversions.h"
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
@@ -18,7 +18,7 @@
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/threading/sequenced_task_runner_handle.h"
+#include "base/task/sequenced_task_runner.h"
#include "build/build_config.h"
#include "third_party/zlib/google/redact.h"
#include "third_party/zlib/google/zip_internal.h"
@@ -461,11 +461,11 @@ void ZipReader::ExtractCurrentEntryToFilePathAsync(
// If this is a directory, just create it and return.
if (entry_.is_directory) {
if (base::CreateDirectory(output_file_path)) {
- base::SequencedTaskRunnerHandle::Get()->PostTask(
+ base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, std::move(success_callback));
} else {
LOG(ERROR) << "Cannot create directory " << Redact(output_file_path);
- base::SequencedTaskRunnerHandle::Get()->PostTask(
+ base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, std::move(failure_callback));
}
return;
@@ -479,7 +479,7 @@ void ZipReader::ExtractCurrentEntryToFilePathAsync(
err != UNZ_OK) {
LOG(ERROR) << "Cannot open file " << Redact(entry_.path)
<< " from ZIP: " << err;
- base::SequencedTaskRunnerHandle::Get()->PostTask(
+ base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, std::move(failure_callback));
return;
}
@@ -487,7 +487,7 @@ void ZipReader::ExtractCurrentEntryToFilePathAsync(
base::FilePath output_dir_path = output_file_path.DirName();
if (!base::CreateDirectory(output_dir_path)) {
LOG(ERROR) << "Cannot create directory " << Redact(output_dir_path);
- base::SequencedTaskRunnerHandle::Get()->PostTask(
+ base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, std::move(failure_callback));
return;
}
@@ -497,12 +497,12 @@ void ZipReader::ExtractCurrentEntryToFilePathAsync(
if (!output_file.IsValid()) {
LOG(ERROR) << "Cannot create file " << Redact(output_file_path);
- base::SequencedTaskRunnerHandle::Get()->PostTask(
+ base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, std::move(failure_callback));
return;
}
- base::SequencedTaskRunnerHandle::Get()->PostTask(
+ base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(&ZipReader::ExtractChunk, weak_ptr_factory_.GetWeakPtr(),
std::move(output_file), std::move(success_callback),
@@ -602,7 +602,7 @@ void ZipReader::ExtractChunk(base::File output_file,
offset += num_bytes_read;
progress_callback.Run(offset);
- base::SequencedTaskRunnerHandle::Get()->PostTask(
+ base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(&ZipReader::ExtractChunk, weak_ptr_factory_.GetWeakPtr(),
std::move(output_file), std::move(success_callback),
diff --git a/google/zip_reader.h b/google/zip_reader.h
index 48244c8..b7680cc 100644
--- a/google/zip_reader.h
+++ b/google/zip_reader.h
@@ -11,9 +11,9 @@
#include <memory>
#include <string>
-#include "base/callback.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
+#include "base/functional/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/numerics/safe_conversions.h"
#include "base/time/time.h"
diff --git a/google/zip_reader_unittest.cc b/google/zip_reader_unittest.cc
index 52dab20..b917504 100644
--- a/google/zip_reader_unittest.cc
+++ b/google/zip_reader_unittest.cc
@@ -12,12 +12,12 @@
#include <string>
#include <vector>
-#include "base/bind.h"
#include "base/check.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
+#include "base/functional/bind.h"
#include "base/hash/md5.h"
#include "base/path_service.h"
#include "base/run_loop.h"
diff --git a/google/zip_unittest.cc b/google/zip_unittest.cc
index b639e8e..d0fc02f 100644
--- a/google/zip_unittest.cc
+++ b/google/zip_unittest.cc
@@ -12,12 +12,12 @@
#include <unordered_set>
#include <vector>
-#include "base/bind.h"
#include "base/files/file.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
+#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/strings/strcat.h"
@@ -611,7 +611,7 @@ TEST_F(ZipTest, UnzipWindowsSpecialNames) {
"NUL .txt",
"NUL .txt",
"NUL ..txt",
-#ifndef OS_MAC
+#ifndef OS_APPLE
"Nul.txt",
#endif
"nul.very long extension",
@@ -669,7 +669,7 @@ TEST_F(ZipTest, UnzipWindowsSpecialNames) {
}
TEST_F(ZipTest, UnzipDifferentCases) {
-#if defined(OS_WIN) || defined(OS_MAC)
+#if defined(OS_WIN) || defined(OS_APPLE)
// Only the first file (with mixed case) is extracted.
EXPECT_FALSE(zip::Unzip(GetDataDirectory().AppendASCII(
"Repeated File Name With Different Cases.zip"),
@@ -711,7 +711,7 @@ TEST_F(ZipTest, UnzipDifferentCasesContinueOnError) {
std::string contents;
-#if defined(OS_WIN) || defined(OS_MAC)
+#if defined(OS_WIN) || defined(OS_APPLE)
// Only the first file (with mixed case) has been extracted.
EXPECT_THAT(
GetRelativePaths(test_dir_, base::FileEnumerator::FileType::FILES),
@@ -782,7 +782,7 @@ TEST_F(ZipTest, UnzipMixedPaths) {
"Space→ ", //
"c/NUL", // Disappears on Windows
"nul.very long extension", // Disappears on Windows
-#ifndef OS_MAC
+#ifndef OS_APPLE
"CASE", // Conflicts with "Case"
"case", // Conflicts with "Case"
#endif
diff --git a/patches/0010-cmake-enable-simd.patch b/patches/0010-cmake-enable-simd.patch
new file mode 100644
index 0000000..3893101
--- /dev/null
+++ b/patches/0010-cmake-enable-simd.patch
@@ -0,0 +1,96 @@
+diff --git a/third_party/zlib/CMakeLists.txt b/third_party/zlib/CMakeLists.txt
+index b412dc7feb732..0431278405046 100644
+--- a/third_party/zlib/CMakeLists.txt
++++ b/third_party/zlib/CMakeLists.txt
+@@ -1,4 +1,4 @@
+-cmake_minimum_required(VERSION 2.4.4)
++cmake_minimum_required(VERSION 3.0)
+ set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
+
+ project(zlib C)
+@@ -21,6 +21,26 @@ 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)
+
++option(ENABLE_SIMD_OPTIMIZATIONS "Enable all SIMD optimizations" OFF)
++
++# TODO(cavalcantii): add support for other OSes (e.g. Android, fuchsia, osx)
++# and architectures (e.g. Arm).
++if (ENABLE_SIMD_OPTIMIZATIONS)
++ add_definitions(-DINFLATE_CHUNK_SIMD_SSE2)
++ add_definitions(-DADLER32_SIMD_SSSE3)
++ add_definitions(-DINFLATE_CHUNK_READ_64LE)
++ add_definitions(-DCRC32_SIMD_SSE42_PCLMUL)
++ add_definitions(-DDEFLATE_SLIDE_HASH_SSE2)
++ add_compile_options(-msse4.2 -mpclmul)
++ # Required by CPU features detection code.
++ add_definitions(-DX86_NOT_WINDOWS)
++ # Apparently some environments (e.g. CentOS) require to explicitly link
++ # with pthread and that is required by the CPU features detection code.
++ find_package (Threads REQUIRED)
++ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread")
++ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
++endif()
++
+ #
+ # Check to see if we have large file support
+ #
+@@ -120,10 +140,25 @@ set(ZLIB_SRCS
+ zutil.c
+ )
+
+-if(NOT MINGW)
+- set(ZLIB_DLL_SRCS
+- win32/zlib1.rc # If present will override custom build rule below.
+- )
++
++#============================================================================
++# Update list of source files if optimizations were enabled
++#============================================================================
++if (ENABLE_SIMD_OPTIMIZATIONS)
++ list(REMOVE_ITEM ZLIB_SRCS inflate.c)
++
++ list(APPEND ZLIB_PRIVATE_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/adler32_simd.h)
++ list(APPEND ZLIB_PRIVATE_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/contrib/optimizations/chunkcopy.h)
++ list(APPEND ZLIB_PRIVATE_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/contrib/optimizations/inffast_chunk.h)
++ list(APPEND ZLIB_PRIVATE_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/cpu_features.h)
++ list(APPEND ZLIB_PRIVATE_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/crc32_simd.h)
++
++ list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/adler32_simd.c)
++ list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/contrib/optimizations/inffast_chunk.c)
++ list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/contrib/optimizations/inflate.c)
++ list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/cpu_features.c)
++ list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/crc32_simd.c)
++ list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/crc_folding.c)
+ endif()
+
+ # parse the full version number from zlib.h and include in ZLIB_FULL_VERSION
+@@ -191,23 +226,9 @@ if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
+ endif()
+
+ #============================================================================
+-# Example binaries
++# Benchmarker
+ #============================================================================
+-
+-add_executable(example test/example.c)
+-target_link_libraries(example zlib)
+-add_test(example example)
+-
+-add_executable(minigzip test/minigzip.c)
+-target_link_libraries(minigzip zlib)
+-
+-if(HAVE_OFF64_T)
+- add_executable(example64 test/example.c)
+- target_link_libraries(example64 zlib)
+- set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
+- add_test(example64 example64)
+-
+- add_executable(minigzip64 test/minigzip.c)
+- target_link_libraries(minigzip64 zlib)
+- set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
+-endif()
++enable_language(CXX)
++set(CMAKE_CXX_STANDARD 14) # workaround for older compilers (e.g. g++ 5.4).
++add_executable(zlib_bench contrib/bench/zlib_bench.cc)
++target_link_libraries(zlib_bench zlib)
diff --git a/patches/0011-avx512.patch b/patches/0011-avx512.patch
new file mode 100644
index 0000000..6d409b7
--- /dev/null
+++ b/patches/0011-avx512.patch
@@ -0,0 +1,357 @@
+From 87fc8e3e38323cfdabf8da3927488e3e57073b02 Mon Sep 17 00:00:00 2001
+From: Jia Liu <jia3.liu@intel.com>
+Date: Thu, 30 Mar 2023 11:13:16 +0800
+Subject: [PATCH] Enabled AVX512 for CRC32
+
+Enabled AVX512 for CRC32 that provide best of known performance
+beyond current SSE SIMD optimization. It enables multiple folding
+operations and AVX512 new instructions, providing ~3.5X CRC32
+performance and ~3.7% gain on Zlib_bench gzip performance.
+---
+ CMakeLists.txt | 8 +-
+ cpu_features.c | 9 +++
+ cpu_features.h | 1 +
+ crc32.c | 14 +++-
+ crc32_simd.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++++-
+ crc32_simd.h | 6 ++
+ 6 files changed, 230 insertions(+), 6 deletions(-)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index f06e193..d45b902 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -22,6 +22,7 @@ check_include_file(stdint.h HAVE_STDINT_H)
+ check_include_file(stddef.h HAVE_STDDEF_H)
+
+ option(ENABLE_SIMD_OPTIMIZATIONS "Enable all SIMD optimizations" OFF)
++option(ENABLE_SIMD_AVX512 "Enable SIMD AXV512 optimizations" OFF)
+
+ # TODO(cavalcantii): add support for other OSes (e.g. Android, fuchsia, osx)
+ # and architectures (e.g. Arm).
+@@ -30,8 +31,13 @@ if (ENABLE_SIMD_OPTIMIZATIONS)
+ add_definitions(-DADLER32_SIMD_SSSE3)
+ add_definitions(-DINFLATE_CHUNK_READ_64LE)
+ add_definitions(-DCRC32_SIMD_SSE42_PCLMUL)
++ if (ENABLE_SIMD_AVX512)
++ add_definitions(-DCRC32_SIMD_AVX512_PCLMUL)
++ add_compile_options(-mvpclmulqdq -msse2 -mavx512f -mpclmul)
++ else()
++ add_compile_options(-msse4.2 -mpclmul)
++ endif()
+ add_definitions(-DDEFLATE_SLIDE_HASH_SSE2)
+- add_compile_options(-msse4.2 -mpclmul)
+ # Required by CPU features detection code.
+ add_definitions(-DX86_NOT_WINDOWS)
+ # Apparently some environments (e.g. CentOS) require to explicitly link
+diff --git a/cpu_features.c b/cpu_features.c
+index 877d5f2..ac6ee88 100644
+--- a/cpu_features.c
++++ b/cpu_features.c
+@@ -31,6 +31,7 @@ int ZLIB_INTERNAL arm_cpu_enable_pmull = 0;
+ int ZLIB_INTERNAL x86_cpu_enable_sse2 = 0;
+ int ZLIB_INTERNAL x86_cpu_enable_ssse3 = 0;
+ int ZLIB_INTERNAL x86_cpu_enable_simd = 0;
++int ZLIB_INTERNAL x86_cpu_enable_avx512 = 0;
+
+ #ifndef CPU_NO_SIMD
+
+@@ -138,6 +139,10 @@ static void _cpu_check_features(void)
+ /* On x86 we simply use a instruction to check the CPU features.
+ * (i.e. CPUID).
+ */
++#ifdef CRC32_SIMD_AVX512_PCLMUL
++#include <immintrin.h>
++#include <xsaveintrin.h>
++#endif
+ static void _cpu_check_features(void)
+ {
+ int x86_cpu_has_sse2;
+@@ -164,6 +169,10 @@ static void _cpu_check_features(void)
+ x86_cpu_enable_simd = x86_cpu_has_sse2 &&
+ x86_cpu_has_sse42 &&
+ x86_cpu_has_pclmulqdq;
++
++#ifdef CRC32_SIMD_AVX512_PCLMUL
++ x86_cpu_enable_avx512 = _xgetbv(0) & 0x00000040;
++#endif
+ }
+ #endif
+ #endif
+diff --git a/cpu_features.h b/cpu_features.h
+index 279246c..aed3e83 100644
+--- a/cpu_features.h
++++ b/cpu_features.h
+@@ -14,5 +14,6 @@ extern int arm_cpu_enable_pmull;
+ extern int x86_cpu_enable_sse2;
+ extern int x86_cpu_enable_ssse3;
+ extern int x86_cpu_enable_simd;
++extern int x86_cpu_enable_avx512;
+
+ void cpu_check_features(void);
+diff --git a/crc32.c b/crc32.c
+index 4486098..acb6972 100644
+--- a/crc32.c
++++ b/crc32.c
+@@ -773,7 +773,19 @@ unsigned long ZEXPORT crc32_z(crc, buf, len)
+ }
+
+ #endif
+-#if defined(CRC32_SIMD_SSE42_PCLMUL)
++#if defined(CRC32_SIMD_AVX512_PCLMUL)
++ if (x86_cpu_enable_avx512 && len >= Z_CRC32_AVX512_MINIMUM_LENGTH) {
++ /* crc32 64-byte chunks */
++ z_size_t chunk_size = len & ~Z_CRC32_AVX512_CHUNKSIZE_MASK;
++ crc = ~crc32_avx512_simd_(buf, chunk_size, ~(uint32_t)crc);
++ /* check remaining data */
++ len -= chunk_size;
++ if (!len)
++ return crc;
++ /* Fall into the default crc32 for the remaining data. */
++ buf += chunk_size;
++ }
++#elif defined(CRC32_SIMD_SSE42_PCLMUL)
+ if (x86_cpu_enable_simd && len >= Z_CRC32_SSE42_MINIMUM_LENGTH) {
+ /* crc32 16-byte chunks */
+ z_size_t chunk_size = len & ~Z_CRC32_SSE42_CHUNKSIZE_MASK;
+diff --git a/crc32_simd.c b/crc32_simd.c
+index d80beba..7428270 100644
+--- a/crc32_simd.c
++++ b/crc32_simd.c
+@@ -6,17 +6,207 @@
+ */
+
+ #include "crc32_simd.h"
+-
+-#if defined(CRC32_SIMD_SSE42_PCLMUL)
++#if defined(CRC32_SIMD_AVX512_PCLMUL)
+
+ /*
+- * crc32_sse42_simd_(): compute the crc32 of the buffer, where the buffer
+- * length must be at least 64, and a multiple of 16. Based on:
++ * crc32_avx512_simd_(): compute the crc32 of the buffer, where the buffer
++ * length must be at least 256, and a multiple of 64. Based on:
+ *
+ * "Fast CRC Computation for Generic Polynomials Using PCLMULQDQ Instruction"
+ * V. Gopal, E. Ozturk, et al., 2009, http://intel.ly/2ySEwL0
+ */
+
++#include <emmintrin.h>
++#include <smmintrin.h>
++#include <wmmintrin.h>
++#include <immintrin.h>
++
++uint32_t ZLIB_INTERNAL crc32_avx512_simd_( /* AVX512+PCLMUL */
++ const unsigned char *buf,
++ z_size_t len,
++ uint32_t crc)
++{
++ /*
++ * Definitions of the bit-reflected domain constants k1,k2,k3,k4
++ * are similar to those given at the end of the paper, and remaining
++ * constants and CRC32+Barrett polynomials remain unchanged.
++ *
++ * Replace the index of x from 128 to 512. As follows:
++ * k1 = ( x ^ ( 512 * 4 + 32 ) mod P(x) << 32 )' << 1 = 0x011542778a
++ * k2 = ( x ^ ( 512 * 4 - 32 ) mod P(x) << 32 )' << 1 = 0x01322d1430
++ * k3 = ( x ^ ( 512 + 32 ) mod P(x) << 32 )' << 1 = 0x0154442bd4
++ * k4 = ( x ^ ( 512 - 32 ) mod P(x) << 32 )' << 1 = 0x01c6e41596
++ */
++ static const uint64_t zalign(64) k1k2[] = { 0x011542778a, 0x01322d1430,
++ 0x011542778a, 0x01322d1430,
++ 0x011542778a, 0x01322d1430,
++ 0x011542778a, 0x01322d1430 };
++ static const uint64_t zalign(64) k3k4[] = { 0x0154442bd4, 0x01c6e41596,
++ 0x0154442bd4, 0x01c6e41596,
++ 0x0154442bd4, 0x01c6e41596,
++ 0x0154442bd4, 0x01c6e41596 };
++ static const uint64_t zalign(16) k5k6[] = { 0x01751997d0, 0x00ccaa009e };
++ static const uint64_t zalign(16) k7k8[] = { 0x0163cd6124, 0x0000000000 };
++ static const uint64_t zalign(16) poly[] = { 0x01db710641, 0x01f7011641 };
++ __m512i x0, x1, x2, x3, x4, x5, x6, x7, x8, y5, y6, y7, y8;
++ __m128i a0, a1, a2, a3;
++
++ /*
++ * There's at least one block of 256.
++ */
++ x1 = _mm512_loadu_si512((__m512i *)(buf + 0x00));
++ x2 = _mm512_loadu_si512((__m512i *)(buf + 0x40));
++ x3 = _mm512_loadu_si512((__m512i *)(buf + 0x80));
++ x4 = _mm512_loadu_si512((__m512i *)(buf + 0xC0));
++
++ x1 = _mm512_xor_si512(x1, _mm512_castsi128_si512(_mm_cvtsi32_si128(crc)));
++
++ x0 = _mm512_load_si512((__m512i *)k1k2);
++
++ buf += 256;
++ len -= 256;
++
++ /*
++ * Parallel fold blocks of 256, if any.
++ */
++ while (len >= 256)
++ {
++ x5 = _mm512_clmulepi64_epi128(x1, x0, 0x00);
++ x6 = _mm512_clmulepi64_epi128(x2, x0, 0x00);
++ x7 = _mm512_clmulepi64_epi128(x3, x0, 0x00);
++ x8 = _mm512_clmulepi64_epi128(x4, x0, 0x00);
++
++
++ x1 = _mm512_clmulepi64_epi128(x1, x0, 0x11);
++ x2 = _mm512_clmulepi64_epi128(x2, x0, 0x11);
++ x3 = _mm512_clmulepi64_epi128(x3, x0, 0x11);
++ x4 = _mm512_clmulepi64_epi128(x4, x0, 0x11);
++
++ y5 = _mm512_loadu_si512((__m512i *)(buf + 0x00));
++ y6 = _mm512_loadu_si512((__m512i *)(buf + 0x40));
++ y7 = _mm512_loadu_si512((__m512i *)(buf + 0x80));
++ y8 = _mm512_loadu_si512((__m512i *)(buf + 0xC0));
++
++ x1 = _mm512_xor_si512(x1, x5);
++ x2 = _mm512_xor_si512(x2, x6);
++ x3 = _mm512_xor_si512(x3, x7);
++ x4 = _mm512_xor_si512(x4, x8);
++
++ x1 = _mm512_xor_si512(x1, y5);
++ x2 = _mm512_xor_si512(x2, y6);
++ x3 = _mm512_xor_si512(x3, y7);
++ x4 = _mm512_xor_si512(x4, y8);
++
++ buf += 256;
++ len -= 256;
++ }
++
++ /*
++ * Fold into 512-bits.
++ */
++ x0 = _mm512_load_si512((__m512i *)k3k4);
++
++ x5 = _mm512_clmulepi64_epi128(x1, x0, 0x00);
++ x1 = _mm512_clmulepi64_epi128(x1, x0, 0x11);
++ x1 = _mm512_xor_si512(x1, x2);
++ x1 = _mm512_xor_si512(x1, x5);
++
++ x5 = _mm512_clmulepi64_epi128(x1, x0, 0x00);
++ x1 = _mm512_clmulepi64_epi128(x1, x0, 0x11);
++ x1 = _mm512_xor_si512(x1, x3);
++ x1 = _mm512_xor_si512(x1, x5);
++
++ x5 = _mm512_clmulepi64_epi128(x1, x0, 0x00);
++ x1 = _mm512_clmulepi64_epi128(x1, x0, 0x11);
++ x1 = _mm512_xor_si512(x1, x4);
++ x1 = _mm512_xor_si512(x1, x5);
++
++ /*
++ * Single fold blocks of 64, if any.
++ */
++ while (len >= 64)
++ {
++ x2 = _mm512_loadu_si512((__m512i *)buf);
++
++ x5 = _mm512_clmulepi64_epi128(x1, x0, 0x00);
++ x1 = _mm512_clmulepi64_epi128(x1, x0, 0x11);
++ x1 = _mm512_xor_si512(x1, x2);
++ x1 = _mm512_xor_si512(x1, x5);
++
++ buf += 64;
++ len -= 64;
++ }
++
++ /*
++ * Fold 512-bits to 384-bits.
++ */
++ a0 = _mm_load_si128((__m128i *)k5k6);
++
++ a1 = _mm512_extracti32x4_epi32(x1, 0);
++ a2 = _mm512_extracti32x4_epi32(x1, 1);
++
++ a3 = _mm_clmulepi64_si128(a1, a0, 0x00);
++ a1 = _mm_clmulepi64_si128(a1, a0, 0x11);
++
++ a1 = _mm_xor_si128(a1, a3);
++ a1 = _mm_xor_si128(a1, a2);
++
++ /*
++ * Fold 384-bits to 256-bits.
++ */
++ a2 = _mm512_extracti32x4_epi32(x1, 2);
++ a3 = _mm_clmulepi64_si128(a1, a0, 0x00);
++ a1 = _mm_clmulepi64_si128(a1, a0, 0x11);
++ a1 = _mm_xor_si128(a1, a3);
++ a1 = _mm_xor_si128(a1, a2);
++
++ /*
++ * Fold 256-bits to 128-bits.
++ */
++ a2 = _mm512_extracti32x4_epi32(x1, 3);
++ a3 = _mm_clmulepi64_si128(a1, a0, 0x00);
++ a1 = _mm_clmulepi64_si128(a1, a0, 0x11);
++ a1 = _mm_xor_si128(a1, a3);
++ a1 = _mm_xor_si128(a1, a2);
++
++ /*
++ * Fold 128-bits to 64-bits.
++ */
++ a2 = _mm_clmulepi64_si128(a1, a0, 0x10);
++ a3 = _mm_setr_epi32(~0, 0, ~0, 0);
++ a1 = _mm_srli_si128(a1, 8);
++ a1 = _mm_xor_si128(a1, a2);
++
++ a0 = _mm_loadl_epi64((__m128i*)k7k8);
++ a2 = _mm_srli_si128(a1, 4);
++ a1 = _mm_and_si128(a1, a3);
++ a1 = _mm_clmulepi64_si128(a1, a0, 0x00);
++ a1 = _mm_xor_si128(a1, a2);
++
++ /*
++ * Barret reduce to 32-bits.
++ */
++ a0 = _mm_load_si128((__m128i*)poly);
++
++ a2 = _mm_and_si128(a1, a3);
++ a2 = _mm_clmulepi64_si128(a2, a0, 0x10);
++ a2 = _mm_and_si128(a2, a3);
++ a2 = _mm_clmulepi64_si128(a2, a0, 0x00);
++ a1 = _mm_xor_si128(a1, a2);
++
++ /*
++ * Return the crc32.
++ */
++ return _mm_extract_epi32(a1, 1);
++}
++
++#elif defined(CRC32_SIMD_SSE42_PCLMUL)
++
++/*
++ * crc32_sse42_simd_(): compute the crc32 of the buffer, where the buffer
++ * length must be at least 64, and a multiple of 16.
++ */
++
+ #include <emmintrin.h>
+ #include <smmintrin.h>
+ #include <wmmintrin.h>
+diff --git a/crc32_simd.h b/crc32_simd.h
+index c0346dc..8462464 100644
+--- a/crc32_simd.h
++++ b/crc32_simd.h
+@@ -19,12 +19,18 @@ uint32_t ZLIB_INTERNAL crc32_sse42_simd_(const unsigned char* buf,
+ z_size_t len,
+ uint32_t crc);
+
++uint32_t ZLIB_INTERNAL crc32_avx512_simd_(const unsigned char* buf,
++ z_size_t len,
++ uint32_t crc);
++
+ /*
+ * crc32_sse42_simd_ buffer size constraints: see the use in zlib/crc32.c
+ * for computing the crc32 of an arbitrary length buffer.
+ */
+ #define Z_CRC32_SSE42_MINIMUM_LENGTH 64
+ #define Z_CRC32_SSE42_CHUNKSIZE_MASK 15
++#define Z_CRC32_AVX512_MINIMUM_LENGTH 256
++#define Z_CRC32_AVX512_CHUNKSIZE_MASK 63
+
+ /*
+ * CRC32 checksums using ARMv8-a crypto instructions.
+--
+2.34.1
+
diff --git a/zconf.h.cmakein b/zconf.h.cmakein
new file mode 100644
index 0000000..247ba24
--- /dev/null
+++ b/zconf.h.cmakein
@@ -0,0 +1,549 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+#cmakedefine Z_PREFIX
+#cmakedefine Z_HAVE_UNISTD_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ * Even better than compiling with -DZ_PREFIX would be to use configure to set
+ * this permanently in zconf.h using "./configure --zprefix".
+ */
+#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */
+# define Z_PREFIX_SET
+
+/* all linked symbols and init macros */
+# define _dist_code z__dist_code
+# define _length_code z__length_code
+# define _tr_align z__tr_align
+# define _tr_flush_bits z__tr_flush_bits
+# define _tr_flush_block z__tr_flush_block
+# define _tr_init z__tr_init
+# define _tr_stored_block z__tr_stored_block
+# define _tr_tally z__tr_tally
+# define adler32 z_adler32
+# define adler32_combine z_adler32_combine
+# define adler32_combine64 z_adler32_combine64
+# define adler32_z z_adler32_z
+# ifndef Z_SOLO
+# define compress z_compress
+# define compress2 z_compress2
+# define compressBound z_compressBound
+# endif
+# define crc32 z_crc32
+# define crc32_combine z_crc32_combine
+# define crc32_combine64 z_crc32_combine64
+# define crc32_combine_gen z_crc32_combine_gen
+# define crc32_combine_gen64 z_crc32_combine_gen64
+# define crc32_combine_op z_crc32_combine_op
+# define crc32_z z_crc32_z
+# define deflate z_deflate
+# define deflateBound z_deflateBound
+# define deflateCopy z_deflateCopy
+# define deflateEnd z_deflateEnd
+# define deflateGetDictionary z_deflateGetDictionary
+# define deflateInit z_deflateInit
+# define deflateInit2 z_deflateInit2
+# define deflateInit2_ z_deflateInit2_
+# define deflateInit_ z_deflateInit_
+# define deflateParams z_deflateParams
+# define deflatePending z_deflatePending
+# define deflatePrime z_deflatePrime
+# define deflateReset z_deflateReset
+# define deflateResetKeep z_deflateResetKeep
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateSetHeader z_deflateSetHeader
+# define deflateTune z_deflateTune
+# define deflate_copyright z_deflate_copyright
+# define get_crc_table z_get_crc_table
+# ifndef Z_SOLO
+# define gz_error z_gz_error
+# define gz_intmax z_gz_intmax
+# define gz_strwinerror z_gz_strwinerror
+# define gzbuffer z_gzbuffer
+# define gzclearerr z_gzclearerr
+# define gzclose z_gzclose
+# define gzclose_r z_gzclose_r
+# define gzclose_w z_gzclose_w
+# define gzdirect z_gzdirect
+# define gzdopen z_gzdopen
+# define gzeof z_gzeof
+# define gzerror z_gzerror
+# define gzflush z_gzflush
+# define gzfread z_gzfread
+# define gzfwrite z_gzfwrite
+# define gzgetc z_gzgetc
+# define gzgetc_ z_gzgetc_
+# define gzgets z_gzgets
+# define gzoffset z_gzoffset
+# define gzoffset64 z_gzoffset64
+# define gzopen z_gzopen
+# define gzopen64 z_gzopen64
+# ifdef _WIN32
+# define gzopen_w z_gzopen_w
+# endif
+# define gzprintf z_gzprintf
+# define gzputc z_gzputc
+# define gzputs z_gzputs
+# define gzread z_gzread
+# define gzrewind z_gzrewind
+# define gzseek z_gzseek
+# define gzseek64 z_gzseek64
+# define gzsetparams z_gzsetparams
+# define gztell z_gztell
+# define gztell64 z_gztell64
+# define gzungetc z_gzungetc
+# define gzvprintf z_gzvprintf
+# define gzwrite z_gzwrite
+# endif
+# define inflate z_inflate
+# define inflateBack z_inflateBack
+# define inflateBackEnd z_inflateBackEnd
+# define inflateBackInit z_inflateBackInit
+# define inflateBackInit_ z_inflateBackInit_
+# define inflateCodesUsed z_inflateCodesUsed
+# define inflateCopy z_inflateCopy
+# define inflateEnd z_inflateEnd
+# define inflateGetDictionary z_inflateGetDictionary
+# define inflateGetHeader z_inflateGetHeader
+# define inflateInit z_inflateInit
+# define inflateInit2 z_inflateInit2
+# define inflateInit2_ z_inflateInit2_
+# define inflateInit_ z_inflateInit_
+# define inflateMark z_inflateMark
+# define inflatePrime z_inflatePrime
+# define inflateReset z_inflateReset
+# define inflateReset2 z_inflateReset2
+# define inflateResetKeep z_inflateResetKeep
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateSync z_inflateSync
+# define inflateSyncPoint z_inflateSyncPoint
+# define inflateUndermine z_inflateUndermine
+# define inflateValidate z_inflateValidate
+# define inflate_copyright z_inflate_copyright
+# define inflate_fast z_inflate_fast
+# define inflate_table z_inflate_table
+# ifndef Z_SOLO
+# define uncompress z_uncompress
+# define uncompress2 z_uncompress2
+# endif
+# define zError z_zError
+# ifndef Z_SOLO
+# define zcalloc z_zcalloc
+# define zcfree z_zcfree
+# endif
+# define zlibCompileFlags z_zlibCompileFlags
+# define zlibVersion z_zlibVersion
+
+/* all zlib typedefs in zlib.h and zconf.h */
+# define Byte z_Byte
+# define Bytef z_Bytef
+# define alloc_func z_alloc_func
+# define charf z_charf
+# define free_func z_free_func
+# ifndef Z_SOLO
+# define gzFile z_gzFile
+# endif
+# define gz_header z_gz_header
+# define gz_headerp z_gz_headerp
+# define in_func z_in_func
+# define intf z_intf
+# define out_func z_out_func
+# define uInt z_uInt
+# define uIntf z_uIntf
+# define uLong z_uLong
+# define uLongf z_uLongf
+# define voidp z_voidp
+# define voidpc z_voidpc
+# define voidpf z_voidpf
+
+/* all zlib structs in zlib.h and zconf.h */
+# define gz_header_s z_gz_header_s
+# define internal_state z_internal_state
+
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+# define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+# define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+# ifndef WIN32
+# define WIN32
+# endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+# ifndef SYS16BIT
+# define SYS16BIT
+# endif
+# endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+# ifndef STDC
+# define STDC
+# endif
+# if __STDC_VERSION__ >= 199901L
+# ifndef STDC99
+# define STDC99
+# endif
+# endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+# define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
+# define STDC
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const /* note: need a more gentle solution here */
+# endif
+#endif
+
+#if defined(ZLIB_CONST) && !defined(z_const)
+# define z_const const
+#else
+# define z_const
+#endif
+
+#ifdef Z_SOLO
+ typedef unsigned long z_size_t;
+#else
+# define z_longlong long long
+# if defined(NO_SIZE_T)
+ typedef unsigned NO_SIZE_T z_size_t;
+# elif defined(STDC)
+# include <stddef.h>
+ typedef size_t z_size_t;
+# else
+ typedef unsigned long z_size_t;
+# endif
+# undef z_longlong
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus about 7 kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+#ifndef Z_ARG /* function prototypes for stdarg */
+# if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# define Z_ARG(args) args
+# else
+# define Z_ARG(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+# if defined(M_I86SM) || defined(M_I86MM)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+# if (defined(__SMALL__) || defined(__MEDIUM__))
+ /* Turbo C small or medium model */
+# define SMALL_MEDIUM
+# ifdef __BORLANDC__
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+ /* If building or using zlib as a DLL, define ZLIB_DLL.
+ * This is not mandatory, but it offers a little performance increase.
+ */
+# ifdef ZLIB_DLL
+# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+# ifdef ZLIB_INTERNAL
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+# endif
+# endif /* ZLIB_DLL */
+ /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+ * define ZLIB_WINAPI.
+ * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+ */
+# ifdef ZLIB_WINAPI
+# ifdef FAR
+# undef FAR
+# endif
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include <windows.h>
+ /* No need for _export, use ZLIB.DEF instead. */
+ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+# define ZEXPORT WINAPI
+# ifdef WIN32
+# define ZEXPORTVA WINAPIV
+# else
+# define ZEXPORTVA FAR CDECL
+# endif
+# endif
+#endif
+
+#if defined (__BEOS__)
+# ifdef ZLIB_DLL
+# ifdef ZLIB_INTERNAL
+# define ZEXPORT __declspec(dllexport)
+# define ZEXPORTVA __declspec(dllexport)
+# else
+# define ZEXPORT __declspec(dllimport)
+# define ZEXPORTVA __declspec(dllimport)
+# endif
+# endif
+#endif
+
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+# define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void const *voidpc;
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte const *voidpc;
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
+# include <limits.h>
+# if (UINT_MAX == 0xffffffffUL)
+# define Z_U4 unsigned
+# elif (ULONG_MAX == 0xffffffffUL)
+# define Z_U4 unsigned long
+# elif (USHRT_MAX == 0xffffffffUL)
+# define Z_U4 unsigned short
+# endif
+#endif
+
+#ifdef Z_U4
+ typedef Z_U4 z_crc_t;
+#else
+ typedef unsigned long z_crc_t;
+#endif
+
+#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
+# define Z_HAVE_UNISTD_H
+#endif
+
+#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */
+# define Z_HAVE_STDARG_H
+#endif
+
+#ifdef STDC
+# ifndef Z_SOLO
+# include <sys/types.h> /* for off_t */
+# endif
+#endif
+
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# ifndef Z_SOLO
+# include <stdarg.h> /* for va_list */
+# endif
+#endif
+
+#ifdef _WIN32
+# ifndef Z_SOLO
+# include <stddef.h> /* for wchar_t */
+# endif
+#endif
+
+/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
+ * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
+ * though the former does not conform to the LFS document), but considering
+ * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
+ * equivalently requesting no 64-bit operations
+ */
+#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
+# undef _LARGEFILE64_SOURCE
+#endif
+
+#ifndef Z_HAVE_UNISTD_H
+# ifdef __WATCOMC__
+# define Z_HAVE_UNISTD_H
+# endif
+#endif
+#ifndef Z_HAVE_UNISTD_H
+# if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32)
+# define Z_HAVE_UNISTD_H
+# endif
+#endif
+#ifndef Z_SOLO
+# if defined(Z_HAVE_UNISTD_H)
+# include <unistd.h> /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
+# ifdef VMS
+# include <unixio.h> /* for off_t */
+# endif
+# ifndef z_off_t
+# define z_off_t off_t
+# endif
+# endif
+#endif
+
+#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
+# define Z_LFS64
+#endif
+
+#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
+# define Z_LARGE64
+#endif
+
+#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
+# define Z_WANT64
+#endif
+
+#if !defined(SEEK_SET) && !defined(Z_SOLO)
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+#if !defined(_WIN32) && defined(Z_LARGE64)
+# define z_off64_t off64_t
+#else
+# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
+# define z_off64_t __int64
+# else
+# define z_off64_t z_off_t
+# endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+ #pragma map(deflateInit_,"DEIN")
+ #pragma map(deflateInit2_,"DEIN2")
+ #pragma map(deflateEnd,"DEEND")
+ #pragma map(deflateBound,"DEBND")
+ #pragma map(inflateInit_,"ININ")
+ #pragma map(inflateInit2_,"ININ2")
+ #pragma map(inflateEnd,"INEND")
+ #pragma map(inflateSync,"INSY")
+ #pragma map(inflateSetDictionary,"INSEDI")
+ #pragma map(compressBound,"CMBND")
+ #pragma map(inflate_table,"INTABL")
+ #pragma map(inflate_fast,"INFA")
+ #pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/zlib.3 b/zlib.3
new file mode 100644
index 0000000..6f6e914
--- /dev/null
+++ b/zlib.3
@@ -0,0 +1,149 @@
+.TH ZLIB 3 "13 Oct 2022"
+.SH NAME
+zlib \- compression/decompression library
+.SH SYNOPSIS
+[see
+.I zlib.h
+for full description]
+.SH DESCRIPTION
+The
+.I zlib
+library is a general purpose data compression library.
+The code is thread safe, assuming that the standard library functions
+used are thread safe, such as memory allocation routines.
+It provides in-memory compression and decompression functions,
+including integrity checks of the uncompressed data.
+This version of the library supports only one compression method (deflation)
+but other algorithms may be added later
+with the same stream interface.
+.LP
+Compression can be done in a single step if the buffers are large enough
+or can be done by repeated calls of the compression function.
+In the latter case,
+the application must provide more input and/or consume the output
+(providing more output space) before each call.
+.LP
+The library also supports reading and writing files in
+.IR gzip (1)
+(.gz) format
+with an interface similar to that of stdio.
+.LP
+The library does not install any signal handler.
+The decoder checks the consistency of the compressed data,
+so the library should never crash even in the case of corrupted input.
+.LP
+All functions of the compression library are documented in the file
+.IR zlib.h .
+The distribution source includes examples of use of the library
+in the files
+.I test/example.c
+and
+.IR test/minigzip.c,
+as well as other examples in the
+.IR examples/
+directory.
+.LP
+Changes to this version are documented in the file
+.I ChangeLog
+that accompanies the source.
+.LP
+.I zlib
+is built in to many languages and operating systems, including but not limited to
+Java, Python, .NET, PHP, Perl, Ruby, Swift, and Go.
+.LP
+An experimental package to read and write files in the .zip format,
+written on top of
+.I zlib
+by Gilles Vollant (info@winimage.com),
+is available at:
+.IP
+http://www.winimage.com/zLibDll/minizip.html
+and also in the
+.I contrib/minizip
+directory of the main
+.I zlib
+source distribution.
+.SH "SEE ALSO"
+The
+.I zlib
+web site can be found at:
+.IP
+http://zlib.net/
+.LP
+The data format used by the
+.I zlib
+library is described by RFC
+(Request for Comments) 1950 to 1952 in the files:
+.IP
+http://tools.ietf.org/html/rfc1950 (for the zlib header and trailer format)
+.br
+http://tools.ietf.org/html/rfc1951 (for the deflate compressed data format)
+.br
+http://tools.ietf.org/html/rfc1952 (for the gzip header and trailer format)
+.LP
+Mark Nelson wrote an article about
+.I zlib
+for the Jan. 1997 issue of Dr. Dobb's Journal;
+a copy of the article is available at:
+.IP
+http://marknelson.us/1997/01/01/zlib-engine/
+.SH "REPORTING PROBLEMS"
+Before reporting a problem,
+please check the
+.I zlib
+web site to verify that you have the latest version of
+.IR zlib ;
+otherwise,
+obtain the latest version and see if the problem still exists.
+Please read the
+.I zlib
+FAQ at:
+.IP
+http://zlib.net/zlib_faq.html
+.LP
+before asking for help.
+Send questions and/or comments to zlib@gzip.org,
+or (for the Windows DLL version) to Gilles Vollant (info@winimage.com).
+.SH AUTHORS AND LICENSE
+Version 1.2.13
+.LP
+Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler
+.LP
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+.LP
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+.LP
+.nr step 1 1
+.IP \n[step]. 3
+The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software
+in a product, an acknowledgment in the product documentation would be
+appreciated but is not required.
+.IP \n+[step].
+Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+.IP \n+[step].
+This notice may not be removed or altered from any source distribution.
+.LP
+Jean-loup Gailly Mark Adler
+.br
+jloup@gzip.org madler@alumni.caltech.edu
+.LP
+The deflate format used by
+.I zlib
+was defined by Phil Katz.
+The deflate and
+.I zlib
+specifications were written by L. Peter Deutsch.
+Thanks to all the people who reported problems and suggested various
+improvements in
+.IR zlib ;
+who are too numerous to cite here.
+.LP
+UNIX manual page by R. P. C. Rodgers,
+U.S. National Library of Medicine (rodgers@nlm.nih.gov).
+.\" end of man page
diff --git a/zlib.map b/zlib.map
new file mode 100644
index 0000000..b330b60
--- /dev/null
+++ b/zlib.map
@@ -0,0 +1,100 @@
+ZLIB_1.2.0 {
+ global:
+ compressBound;
+ deflateBound;
+ inflateBack;
+ inflateBackEnd;
+ inflateBackInit_;
+ inflateCopy;
+ local:
+ deflate_copyright;
+ inflate_copyright;
+ inflate_fast;
+ inflate_table;
+ zcalloc;
+ zcfree;
+ z_errmsg;
+ gz_error;
+ gz_intmax;
+ _*;
+};
+
+ZLIB_1.2.0.2 {
+ gzclearerr;
+ gzungetc;
+ zlibCompileFlags;
+} ZLIB_1.2.0;
+
+ZLIB_1.2.0.8 {
+ deflatePrime;
+} ZLIB_1.2.0.2;
+
+ZLIB_1.2.2 {
+ adler32_combine;
+ crc32_combine;
+ deflateSetHeader;
+ inflateGetHeader;
+} ZLIB_1.2.0.8;
+
+ZLIB_1.2.2.3 {
+ deflateTune;
+ gzdirect;
+} ZLIB_1.2.2;
+
+ZLIB_1.2.2.4 {
+ inflatePrime;
+} ZLIB_1.2.2.3;
+
+ZLIB_1.2.3.3 {
+ adler32_combine64;
+ crc32_combine64;
+ gzopen64;
+ gzseek64;
+ gztell64;
+ inflateUndermine;
+} ZLIB_1.2.2.4;
+
+ZLIB_1.2.3.4 {
+ inflateReset2;
+ inflateMark;
+} ZLIB_1.2.3.3;
+
+ZLIB_1.2.3.5 {
+ gzbuffer;
+ gzoffset;
+ gzoffset64;
+ gzclose_r;
+ gzclose_w;
+} ZLIB_1.2.3.4;
+
+ZLIB_1.2.5.1 {
+ deflatePending;
+} ZLIB_1.2.3.5;
+
+ZLIB_1.2.5.2 {
+ deflateResetKeep;
+ gzgetc_;
+ inflateResetKeep;
+} ZLIB_1.2.5.1;
+
+ZLIB_1.2.7.1 {
+ inflateGetDictionary;
+ gzvprintf;
+} ZLIB_1.2.5.2;
+
+ZLIB_1.2.9 {
+ inflateCodesUsed;
+ inflateValidate;
+ uncompress2;
+ gzfread;
+ gzfwrite;
+ deflateGetDictionary;
+ adler32_z;
+ crc32_z;
+} ZLIB_1.2.7.1;
+
+ZLIB_1.2.12 {
+ crc32_combine_gen;
+ crc32_combine_gen64;
+ crc32_combine_op;
+} ZLIB_1.2.9;
diff --git a/zlib.pc.cmakein b/zlib.pc.cmakein
new file mode 100644
index 0000000..a5e6429
--- /dev/null
+++ b/zlib.pc.cmakein
@@ -0,0 +1,13 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=@CMAKE_INSTALL_PREFIX@
+libdir=@INSTALL_LIB_DIR@
+sharedlibdir=@INSTALL_LIB_DIR@
+includedir=@INSTALL_INC_DIR@
+
+Name: zlib
+Description: zlib compression library
+Version: @VERSION@
+
+Requires:
+Libs: -L${libdir} -L${sharedlibdir} -lz
+Cflags: -I${includedir}